Arithmetic and Logical Operations

Below are some of the more common integer and logic operations.

Instruction Effect Description
leaq    S,D D  <– S Load effective address
Unary Classes
inc    D D  <– D+1 Increment
dec   D D  <– D-1 Decrement
neg   D D  <–  -D Negate
not    D D  <–  ~D Complement
Arithmetic and Logic Classes
add   S,D D  <–  D + S Add
sub   S,D D  <– D – S Subtract
imul  S,D D  <–  D * S Multiply
xor S,D D <– D ^ S Exclusive OR
or   S,D D  <– D  |  S logical OR
and S, D D  <– D & S logical AND
Shift Classes
sal  k, D D  <– D  <<  k Left shift (fill with zeros)
shl  k, D D <– D << k Left shift (same as sal)
sar  k, D D  <–  D >>A k Arithmetic shift right (filled with most sig bit)
shr  k, D D <– D >>L k Logical shift right (zero filled)

Note: Each unary, binary and shift operation has 4 variants for each size: b, w, d, q.

Load Effective Address

  • leaq copies the value of S (not value at S) into D.

Examples

Suppose %rdx contains some value x.

leaq 7(%rdx, %rdx, 4), %rax      // copies 5x + 7 into %rax

7(%rdx, %rdx, 4) = (7 + x + 4x) = 5x + 7

Suppose %rax holds x and %rcx holds y.

leaq 9(%rax, %rcx, 2), %rdx    // copies 9 + x + 2y into %rdx

9(%rax, %rcx, 2) = 9 + x + 2y

leaq 0xA(,%rcx,4), %rdx    // copies 10 + 4y into %rdx

0xA(,%rcx,4) = 10+4y

Unary Ops

  • Operand serves as both source and destination
  • Operand can be register or memory location

Arithmetic and Logic Classes

  • The first operand can be an immediate value, register or memory location.
  • The second argument can only be a register or memory location.
  • They both can’t be memory locations

Shift Classes

  • The first operand is the shift amount. Can be an immediate value or the single-byte register %cl.  Note:  %cl can store the values 0 – 255.
  • The destination operand can be a register or memory address.

Example

long arith (long x, long y, long z) {
    long t1 = x ^ y;
    long t2 = z * 48;
    long t3 = t1 & 0x0F0F0F0F;
    long t4 = t2 - t3;
    return t4;
}

Assembly code

Note: x is in %rsi, y is in %rdi, z is in %rdx

arith:
    xorq    %rsi, %rdi                // t1 = x ^ y
    leaq    (%rdx, %rdx, 2), %rax     // 3 * z
    salq    $4, %rax                  // t2 = 16 * (3*z) = 48*z
    andl    $252645135, %edi          // t3 = t1 & 0x0F0F0F0F
    subq    %rdi, %rax                // return t2 - t3
    ret

Special Arithmetic Operations

When multiplying two 64-bit integers, the product may require 128 bit to represent the result.  The x86-64 instruction set provides limited support for operations involving 128-bit numbers.

Intel refers to a 16-byte quantity as an oct-word.

Instruction Effect Description
imulq    S R[%rdx]:R[%rax] <– S x R[%rax] Signed full multiply
mulq    S R[%rdx]:R[%rax] <– S x R[%rax] Unsinged full multiply
cqto R[%rdx]:R[%rax] <– SignExtend(R[%rax]) Convert to oct-word
idivq    S R[%rdx] <- R[%rdx]:R[%rax] mod S;

R[%rax] <- R[%rdx]:R[%rax] / S

Signed divide
divq    S R[%rdx] <- R[%rdx]:R[%rax] mod S;

R[%rax] <- R[%rdx]:R[%rax] / S

Unsigned divide

One-operand Multiply Instructions

  • Both imult and mulq expect one argument to already be in %rax.
  • %rdx holds the high order 64-bits
  • %rax holds the low order 64-bits

Signed Extension to Oct-word: cqto

  • takes no arguments
  • reads the sign bit from %rax and copies it accross %rdx
  • cqto is listed as cqo in the Intel documentation.

© 2017 – 2018, Eric. All rights reserved.