🎧 New: AI-Generated Podcasts Turn your study notes into engaging audio conversations. Learn more

Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Full Transcript

Assembly Language Programming II: C Compiler Calling Sequences 1 Homework • Reading – PAL, pp 201-216, 297-312 • Labs – Continue labs with your assigned section 2 Coding and Calling Functions • An assembly language programmer handles a lot of details to coordinate the code for calling a funct...

Assembly Language Programming II: C Compiler Calling Sequences 1 Homework • Reading – PAL, pp 201-216, 297-312 • Labs – Continue labs with your assigned section 2 Coding and Calling Functions • An assembly language programmer handles a lot of details to coordinate the code for calling a function and the code in the function itself • There are two mechanisms in the instruction set for calling and returning from functions: • Linux system calls and returns int $0x80 and iret (hardware saves eip, eflags) • C library style function calls and returns call and ret (hardware saves eip)3 Coding and Calling Functions • A really “old school” way to pass data back and forth between assembly language functions is to leave all data in “global memory” • This was really very efficient back when CPU’s were not very powerful and some did not have hardware supported stack mechanisms • Today we understand the software maintenance problem that this choice creates and the CPU’s are powerful enough for us to not need to do it 4 Coding and Calling Functions • A somewhat “old school” way to call functions: – Load up registers with input values before call – Unload return values from registers after return (if any) • This is still in use in Linux system calls, such as: # <unistd> write as a Linux system call movl $4, %eax # system call value movl $1, %ebx # file descriptor movl $output, %ecx # *buffer movl $len, %edx # length int $0x80 # call to system 5 Coding and Calling Functions • We won’t use the Linux system call and return mechanism in this course, but: – I feel that you should be aware of it and recognize it when the textbook uses it in an example – We’ll use the iret instruction later with hardware interrupts • We will use the call and ret mechanism as is typically used for C library function calls 6 main function in C • Example of a caller function in C: extern int mycode(int x, int y); int main(void){ … z = mycode(x, y); … } 7 Compiled output for main() # C compiler generated code for main: .text . . . pushl y pushl x call mycode addl $8, %esp movl %eax, z . . . .data # # # # # .long 0 # location for variable z put arg y on stack put arg x on stack call function mycode purge args from stack save return value z: 8 Function Written in C • Example of a callee function in C : int mycode(int x, int y) { /* automatic variables */ int i; int j; . . . return result; } 9 Function Written in Assembly • calling sequence discussed in later slides .text .globl mycode mycode: pushl %ebp movl %esp,%ebp subl $n,%esp .. . movl xxx, %eax # # # # # # entry point label set up stack frame save %esp in %ebp automatic variables code as needed set return value movl %ebp, %esp # restore %esp from %ebp popl %ebp # restore %ebp ret .end # return to caller 10 Writing Assembly Language functionsGeneral Coding Conventions • Use same function name as used in the calling C program • Setup C compiler stack frame (optional) • Use only %eax, %ecx, and %edx as scratch registers (see http://wiki.osdev.org/Calling_Conventions) • • • • Save/restore any other registers on stack if used Put return value in %eax Remove C compiler stack frame (optional) 11 Return Writing Assembly Language FunctionsCoding Conventions for callee • If function has arguments or automatic variables (that require n bytes), include this optional code • Assembly language after entry point label (enter): pushl %ebp movl %esp,%ebp subl $n,%esp # set up stack frame # save %esp in %ebp # automatic variables • Assembly language before ret (leave): movl popl %ebp, %esp %ebp # restore %esp from %ebp # restore %ebp 12 Stack Pointer For C Function Call • State of the stack during function execution: %esp before calling a lower function Lower level Functon Calls %eip … Lower Level Function Returns Low address %ebp j i Automatic Variables i = -4(%ebp) j = -8(%ebp) Arguments for calling a lower function %esp before setting up call Points to previous stack frame %esp before call _func %ebp %eip Return Address x = 8(%ebp) y = 12(%ebp) x y Argument Variables High address Writing Assembly Language functionsC Reserved registers • The C compiler assumes it can keep data in certain registers (%ebx, %ebp) when it generates code • If assembly code uses compiler’s reserved registers, it must save and restore the values for the calling C code • Example in the assembly function: Matching pair . . . pushl %ebx . . . popl %ebx . . . ret # # # # # we can’t use %ebx yet save register contents we can use %ebx now restore %ebx we can’t use %ebx any more 14 Code Demo 1 /* demo_fun1c.c: 2 Demo program for a C main calling an assembly function 3 C compiler expects ebp, ebx to be preserved 4 Ron Cheung 02/28/2015 5 */ 6 7 #include <stdio.h> 8 extern int add2(int a, int b); 9 int abc; 10 int a=0x10, b=0x20; 11 12 int main(void) 13 { 14 abc = add2(a, b); 15 printf("The sum is %d\n", abc); 16 return 0; 17 } 1 # demo_fun1.s:add 2 integers 2 # Need to preserve ebp 3 # Ron Cheung 02/28/2015 4 # 5 .text 6 .globl add2 7 add2: 8 # enter (setup stack frame) 9 pushl %ebp 10 movl %esp, %ebp 11 subl $8, %esp # pointer for local automatic 12 movl 8(%ebp), %eax # move a to eax 13 addl 12(%ebp), %eax # add b to eax 14 done: 15 # leave (remove stack frame) 16 movl %ebp, %esp 17 popl %ebp 18 ret 19 .end 15 Turning It Around • Calling a C function from Assembly Language – Can use printf to help debug assembly code (although it’s better to use either tutor or gdb as a debugger ) – Assume C functions “clobber” the contents of the %eax, %ecx, and %edx registers – If you need to save them across a C function call: • Push them on the stack before the call • Pop them off the stack after the return 16 Printing From Assembler • The C calling routine (helloc.c according to our convention) to get things going is: extern void hello(); int main(int argc, char ** argv) { hello(); return 0; } 17 Printing From Assembler • Assembly code to print Hello: .globl hello .text hello: pushl $hellostr # call printf # # addl $4, %esp # ret .data hellostr: .asciz “Hello\n” # .end pass string argument call printf from stdio.h to print the string restore stack printf format string 18 Printing from Assembler • Assembly code to use printf with a format statement and variable: x: format: . . . pushl pushl call addl . . . .long .asciz x $format printf $8, %esp # # # # x is a 32-bit integer pointer to format call C printf routine purge the arguments 0x341256 “x is: %d” 19 Preserving Compiler Scratch Registers • C compiler assumes that it can use certain registers when it generates code • A C function may or may not clobber the value of these registers • If assembly code needs to preserve the values of these registers across a C function call, it must save/restore their: . . . pushl call popl . . . %ecx cFunction %ecx # # # # # if ecx is in use save %ecx may clobber ecx restore %ecx ecx is OK again 20 Function Calling Summary • Passing information to functions in assembly – In global memory (Horrors!) – In registers (“old school” for assembly calling assembly) – On the stack (for C compatible functions) • For C compatible functions, the stack is used to hold: – Arguments – Return address – Previous frame’s %ebp value – Automatic variables – Saved values for other compiler used registers (if needed) • Passing information from function back to caller – In registers (%eax is C compiler return value convention) 21

Use Quizgecko on...
Browser
Browser