Sign in to follow this  
serratemplar

OMG x86 stack manipulation!!!

Recommended Posts

So I can do it with the ARM, and I know theoretically it's common practice, but I have no idea how to do it on the x86. I'm workin with a 16bit architecture here (legacy code is like that), so bear with me. I want to pass four values to a subroutine on the stack. So I do this
        PUSH    param1
        PUSH    param2
        PUSH    param3
        PUSH    param4

    ; note that each parameter is 2 bytes
now we got into the subroutine (woohoo!) and in the subroutine I backup my registers, do useful work, restore my registers, then kill the value parameters.
mySub:

        PUSH    AX
        PUSH    BX
        PUSH    CX

    ; do useful work HERE

        POP     CX
        POP     BX
        POP     AX

        RET     8       ; blow the value params off the stack
My question is this: how do I access my parameters?! On the ARM I can just treat the stack like an array that goes backwards, so it'd be like... LDR R1, [SP, #20] ...which says "20 bytes into the stack (added to the Stack Pointer) is where we'll find the first of our parameters...now load that into register R1" So what is the equivalent x86 notation? Anybody know? Thanks =)

Share this post


Link to post
Share on other sites


push param1 ; NOTE: in Method 2 I assume these to be 2 byte values.
push param2
call mySub


; Method 1
mySub:
pop ax ; Pop return address.
pop bx ; Pop param2
pop dx ; Pop param1
push ax ; Push return address back on stack

; Do useful work here.

ret

; Method 2
mySub:
; Setup stack frame.
push bp ; Save for later use.
mov bp, si ; Used to access parameters and local vars.

add si, x ; where x is the amount of bytes to reserve for locals variables (if any).

; Save registers.
push ax
push bx
push cx
push dx

mov ax, [bp+4] ; copy param1 to the ax register.
mov bx, [bp+2] ; copy param2 to the bx register.

; Do whatever work.

; Restore registers.
pop dx
pop cx
pop bx
pop ax

; Clean up stack frame.
mov si, bp ; clear local variables from stack.
add si, 4 ; clear 4 bytes (the params) from stack.
pop bp

ret



Method 1 is easier but does not allow for saving the registers (without some extra work), Method 2 is "the way to do it" though I may have made some mistakes.
I think that code will work, not entirely certain, I may have missed something here or there..

Anyway, hope that helps.

EDIT: Found this, thought it may be of use: clicky

Share this post


Link to post
Share on other sites
that is GREAT man...that appears to be, in x86 code, precisely the way I'd do it on the ARM. Thank you thank you thank you =) I'll let you know how well it works!

Share this post


Link to post
Share on other sites
Quote:
Original post by issch

various code


which could also be written for 286 and above.

myfunc:
enter x,0 ;create stack frame, reserve x bytes for locals
mov ax, [bp+4] ;last variable passed, left most variable for C calling convention.
xor ax, ax ;return code 0
leave ;destroy stack frame
ret

Share this post


Link to post
Share on other sites
Quote:
Original post by Washu

enter x,0


What does the second parameter to enter do?
Just thought I may as well update my knowledge while im at it :-)

Share this post


Link to post
Share on other sites
What is it used for? I mean what effect would having a different nesting level have on the routine (or the leave instruction...)?

Share this post


Link to post
Share on other sites
proc your_procedure_name
ARG arg1:WORD,arg2:WORD,....,argN:WORD
enter 0,0
;do some stuff
leave
ret 2xN;2 times the number of params you used


where enter 0,0 does the
push bp
mov bp,sp
and leave does
mov sp,bp
pop bp

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this