Lecture 07 Assembly Arithmetic and Control

Joseph Haugh

University of New Mexico

Recall: Assembly/Machine Code View

  • Programmer-Visible State
    • PC: Address of next instruction
    • Register file: Temporary storage
    • Condition Codes: Special state for comparisons
    • Memory
      • Byte addressable array
      • Code and user data
      • Stack to support procedures

Simple Memory Addressing Modes

  • Normal (reg) M[R[reg]]
    • reg specifies memory address
    • Pointer dereferencing in C
    • movq (%rcx), %rax
  • Displacement D(reg) M[R[reg]+D]
    • reg specifies start of memory region
    • Constant displacement D specifies offset
    • movq 8(%rbp), %rdx

Practice: Problem 3.2 and 3.3

  • Problem 3.2: Fill in the blank
    • mov_ %eax, (%rsp)
    • mov_ (%rax), %dx
    • mov_ (%rdx), %rax
  • Problem 3.3: What is wrong with each
    • movl %rax, (%rsp)
    • movw (%rax), 4(%rsp)
    • movq %rax, $0x123

Practice: Problem 3.2 and 3.3

  • Problem 3.2: Fill in the blank
    • movl %eax, (%rsp)
    • movw (%rax), %dx
    • movq (%rdx), %rax
  • Problem 3.3: What is wrong with each
    • movl %rax, (%rsp) is 64 bit
    • movw (%rax), 4(%rsp) Memory to memory
    • movl %eax, $0x123 dest. cannot be immediate

Example: Simple Addressing Modes

void swap (long *xp, long *yp) 
{
  long t0 = *xp;
  long t1 = *yp;
  *xp = t1;
  *yp = t0;
}
swap:
   movq    (%rdi), %rax
   movq    (%rsi), %rdx
   movq    %rdx, (%rdi)
   movq    %rax, (%rsi)
   ret
  • More details on functions in sec. 3.7
  • For now just know that the first argument goes in %rdi and the second in %rsi

Understanding swap()

void swap (long *xp, long *yp) 
{
  long t0 = *xp;
  long t1 = *yp;
  *xp = t1;
  *yp = t0;
}

%rdi xp
%rsi yp
%rax t0
%rdx t1
swap:
   movq    (%rdi), %rax  # t0 = *xp  
   movq    (%rsi), %rdx  # t1 = *yp
   movq    %rdx, (%rdi)  # *xp = t1
   movq    %rax, (%rsi)  # *yp = t0
   ret

Understanding swap()

Understanding swap()

Understanding swap()

Understanding swap()

Understanding swap()

Complete Memory Addressing Modes

  • Most general form:
    • D(rb, ri, S) → M[R[rb] + S * R[ri] + D]
      • D: constant “displacement” of 1,2, or 4 bytes
      • rb: Base register, any of 16 integer registers
      • ri: Index register: any, except for %rsp
      • S: Scale: 1, 2, 4, or 8
  • Special Cases:
    • (rb, ri) → M[R[rb] + R[ri]]
    • D(rb, ri) → M[R[rb] + R[ri] + D]
    • (rb, ri, S) → M[R[rb] + S * R[ri]]

Practice: Address Computations

%rdx 0xf000
%rcx 0x0100
Expression Address Computation Address
$0x8(%rdx)
(%rdx,%rcx)
(%rdx,%rcx,4)
$0x80(,%rdx,2)

Practice: Address Computations

%rdx 0xf000
%rcx 0x0100
Expression Address Computation Address
$0x8(%rdx) 0xf000 + 0x8 0xf008
(%rdx,%rcx) 0xf000 + 0x100 0xf100
(%rdx,%rcx,4) 0xf000 + 4*0x100 0xf400
$0x80(,%rdx,2) 2*0xf000 + 0x80 0x1e080

Learning Objectives

  • After this session students should be able to:
    • Describe the data movement instructions (sec 3.4)
    • Describe arithmetic and logical instructions (sec 3.5)
    • Read assembly code containing move instructions as generated by a compiler

Operation Groups

  • load effective address: leaq (variant of movq)
  • unary operations
  • binary operations
  • shifts
  • All the operations are listed in figure 3.10

Address Computation Instruction

  • leaq S, D (does not refer to memory at all, copies effective address to D)
  • S is an address mode expression
  • Set D to address denoted by expression. Must be a register
  • Uses:
    • Computing addresses without a memory reference
      • E.g., translation of p = &x[i];
    • Computing arithmetic expressions of the form x + k*y
      • k = 1, 2, 4, or 8
  • Example:
long m12(long x) 
{
  return x * 12;
}
leaq (%rdi,%rdi,2), %rax # t <- x+x*2
salq $2, %rax            # return t<<2

Practice: Problem 3.6

%rax holds x and %rcx holds y

