Download presentation
Presentation is loading. Please wait.
Published byHillary Cook Modified over 9 years ago
1
1 1 Machine-Level Programming IV: x86-64 Procedures, Data Andrew Case Slides adapted from Jinyang Li, Randy Bryant & Dave O’Hallaron
2
2 Today Procedures (x86-64) Arrays One-dimensional Multi-dimensional (nested) Multi-level Structures Allocation Access
3
3 x86-64 Registers Arguments passed to functions via registers If more than 6 integral parameters, then pass rest on stack These registers can be used as caller-saved as well All references to stack frame via stack pointer Eliminates need to update %ebp/%rbp
4
4 %rax %rbx %rcx %rdx %rsi %rdi %rsp %rbp x86-64 Integer Registers: Usage Conventions %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 Callee saved Caller saved Callee saved Stack pointer Caller Saved Return value Argument #4 Argument #1 Argument #3 Argument #2 Argument #6 Argument #5
5
5 x86-64 Long Swap Operands passed in registers First ( xp ) in %rdi, second ( yp ) in %rsi 64-bit pointers No stack operations required (except ret ) Can hold all local information in registers void swap_l(long *xp, long *yp) { long t0 = *xp; long t1 = *yp; *xp = t1; *yp = t0; } swap: movq(%rdi), %rdx movq(%rsi), %rax movq%rax, (%rdi) movq%rdx, (%rsi) ret
6
6 x86-64 Leaf call without Stack Frame Avoiding Stack Pointer Change 128 bytes after the %rsp is scratch space for functions (red zone). Only good for leaf-functions /* Swap, using local array */ void swap_a(long *xp, long *yp) { volatile long loc[2]; loc[0] = *xp; loc[1] = *yp; *xp = loc[1]; *yp = loc[0]; } swap_a: movq (%rdi), %rax movq %rax, -24(%rsp) movq (%rsi), %rax movq %rax, -16(%rsp) movq -16(%rsp), %rax movq %rax, (%rdi) movq -24(%rsp), %rax movq %rax, (%rsi) ret rtn Ptr unused %rsp −8−8 loc[1] loc[0] − 16 − 24 … 128 bytes
7
7 x86-64 NonLeaf call without Stack Frame Data stored in registers instead of stack /* Swap a[i] & a[i+1] */ void swap_ele(long a[], int i) { swap(&a[i], &a[i+1]); } swap_ele: movslq %esi,%rsi # Sign extend i leaq8(%rdi,%rsi,8), %rax# &a[i+1] leaq(%rdi,%rsi,8), %rdi# &a[i] (1 st arg) movq%rax, %rsi# (2 nd arg) callswap ret
8
8 x86-64 Stack Frame Example Keeps values of &a[i] and &a[i+1] in callee save registers Must set up stack frame to save these registers long sum = 0; /* Swap a[i] & a[i+1] */ void swap_and_sum(long a[], int i) { swap(&a[i], &a[i+1]); sum += (a[i]*a[i+1]); } Swap_and_sum: movq %rbx, -16(%rsp) movq%rbp, -8(%rsp) subq$16, %rsp movslq%esi, %rax leaq8(%rdi,%rax,8), %rbx leaq(%rdi,%rax,8), %rbp movq%rbx, %rsi movq%rbp, %rdi callswap movq(%rbx), %rax imulq(%rbp), %rax addq%rax, sum(%rip) movq(%rsp), %rbx movq8(%rsp), %rbp addq$16, %rsp ret
9
9 Understanding x86-64 Stack Frame Swap_and_sum: movq%rbx, -16(%rsp)# Save %rbx movq%rbp, -8(%rsp)# Save %rbp subq$16, %rsp# Allocate stack frame movslq%esi,%rax# Extend i leaq8(%rdi,%rax,8), %rbx# &a[i+1] (callee save) leaq(%rdi,%rax,8), %rbp# &a[i] (callee save) movq%rbx, %rsi# 2 nd argument movq%rbp, %rdi# 1 st argument callswap movq(%rbx), %rax# Get a[i+1] imulq(%rbp), %rax# Multiply by a[i] addq%rax, sum(%rip)# Add to sum movq(%rsp), %rbx# Restore %rbx movq8(%rsp), %rbp# Restore %rbp addq$16, %rsp# Deallocate frame ret
10
10 Understanding x86-64 Stack Frame rtn addr %rbp %rsp −8−8 %rbx − 16 rtn addr %rbp %rsp +8+8 %rbx movq%rbx, -16(%rsp)# Save %rbx movq%rbp, -8(%rsp)# Save %rbp subq$16, %rsp# Allocate stack frame movq(%rsp), %rbx# Restore %rbx movq8(%rsp), %rbp# Restore %rbp addq$16, %rsp# Deallocate frame
11
11 Interesting Features of Stack Frame Allocate entire frame at once All stack accesses can be relative to %rsp Do by decrementing stack pointer Can delay allocation, since safe to temporarily use red zone Simple deallocation Increment stack pointer No base/frame pointer needed
12
12 x86-64 Procedure Summary Heavy use of registers Parameter passing More temporaries using registers Minimal use of stack Sometimes none Allocate/deallocate entire frame at once All stack accesses can be relative to %rsp Usually no base/frame pointer needed
13
13 Today Procedures (x86-64) Arrays One-dimensional Multi-dimensional (nested) Multi-level Structures
14
14 Basic Data Types Integral Stored & operated on in general (integer) registers Signed vs. unsigned depends on instructions used IntelASMBytesC byte b 1[ unsigned ] char word w 2[ unsigned ] short double word l 4[ unsigned ] int quad word q 8[ unsigned ] long int (x86-64) Floating Point Stored & operated on in floating point registers IntelASMBytesC Single s 4 float Double l 8 double Extended t 10/12/16 long double
15
15 Array Allocation Basic Principle T A[ L ]; Array of data type T and length L Contiguously allocated region of L * sizeof( T ) bytes char string[12]; xx + 12 int val[5]; x x + 4x + 8x + 12x + 16x + 20 double a[3]; x + 24 x x + 8x + 16 char *p[3]; x x + 8x + 16 x + 24 x x + 4x + 8x + 12 IA32 x86-64
16
16 Array Access Basic Principle Type A[ Length ]; Identifier A can be used as a pointer to array element 0: Type T* x is the address of A ReferenceTypeValue val[4]int 3 valint * x val+1int * x + 4 &val[2]int * x + 8 val[5]int ?? *(val+1)int 5 val + i int * x + 4 i int val[5]; 15213 x =A x + 4x+ 8x + 12x + 16x + 20
17
17 Array Example Declaration “ zip nyu ” equivalent to “ int nyu[5] ” Example arrays were allocated in successive 20 byte blocks Not guaranteed to happen in general #define ZLEN 5 typedef int zip[ZLEN]; zip nyu = { 1, 0, 0, 0, 3 }; zip mit = { 0, 2, 1, 3, 9 }; zip nyu; 10003 16 2024283236 zip mit; 02139 36 4044485256
18
18 Array Accessing Example Store starting address of array in %edx (base) Store array index in %eax (index) Size of data type in multiplier Use memory reference (%edx,%eax,4): results in: %edx + 4*%eax (base pointer + index*size) int get_digit(zip z, int digit) { return z[digit]; } # %edx = z # %eax = digit movl (%edx,%eax,4),%eax # z[digit] IA32 zip nyu; 10003 16 2024283236
19
19 # edx = z movl$0, %eax# %eax = i.L4:# loop: addl$1, (%edx,%eax,4)# z[i]++ addl$1, %eax# i++ cmpl$5, %eax# i:5 (ZIP_LEN) jne.L4# if !=, goto loop Array Loop Example (IA32) void zip_inc(zip z) { int i; for (i = 0; i < ZIP_LEN; i++) z[i]++; }
20
20 2D Array: Example 2D array “Row-Major” ordering of all elements A[i][j] == *(A+i*C+j) int zips[4][5] = {{1, 0, 0, 0, 3}, {1, 0, 0, 1, 0 }, {1, 0, 0, 1, 1 }, {1, 0, 0, 0, 5 }}; 7696116136156 100031001010011 100 0 5 int A[R][C];
21
21 2D Array Element Access Code Array Elements zips[index][digit] is int Address: zips + 20*index + 4*digit int get_zip_digit(int index, int digit) { return zips[index][digit]; } movl8(%ebp), %eax# index leal(%eax,%eax,4), %eax# 5*index addl12(%ebp), %eax# 5*index+digit movlzips(,%eax,4), %eax# offset 4*(5*index+digit)
22
22 Array of pointers: Example Variable univ denotes array of 3 elements Each element is a pointer 4 bytes Each pointer points to array of int ’s zip nyu = { 1, 0, 0, 0, 3 }; zip mit = { 0, 2, 1, 3, 9 }; zip cmu = { 1, 5, 2, 1, 3}; #define UCOUNT 3 int *univ[UCOUNT] = {mit, nyu, cmu}; 36 160 16 56 164 168 univ nyu mit cmu 10003 16 2024283236 02139 4044485256 1 5 213 6064687276
23
23 Element Access in Multi-Level Array Computation (IA32) Element access Mem[Mem[univ+4*index]+4*dig] Must do two memory reads First get pointer to row array Then access element within array movl8(%ebp), %eax# index movluniv(,%eax,4), %edx# p = univ[index] movl12(%ebp), %eax# dig movl(%edx,%eax,4), %eax# p[digit] int get_univ_digit (int index, int digit) { return univ[index][digit]; }
24
24 Array Element Accesses int get_pgh_digit (int index, int dig) { return pgh[index][dig]; } int get_univ_digit (int index, int dig) { return univ[index][dig]; } Nested array Multi-level array Accesses looks similar in C, but addresses very different: Mem[pgh+20*index+4*dig] Mem[Mem[univ+4*index]+4*dig]
25
25 Today Procedures (x86-64) Arrays One-dimensional Multi-dimensional (nested) Multi-level Structures Allocation Access
26
26 struct rec { int a[3]; int i; struct rec *n; }; Structure Allocation Concept Contiguously-allocated region of memory Offset of each struct member determined at compile time Refer to members within structure by names Members may be of different types Memory Layout ian 0 12 16 20
27
27 struct rec { int a[3]; int i; struct rec *n; }; IA32 Assembly # %edx = val # %eax = r movl %edx, 12(%eax) # Mem[r+12] = val void set_i(struct rec *r, int val) { r->i = val; } Structure Access Accessing Structure Member Pointer indicates first byte of structure Access elements with offsets ian 0 12 16 20 r+12r
28
28.L17:# loop: movl12(%edx), %eax# r->i movl%ecx, (%edx,%eax,4)# r->a[i] = val movl16(%edx), %edx# r = r->n testl%edx, %edx# Test r jne.L17# If != 0 goto loop void set_all_a_i_values (struct rec *r, int val) { while (r) { int i = r->i; r->a[i] = val; r = r->n; } Following Linked List struct rec { int a[3]; int i; struct rec *n; }; ian 0 12 16 20 Element i RegisterValue %edxr %ecxval
29
29 Summary Procedures in x86-64 Stack frame is relative to stack pointer Parameters passed in registers Arrays One-dimensional Multi-dimensional (nested) Multi-level Structures Allocation Access
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.