views:

1014

answers:

11

If I have a program in C++/C that (language doesn't matter much, just needed to illustrate a concept):

#include <iostream>    

void foo() {
    printf("in foo");
}

int main() {
    foo();
    return 0;
}

What happens in the assembly? I'm not actually looking for assembly code as I haven't gotten that far in it yet, but what's the basic principle?

+1  A: 

Arguments are pushed in stack and "call" instruction is made

Call is a simple "jmp" with pushing an address of instruction into stack ("ret" in the end of a method popping it and jumping on it)

valya
Arguments are not necessarily pushed onto the stack. This depends a lot on architecture, calling convention, compiler, etc...
mrduclaw
+1  A: 

I think you want to take a look at call stack to get a better idea what happens during a function call: http://en.wikipedia.org/wiki/Call%5Fstack

vehomzzz
A: 

The common idea is that the registers that are used in the calling method are pushed on the stack (stack pointer is in ESP register), this process is called "push the registers". Sometimes they're also zeroed, but that depends. Assembly programmers tend to free more registers then the common 4 (EAX, EBX, ECX and EDX on x86) to have more possibilities within the function.

When the function ends, the same happens in the reverse: the stack is restored to the state from before calling. This is called "popping the registers".

Update: this process does not necessarily have to happen. Compilers can optimize it away and inline your functions.

Update: normally parameters of the function are pushed on the stack in reverse order, when they are retrieved from the stack, they appear as if in normal order. This order is not guaranteed by C. (ref: Inner Loops by Rick Booth)

Abel
+2  A: 

What happens in the assembly?

A brief explanation: The current stack state is saved, a new stack is created and the code for the function to be executed is loaded and run. This involves inconveniencing a few registers of your microprocessor, some frantic to and fro read/writes to the memory and once done, the calling function's stack state is restored.

dirkgently
A: 

1- a calling context is established on the stack

2- parameters are pushed on the stack

3- a "call" is performed to the method

jldupont
A: 

What happens? In x86, the first line of your main function might look something like:

call foo

The call instruction will push the return address on the stack and then jmp to the location of foo.

mrduclaw
+25  A: 

In general, this is what happens:

  1. Arguments to the function are stored on the stack. In platform specific order.
  2. Location for return value is "allocated" on the stack
  3. The return address for the function is also stored in the stack or in a special purpose CPU register.
  4. The function (or actually, the address of the function) is called, either through a CPU specific call instruction or through a normal jmp or br instruction (jump/branch)
  5. The function reads the arguments (if any) from the stack and the runs the function code
  6. Return value from function is stored in the specified location (stack or special purpose CPU register)
  7. Execution jumps back to the caller and the stack is cleared (by restoring the stack pointer to its initial value).

The details of the above vary from platform to platform and even from compiler to compiler (see e.g. STDCALL vs CDECL calling conventions). For instance, in some cases, CPU registers are used instead of storing stuff on the stack. The general idea is the same though

Isak Savo
Is the function's stack area really cleared in step 7, or is it just that the stack pointer in restored to its previous state? It seems like zeroing out the function's leftover stack memory every time would be rather inefficient...
Jeremy Friesner
No, typically the stack pointer (which is usually just a CPU register) is simply restored to its initial value (so this is a single CPU instruction). I've updated my answer to clarify this
Isak Savo
remembering: at x64 platform have single calling convention only.
lsalamon
Nope, x64 calling convention is different between most OSes (which use convention specified by AMD), and Windows (which uses its own different one).
Pavel Minaev
+6  A: 

You can see it for yourself:

Under Linux 'compile' your program with:

gcc -S myprogram.c

And you'll get a listing of the programm in assembler (myprogram.s).

Of course you should know a little bit about assembler to understand it (but it's worth learning because it helps to understand how your computer works). Calling a function (on x86 architecture) is basically:

  • put variable a on stack
  • put variable b on stack
  • put variable n on stack
  • jump to address of the function
  • load variables from stack
  • do stuff in function
  • clean stack
  • jump back to main

HTH, flokra

flokra
A: 

The general idea is that you need to

  1. Save the current local state
  2. Pass the arguments to a function
  3. Call the actual function. This involves putting the return address somewhere so the RET instruction knows where to continue.

The specifics vary from architecture to architecture. And the even more specific specifics might vary between various languages. Although there usually are ways of controlling this to some extent to allow for interoperability between different languages.

A pretty useful starting point is the Wikipedia article on calling conventions. On x86 for example the stack is almost always used for passing arguments to functions. On many RISC architectures, however, registers are mainly used while the stack is only needed in exceptional cases.

Joey
A: 

A very good illustration: http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.pdf

Tanuj
A: 

What happens?

C mimics what will occur in assembly...

It is so close to machine that you can realize what will occur

void foo() {
    printf("in foo");

/*

db mystring 'in foo'
mov eax, dword ptr mystring
mov edx , dword ptr _printf
push eax
call edx
add esp, 8
ret
//thats it
*/

}

int main() {
    foo();
    return 0;
}
Arabcoder
Aside: please stop your other spam / troll posts... they will just be deleted.
Marc Gravell