Instruction Result
leaq 6(%rax), %rdx
leaq (%rax,%rcx), %rdx
leaq (%rax,%rcx,4), %rdx
leaq 7(%rax,%rax,8), %rdx

Practice: Problem 3.6

%rax holds x and %rcx holds y

Instruction Result
leaq 6(%rax), %rdx 6 + x
leaq (%rax,%rcx), %rdx x + y
leaq (%rax,%rcx,4), %rdx x + 4y
leaq 7(%rax,%rax,8), %rdx 7 + 9x

Binary (two arg.) Arithmetic Operations

Format Operands Computation
addq Src, Dest Dest = Dest + Src
subq Src, Dest Dest = Dest - Src
imulq Src, Dest Dest = Dest * Src
salq Src, Dest Dest = Dest << Src (Also called shlq, 3 shifts use %cl)
sarq Src, Dest Dest = Dest >> Src (Arithmetic)
shrq Src, Dest Dest = Dest >> Src (Logical)
xorq Src, Dest Dest = Dest ^ Src
andq Src, Dest Dest = Dest & Src
orq Src, Dest Dest = Dest | Src

Unary Arithmetic Operations

Format Operands Computation
incq Dest Dest = Dest + 1
decq Dest Dest = Dest - 1
negq Dest Dest = -Dest
notq Dest Dest = ~Dest

Practice: Problem 3.8

Address Value Register Value
0x100 0xFF %rax 0x100
0x108 0xAB %rcx 0x1
0x110 0x13 %rdx 0x3
0x118 0x11
Instruction Destination Value
addq %rcx, (%rax)
subq %rdx, 8(%rax)
imulq $16, (%rax,%rdx,8)
incq 16(%rax)
decq %rcx
subq %rdx, %rax

Practice: Problem 3.8

Address Value Register Value
0x100 0xFF %rax 0x100
0x108 0xAB %rcx 0x1
0x110 0x13 %rdx 0x3
0x118 0x11
Instruction Destination Value
addq %rcx, (%rax) 0x100 0x100
subq %rdx, 8(%rax) 0x108 0xA8
imulq $16, (%rax,%rdx,8) 0x118 0x110
incq 16(%rax) 0x110 0x14
decq %rcx %rcx 0x0
subq %rdx, %rax %rax 0xFD

Practice: Problem 3.9

Suppose we want to generate assembly code for the following C function:

long shift_left4_rightn
    (long x, long n)
{
  x <<= 4;
  x >>= n;
  return x;
}

Assembly code that performs the actual shifts and leaves the final value in register %rax. Parameters x and n are stored in registers %rdi and %rsi, respectively.

  long shift_left4_rightn(long x, long n)
  x in %rdi, n in %rsi
shift_left4_rightn:
  movq    %rdi, %rax  Get x
  ______________  x <<= 4
  movl    %esi, %ecx  Get n (4 bytes)
  ______________  x >>= n

Fill in the missing instructions, following the annotations on the right. The right shift should be performed arithmetically.

Practice: Problem 3.9

Suppose we want to generate assembly code for the following C function:

long shift_left4_rightn
    (long x, long n)
{
  x <<= 4;
  x >>= n;
  return x;
}

Assembly code that performs the actual shifts and leaves the final value in register %rax. Parameters x and n are stored in registers %rdi and %rsi, respectively.

  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

Fill in the missing instructions, following the annotations on the right. The right shift should be performed arithmetically.

Practice: Problem 3.11

It is common to find assembly-code lines of the form:

xorq %rdx %rdx

In code that was generated from C where no exclusive-or operations were present.

  1. Explain the effect of this particular exclusive-or instruction and what useful operation it implements.
  2. What would be the more straightforward way to express this operation in assembly code?
  3. Compare the number of bytes to encode these two different implementations of the same operation.

Practice: Problem 3.11

It is common to find assembly-code lines of the form:

xorq %rdx %rdx

In code that was generated from C where no exclusive-or operations were present.

  1. Explain the effect of this particular exclusive-or instruction and what useful operation it implements.
  • Sets %rdx to 0
  1. What would be the more straightforward way to express this operation in assembly code?
  • movq $0 %rdx
  1. Compare the number of bytes to encode these two different implementations of the same operation.
  • xorq only requires 3 bytes whereas movq requires 7.

Example: Arithmetic Expression

long arith (long x, long y, long z) {
  long t1 = x+y;
  long t2 = z+t1;
  long t3 = x+4;
  long t4 = y * 48;
  long t5 = t3 + t4;
  long rval = t2 * t5;
  return rval;
}
arith:
  leaq    (%rdi,%rsi), %rax    # t1
  addq    %rdx, %rax           # t2
  leaq    (%rsi,%rsi,2), %rdx  # 3y
  salq    $4, %rdx             # t4 (y * 16)
  leaq    4(%rdi,%rdx), %rcx   # t5
  imulq   %rcx, %rax           # rval
  ret