OMG x86 stack manipulation!!!

Started by
7 comments, last by Woodsman 19 years, 4 months ago
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 =)
Advertisement
push param1  ; NOTE: in Method 2 I assume these to be 2 byte values.push param2call mySub; Method 1mySub:    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 2mySub:    ; 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
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!
Glad it helped.
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

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

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 :-)
Sets the nesting level.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

What is it used for? I mean what effect would having a different nesting level have on the routine (or the leave instruction...)?
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
If a plant cannot live according to its nature, it dies; so a man.

This topic is closed to new replies.

Advertisement