Search code examples
assemblyx86procedurecallstack

Getting Procedure Arguments from Stack


I am trying to learn how to call procedures in assembly language. Below is a simple example that shows my problem. I push 7 unto the stack, call the procedure; when the procudeure pops from the stack, the value is not the one I pushed. Can someone please help me understand what is happening and what I can do to make this work?

PUSH 7
CALL FOOBAR
MOV AH, 4CH
INT 21H

FOOBAR PROC
    POP AX ; Not 7
    RET
FOOBAR ENDP

Solution

  • The call instruction puts the return address on the stack, so when you pop ax in your procedure, it doesn't get the 7 you pushed, but the return address. The ret won't work, either (it expects to find the return address there!) try something like...

    FOOBAR proc
    push bp ; save caller's reg
    mov bp, sp
    mov ax, [bp + 4]
    ; do something with it
    ; leave - equivalent to:
    mov sp, bp
    pop bp
    
    ret
    

    There's a possible "gotcha" here. A "far" procedure has both the segment (cs) and offset on the stack, so 4 byes for the return address, and two bytes for the push bp puts the first parameter at [bp + 6]. I guess just proc defaults to proc near - you might want to say that, just for clarity. If you need a proc far it's probably time to graduate to 32-bit code (or 64-bit). 16-bit code is such a PITA - we're really glad to forget it! :)