Presentation is loading. Please wait.

Presentation is loading. Please wait.

Programs – Calling Conventions

Similar presentations


Presentation on theme: "Programs – Calling Conventions"— Presentation transcript:

1 Programs – Calling Conventions
CS/COE 0449 (term 2174) Jarrett Billingsley

2 Class announcements Hi ;B We're gonna go down the rabbit hole today.
Stay with me. This stuff will be really useful to know for project 2. 2/16/2017 CS/COE term 2174

3 Review question time 2/16/2017 CS/COE term 2174

4 Calling Conventions 2/16/2017 CS/COE term 2174

5 So I just met you I'm sorry
We talked about the stack, how it's used to support function calls. When you call a function, we push an AR onto the stack. When it returns, its AR is popped. Remember what's in the AR? But what about the rest of the machinery? How do those parameters get in there? How does the stack pointer get moved around? How are values returned from the function? What responsibilities/protocols do functions have to follow to "play nice" with other code and with the OS? These and other questions are covered by calling conventions. 2/16/2017 CS/COE term 2174

6 Like I said at the beginning...
Our CPUs today are made to run C programs quickly. So naturally, they have built-in mechanisms to call and return from functions. Call instructions save the return address – the address of the instruction after the call – somewhere. Then they jump to the function being called. MIPS puts the return address in the $ra register. x86 pushes the return address onto the stack. Return instructions do the opposite. MIPS just uses "jump to register" to jump to the return address. x86 pops it off the stack, then jumps to it. MIPS x86 jal name call name jr $ra ret 2/16/2017 CS/COE term 2174

