Skip to content

Arithmetic and Logical Operations

Integer arithmetic operations .

Load Effective Address

  • The instruction leaq is actually a variant of the movq instruction (from memory - register). But the difference is:
    • movq is used for moving the actual data. It copies the value from the source operand to the destination operand.
    • leaq is used for calculating effective addresses. It computes the address specified by the source operand and stores it in the destination operand.
  • Example:
movq (%rsi), %rdi # Loads a byte from location specified by the content of %rsi into the %rdi register.
leaq (%rax, %rbx, 8), %rdi # Calculate the effective address (%rax + 8 * %rbx) and stores the result (address) in the %rdi register.
Note that `leaq` doesn't actually access the data at that address.
  • Example 2: suppose register %rbx holds value p and %rdx holds value q.
InstructionResult
leaq 9(%rdx), %rax9+q
leaq (%rdx, %rbx), %raxp+q
leaq (%rdx, %rbx, 3), %rax3p+q
leaq 2(%rbx, %rbx, 7), %rax8p+2
leaq 0xE(,%rdx,3), %rax3q+14
leaq 6(%rbx,%rdx, 7), %rax7q+p+6
  • Real-world usage illustration: consider the following program
    long scale(long x, long y, long z) {
    long t = x + 4*y + 12*z;
    return t;
    }
    • When compiled, the arithmetic operations of the function are implemented by a sequence of 3 leaq functions:
    long scale(long x, long y, long z)
    x in %rdi, y in %rsi, z in %rdx
    //
    scale:
    leaq (%rdi, %rsi, 4), %rax // x + 4y
    leaq (%rdx, %rdx, 2), %rdx // z + 2*z = 3z
    leaq (%rax, %rdx, 4), %rax // x + 4y + 12z

Unary and Binary Operations

  • First operand: can be an immediate, a register or a memory location
  • Second operand: can be a register, or a memory location.

Example: subq %rax, %rdx - “Subtract %rax from %rdx”

  • Registers contains these addresses:

    RegisterValue
    %rax0x100
    %rcx0x1
    %rdx0x3
  • These address contains these hex value:

    AddressValue
    0x1000xFF
    0x1040xAB
    0x1100x13
    0x1180x11
  • The following table shows the effects of the instructions:

    InstructionDestinationValue
    addq %rcx, %(rax)0x1000x100
    subq %rdx, 8(%rax)0x1080xA8
    imulq $16, (%rax, %rdx, 8)0x1180x110
    incq 16(%rax)0x1100x14
    decq %rcx%rcx0x0
    subq %rdx, %rax%rax0xFD

Shift operations

  • The shift amount either as an immediate value or with the single-byte register %cl. This 8-bit register can represent 0 -> 255.

In x86-64 assembly language, the shift instructions (salb, salw, sall, salq) all use the %cl register as the source of the shift count. The size of the data being shifted determines the effective shift count, and it is not directly related to the value in %cl.

  • salb: Shifts a byte (8 bits) left by the value in the low-order 3 bits of %cl.
  • salw: Shifts a word (16 bits) left by the value in the low-order 4 bits of %cl.
  • sall: Shifts a long (32 bits) left by the value in the low-order 5 bits of %cl.
  • salq: Shifts a quad-word (64 bits) left by the value in the low-order 6 bits of %cl.

So, if %cl has a hexadecimal value of 0xFF (binary: 11111111), the effective shift counts would be:

  • For salb: 7 (since %cl is 8 bits, but only the low-order 3 bits are considered).
  • For salw: 15 (considering the low-order 4 bits).
  • For sall: 31 (considering the low-order 5 bits).
  • For salq: 63 (considering the low-order 6 bits).

Example 2: generate assembly code for the following C function:

long shift_left4_rightn(long x, long n) {
x <<= 4;
x >>= n;
return x;
}
  • Generated assembly code:
long shift_left4_rightn(long x, long n)
x in %rdi, n in %rsi
shift_left4_rightn:
movq %rdi, %rax //Get x
salq $4, %rax // x <<= 4
movl %esi, %ecx //Get n (4 bytes)
sarq %cl, %rax // x >>= n