Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Question on stack frame

shaolin007shaolin007 Member Posts: 1,018
Could someone break it down for me? I was reading up on it and I took that it was used for just saving variables on the stack for functions, but can't you just use a regular push to do that? Why create a stack frame?

Comments

  • abhijitpaiabhijitpai Member Posts: 23
    A stack frame is generally used when you have nested subroutines. You will be using a general purpose register as the frame pointer. The advantage here is that in whichever current subroutine you are running, you can easily access the parameters on the stack using positive offsets and local variables (on the stack) by using negetive offsets. These two types of variables will be immediately adjacent (on either side) to your frame pointer, and you do not have to try hard to calculate what the offsets might be.


    : Could someone break it down for me? I was reading up on it and I took that it was used for just saving variables on the stack for functions, but can't you just use a regular push to do that? Why create a stack frame?
    :
    :

  • AsmGuru62AsmGuru62 Member Posts: 6,519
    : A stack frame is generally used when you have nested subroutines. You will be using a general purpose register as the frame pointer. The advantage here is that in whichever current subroutine you are running, you can easily access the parameters on the stack using positive offsets and local variables (on the stack) by using negetive offsets. These two types of variables will be immediately adjacent (on either side) to your frame pointer, and you do not have to try hard to calculate what the offsets might be.
    :
    :
    : : Could someone break it down for me? I was reading up on it and I took that it was used for just saving variables on the stack for functions, but can't you just use a regular push to do that? Why create a stack frame?
    : :
    : :
    :
    :
    [blue]The phrase "creating stack frame" is just a name for a few ASM opcodes - it does not mean that you loosing speed of your code in a great deal - just a few CPU clocks...

    PUSH/POP requires quite an attention to your code - example: you have a complex loop where you decided to save something on stack with PUSH - when you exit that loop you usually forget to POP it back and stack becomes unblanced until CPU reaches instruction RET - which now points not to return address, but to your variable and OOPS! - the CPU will go wandering through the invalid codes until it encounteres something which cannot be processed - and you get an exception (Win32) or undefined behaviour (DOS).

    So, it is much more convenient to use a simple local variable to store something inside the function - as you do in High Level Languages. In fact, without using local vars - it is very hard to write a large application in ASM.[/blue]
  • shaolin007shaolin007 Member Posts: 1,018
    : : A stack frame is generally used when you have nested subroutines. You will be using a general purpose register as the frame pointer. The advantage here is that in whichever current subroutine you are running, you can easily access the parameters on the stack using positive offsets and local variables (on the stack) by using negetive offsets. These two types of variables will be immediately adjacent (on either side) to your frame pointer, and you do not have to try hard to calculate what the offsets might be.
    : :
    : :
    : : : Could someone break it down for me? I was reading up on it and I took that it was used for just saving variables on the stack for functions, but can't you just use a regular push to do that? Why create a stack frame?
    : : :
    : : :
    : :
    : :
    : [blue]The phrase "creating stack frame" is just a name for a few ASM opcodes - it does not mean that you loosing speed of your code in a great deal - just a few CPU clocks...
    :
    : PUSH/POP requires quite an attention to your code - example: you have a complex loop where you decided to save something on stack with PUSH - when you exit that loop you usually forget to POP it back and stack becomes unblanced until CPU reaches instruction RET - which now points not to return address, but to your variable and OOPS! - the CPU will go wandering through the invalid codes until it encounteres something which cannot be processed - and you get an exception (Win32) or undefined behaviour (DOS).
    :
    : So, it is much more convenient to use a simple local variable to store something inside the function - as you do in High Level Languages. In fact, without using local vars - it is very hard to write a large application in ASM.[/blue]
    :
    [green] So from what I understand, correct me if I'm wrong, a stack frame is utilized everytime a variable is defined in a higher level language within a function up to and including the c main function. How would it be used in a external variable, the same way? Should you try and preserve any other registers besides ESP & EBP, like EBX,EDI, or ESI?[green]
  • _codist__codist_ Member Posts: 17
    [b][red]This message was edited by _codist_ at 2004-9-13 11:46:22[/red][/b][hr]
    : : : A stack frame is generally used when you have nested subroutines. You will be using a general purpose register as the frame pointer. The advantage here is that in whichever current subroutine you are running, you can easily access the parameters on the stack using positive offsets and local variables (on the stack) by using negetive offsets. These two types of variables will be immediately adjacent (on either side) to your frame pointer, and you do not have to try hard to calculate what the offsets might be.
    : : :
    : : :
    : : : : Could someone break it down for me? I was reading up on it and I took that it was used for just saving variables on the stack for functions, but can't you just use a regular push to do that? Why create a stack frame?
    : : : :
    : : : :
    : : :
    : : :
    : : [blue]The phrase "creating stack frame" is just a name for a few ASM opcodes - it does not mean that you loosing speed of your code in a great deal - just a few CPU clocks...
    : :
    : : PUSH/POP requires quite an attention to your code - example: you have a complex loop where you decided to save something on stack with PUSH - when you exit that loop you usually forget to POP it back and stack becomes unblanced until CPU reaches instruction RET - which now points not to return address, but to your variable and OOPS! - the CPU will go wandering through the invalid codes until it encounteres something which cannot be processed - and you get an exception (Win32) or undefined behaviour (DOS).
    : :
    : : So, it is much more convenient to use a simple local variable to store something inside the function - as you do in High Level Languages. In fact, without using local vars - it is very hard to write a large application in ASM.[/blue]
    : :
    : [green] So from what I understand, correct me if I'm wrong, a stack frame is utilized everytime a variable is defined in a higher level language within a function up to and including the c main function. How would it be used in a external variable, the same way? Should you try and preserve any other registers besides ESP & EBP, like EBX,EDI, or ESI?[/green]
    :
    If a function programmed in a higher level language (or at least in C, I haven't checked for other languages up to now) calls another function, first it pushes the arguments on the stack (in reverse order), then it executes the call (which pushes the current value of the instruction pointer to the stack and loads the instruction pointer with the offset of the function that is called).
    The called function itself begins with pushing ebp on the stack and copying esp in ebp. If the function contains local variables, the appropriate size in bytes is then substracted from esp to spawn the stack frame. The the stack looks now as follows (top of stack (pointed to by esp) is left, higher memory addresses are right)

    |local variables,if any|old value of ebp|old value of ip|args,if any|

    while ebp points to the beginning of the old value it had before being pushed.
    That way, local variables can be accessed adding negative numbers to ebp, and args can be accessed adding positive values to ebp.

    When the function is done, it ends by copying the value of ebp to esp, so the local variables are removed from the stack. Then, the old value of ebp (now located at top of stack) is popped to ebp, and ret is executed (popping the old value back in the instruction pointer).

    The function that has called is continued cleanly this way, and the stack is back to the state it had before the call was executed: with the args on top of it. It's up to the calling function to remove them now.

    So, only ebp and esp are used to create a stack frame, no other registers need to be taken care of. Stack frames are only used for local variables, global and static variables are located in the data segment (if they are initialized) or in the bbs segment (if they're uninitialized).


  • shaolin007shaolin007 Member Posts: 1,018
    [red]If a function programmed in a higher level language (or at least in C, I haven't checked for other languages up to now) calls another function, first it pushes the arguments on the stack (in reverse order).[/red]
    [green]
    Ahh so,

    void function(int , char, int[])

    the int[] is pushed 1st, then char, and then int.[/green]

  • AsmGuru62AsmGuru62 Member Posts: 6,519
    : [red]If a function programmed in a higher level language (or at least in C, I haven't checked for other languages up to now) calls another function, first it pushes the arguments on the stack (in reverse order).[/red]
    : [green]
    : Ahh so,
    :
    : void function(int , char, int[])
    :
    : the int[] is pushed 1st, then char, and then int.[/green]
    :
    :
    [blue]The order of parameters and who cleans up the stack after the call depends on a calling convention the types of which you can find here:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_argument_passing_and_naming_conventions.asp

    [/blue]
  • CroWCroW Member Posts: 348
    in most calling conventions arrays are passed as a pointer to it(or a pointer to a copy of the array).16 bit values (or 32 bit ones in protected mode) are pushed to the stack.

    return-values are passed through (E)AX,floats in fpu-register ST(0) and arrays as pointer DS:DX.however,in most calling-conventions,not in all.some (like fastcall) are dont use the stack at all,they pass arguments through registers
Sign In or Register to comment.