7 Passing parameters Here's where things get really wild.
How did you pass parameters into functions in MIPS? The $ax registers. But there are only 4. What if you have more than 4 params? The stack! x86-32 is ;)))))))))) Registers: eax, ebx, ecx, edx, esi, edi, ebp, esp ebp and esp are used for the stack and ARs (we'll see) So we have a whole six registers to use!!! How generous Over the years, MANY, MANY parameter passing conventions have arisen. Let's just look at one of the most common ones: cdecl. 2/16/2017 CS/COE term 2174

8 Parameter passing with cdecl
In cdecl, all parameters are pushed onto the stack, but in reverse order: the last parameter is pushed first. No really – it makes sense! What direction does the stack grow? If we call f(1, 2, 3), A cdecl function call might look like either of these: Stack 3 2 1 esp This would be like: sw 3, 8($sp) push 3 push 2 push 1 call f sub esp, 16 mov [esp+8], 3 mov [esp+4], 2 mov [esp], 1 2/16/2017 CS/COE term 2174

9 Peeking under the hood First let's write a little program to call a function. Now let's compile it, using these options: -g includes debugging info in the executable. This makes it easier to debug the program in gdb. -m32 compiles to 32-bit x86. If we leave this off we get x64 which EHGHHHCHA AAAAAAHHHHHHHHH Now let's run it, break at main, and disas...... Oh god. Oh no. OH GOD. This looks horrible. Let's make a file called ~/.gdbinit ~ is short for your home directory (the directory you start in). .gdbinit is sort of a settings file for gdb. In it, let's write set disassembly-flavor intel Save, and try again... 2/16/2017 CS/COE term 2174

10 Peeking under the much easier-to-read hood
Now let's see how main calls f with disas /m! The /m option will only show the C source if it's available. Won't work on your project ;))))))))))) Now let's look inside f to see how it computes its return value. Notice when it accesses the arguments, it uses [ebp+offs]. What the heck is ebp? And why is the first argument at offset 8 instead of 0? 2/16/2017 CS/COE term 2174

11 The stack frame register and { }
esp is the stack pointer. It marks the end of the AR. ebp – "base pointer" – marks the beginning* of the AR. When we first came into f, the call instruction just pushed the return address, so the stack looks like: Then we have this weird sequence that { does: push ebp mov ebp, esp The push saves the old value of ebp. The mov makes ebp point to that old ebp. And now.... uh um what did that do? Stack 3 2 1 return esp old ebp ebp 2/16/2017 CS/COE term 2174

12 pop ebp leave ret It's a linked list of ARs! Stack ??? _init's AR
ebp is the pointer to the head of a linked list. Every AR stores a pointer to the end of the AR of the function that called it. When the function is about to return, it does pop ebp This moves ebp back up to where it was before this function was called! If we put a local variable in f we'll see this: leave ret wha... Stack ??? _init's AR _init's ebp main's AR main's ebp f's AR f's ebp printf's AR ebp 2/16/2017 CS/COE term 2174

13 push ebp mov ebp, esp mov esp, ebp pop ebp The leave instruction
When we entered the function, we did: push ebp mov ebp, esp The x86 leave instruction is functionally identical to: mov esp, ebp pop ebp Which is the inverse. It moves both esp and ebp back to where they were when the function started. There is an enter instruction as well, which does the same thing as the push-mov on entry. x86 is full of silly instructions. Why did the compiler use leave but not enter? ¯\_(ツ)_/¯ 2/16/2017 CS/COE term 2174

14 Space for locals When we added a local to f, you'll notice the stuff at the beginning of the function – the prologue – changed a bit. Now there's an instruction that moves esp down (sub esp, 0x10). This is allocating space for the local variables! It's allocating 16 bytes for alignment reasons. (modern versions of x86 like the stack to be aligned like this. caches. SSE. etc.) Notice in the code, it refers to arguments with [ebp+offs] and the local variable with [ebp-offs]. Something to keep in mind... Locals could also be accessed with [esp+offs]. Sometimes it does it, sometimes it doesn't! I don't really know why! 2/16/2017 CS/COE term 2174

15 Returning Notice what the return statement assembles to.
It puts a value in eax. This is the convention in cdecl. What if the value is bigger than 4 bytes? What if it's a float SHHHH shhhhhhhhhh you don't wanna know shhhhhhhhhhhhhhhhh Then the function epilogue which we saw before moves the ebp pointer back to where they were when the function started, before returning. 2/16/2017 CS/COE term 2174

16 Loose ends Let's look at the stack, esp, and ebp through this whole process: In main, about to call f. In f, after the prologue. Just did ret, back in main. Just got into f. Stack old ebp Stack old ebp 3 2 1 ret. addr Stack old ebp 3 2 1 ret. addr main ebp Stack old ebp 3 2 1 ebp ebp ebp esp Uhh, is anyone gonna clean up this mess?? esp esp ebp esp 2/16/2017 CS/COE term 2174

17 Who cleans the stack? In cdecl it is the responsibility of the caller to put esp back to where it was before the call. (the compiler is being clever in main and relying on leave to clean up those arguments still sitting on the stack.) Why? In MIPS you did addi $sp, $sp, 24 before returning and it was great. Well, there ARE x86 calling conventions where the callee cleans, such as stdcall on windows. But C has this really weird feature that cdecl was created to support... Variadic functions. 2/16/2017 CS/COE term 2174

18 printf is very confused
Have you every really looked at the docs for printf? int printf(const char* format, ...); So there's an argument and then... maybe it's just being cryptic... Let's see what a call to printf looks like. So how does printf know, exactly, how many things you passed it? It... doesn't. The only information printf has about the parameters is the format string you give it as the first parameter. This is why the caller is responsible for cleaning the stack: because the callee has no idea how many parameters it was passed. This is why you can call functions without prototyping them first and they still "work." The caller knows how to clean up! 2/16/2017 CS/COE term 2174

19 Being a good roommate One last thing to consider: register use.
When main calls f, it might assume that some registers are unchanged. (For example, ebp and esp!) MIPS has a nice neat protocol: callee saves $sx registers before using them, and restores them before returning. In x86-32, ebx, edi, and esi should be saved and restored by the callee in the same way. ebp and esp are also saved and restored, in a different way. This means eax, ecx, and edx are free to be changed without saving them. You'll see these registers used for temporary values alllllllllll the time. 2/16/2017 CS/COE term 2174

20 WHYYYYYY???????? Why does all this stuff matter?
Everything your computer does is based on every function following this honor system. isn't that reassuring :^) If anyone messes up the convention, you get a crash. Even if you, the programmer, aren't writing assembly, the compiler has to. The compiler has to know how to call functions. 2/16/2017 CS/COE term 2174


Download ppt "Programs – Calling Conventions"

Similar presentations


Ads by Google