CMPT 295 - Unit - Machine-Level Programming

Lecture 20:

Last Lecture - x86-64 “register saving” convention

callee saved registers:

Register Note
%rbx  
%r12  
%r13  
%r14  
%r15  
%rbp parameters/arguments
%rsp return value

caller saved registers:

Register Note
%rax Return value
%rdi Parameters/arguments
%rsi Parameters/arguments
%rdx Parameters/arguments
%rcx Parameters/arguments
%r8 Parameters/arguments
%r9 Parameters/arguments
%r10  
%r11  

Last Lecture - x86-64 conventions and stack frame

M[] Stack Note
caller frame
caller saved regs caller frame
args 7 … n caller frame
return address caller frame
callee saved regs callee frame
%rsp/Top/local vars callee frame

Recursion in x86-64

Label M[] Stack
  Stack frame of 1st invocation of P
  Stack frame of 2nd invocation of P
top Stack frmae of 3rd invocation of P

Recursive Function – countOnesR(…)

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0){
    return 0;
  } else {
    return (x & 1) + countOnesR(x >> 1);
  }
}

What does this function do?

Recursive Function – Example – Base Case

C program:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0) //highlighted
    return 0; //highlighted
  else
    return (x & 1) + countOnesR(x >> 1);
}

Assembly:

countOnesR:
  xorl %eax, %eax #highlighted
  testq %rdi, %rdi #highlighted
  je done #highlighted
  pushq %rbx
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax
  popq %rbx
done: #highlighted
  ret #highlighted

Recursive Function – Example - Saving registers

C code:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0)
    return 0;
  else
    return (x & 1) + countOnesR(x >> 1);
}

Assembly:

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx #highlighted
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax
  popq %rbx #highlighted
done:
  ret

Recursive Function – Example - Call Setup

C code:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0)
    return 0;
  else
    return (x & 1) + countOnesR(x >> 1); // between the parenthasies are highlighted
}

Assembly code:

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx
  movq %rdi, %rbx #highlighted
  andl $1, %ebx #highlighted
  shrq %rdi #highlighted
  call countOnesR
  addq %rbx, %rax
  popq %rbx
done:
  ret

Recursive Function – Example – Recursive Call

C code:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0)
    return 0;
  else
    return (x & 1) + countOnesR(x >> 1);// countOnesR(x >> 1) is highlighted
}

Assembly:

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax
  popq %rbx
done:
  ret

Recursive Function – Example – Result

C code:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0)
    return 0;
  else
    return (x & 1) + countOnesR(x >> 1); // + is highlighted
}

Assembly:

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax #highlighted
  popq %rbx
done:
  ret

Recursive Function – Example – Clean-up and return

C code:

/* Recursive counter of 1’s */
long countOnesR(unsigned long x) {
  if (x == 0)
    return 0;
  else
    return (x & 1) + countOnesR(x >> 1);
}

Assembly:

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax
  popq %rbx
done:
  ret

Recursive Function – Example – Test Cases

countOnesR:
  xorl %eax, %eax
  testq %rdi, %rdi
  je done
  pushq %rbx
  movq %rdi, %rbx
  andl $1, %ebx
  shrq %rdi
  call countOnesR
  addq %rbx, %rax
  popq %rbx
done:
  ret
base + displacement Stack Variable
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   

Register table:

Register Value
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   

1D Array – in C

In C, arrays are also pointers!

Diagram of: int x[5];

Address/Variable Value
x 1
x+1 5
x+2 2
x+3 1
x+4 3
x+5 end of array
I want… Type Value of result
x[4] int  
x int *  
x+1 int *  
&x[2] int *  
x[5] int  
*(x+1) int  
x+i int *  

1D Array – in C and in x86-64

T A[n];

char x[12];

Name/Address Value
x  
   
   
   
   
   
   
   
   
   
   
x+?  

int x[5];

Name/Address Value
x  
   
   
   
x+?  
   

long x[3];

Name/Address Value
x  
x+?  
   
   

char *x[3];

Name/Address Value
x  
   
   
x+?  

We access arrays differently in x86-64 than in C!

Accessing 1D Array – in x86-64

1D Array – in x86-64

int x[5];

Name/Address Value
x 1
x+4 5
x+8 2
x+12 1
x+16 3
x+20 end of array
I want… Type Value of result (x86-64 instruction)
x[4] int  
x int *  
x+1 int *  
&x[2] int *  
x[5] int  
*(x+1) int  
x+i int *  

Manipulating 1D array – Example - main.c

This program defines 4 arrays:

then it calls the appropriate sum function, i.e., the one that sums elements of the correct data type.

#include <stdio.h>
#include <stdlib.h>

char sumChar(char*,int);
short sumShort(short*,int);
int sumInt(int*,int);
long sumLong(long*,int);

#define N 6

char AC[N] = {-58,22,101,-15,72,27}; // Expected results: sum = -107
short AS[N] = {-58,22,101,-15,72,27}; // Expected results: sum = 149
int AI[N] = {258,522,1010,-15,-3372,27};// Expected results: -1570
long AL[N] = {258,522,1010,-15,-3370,27}; // Expected results: -1570

int main(){
  printf("The total of AC is %hhi.\n", sumChar(AC, N));
  printf("The total of AS is %hi.\n", sumShort(AS, N));
  printf("The total of AI is %d.\n", sumInt(AI, N));
  printf("The total of AL is %ld.\n", sumLong(AL, N));
  return;
}

Manipulating 1D array – Example - sums.s - Part 1

sumChar assembly:

  .global sumChar
sumChar:
  movl $0,%eax
  movl $0,%ecx
loopChar:
  cmpl %ecx,%esi
  jle endloop1
  addb (%rdi,%rcx,1),%al
  incl %ecx
  jmp loopChar
endloop1:
  ret

sumShort assembly:

  .global sumShort
sumShort:
  xorl %eax,%eax
  xorl %ecx,%ecx
  jmp condl
loopShort:
  addw (%rdi,%rcx,2), %ax
  incl %ecx
condl:
  cmpl %esi,%ecx
  jne loopShort
  ret

Manipulating 1D array – Example - sums.s - Part 2

Register %rdi contains starting address of array (base address of array)

sumInt assembly:

  .global sumint
sumInt:
  xorl %eax,%eax
  xorl %ecx,%ecx
  jmp cond2
loopInt:
  addl (%rdi,%rcx,4),%eax
  incl %ecx
cond2:
  jmpl %esi,%ecx
  jne loopInt
  ret

sumLong in assembly:

  .global sumLong
sumLong:
  movq $0,%rax
  movl $0,%ecx
loopLoop:
  cmpl %ecx,%esi,
  jle endloop
  addq (%rdi,%rcx,8),%rax
  incl %ecx
  jmp loopLoop
endloop:
  ret

Warning!

Summary

Next Lecture