I just started tinkering with ASM and I'm not sure if my understanding of procedure calls is correct.
say at some point in the code there is a procedure call
call dword ptr[123]
and the procedure consists of only one command, ret:
ret 0004
what would be the effect of this procedure call, and where would the return value be stored? I read somewhere that a return value of 2 bytes would be stored in AX, but when I replace the procedure call by
mov AX, 0004
(together with the necessary NOPs) the program crashes.
we additionally decrease the ESP if we had pushed arguments in the stack prior calling the procedure.
If there are pushed arguments, your program crashes because you don't pop them. The return offset for the current procedure will be wrong since it will get a value from one of the pushed arguments as the offset.
in x86 assembler the parameter to the
ret
instruction means:RET immediate
(quoting from Intel® 64 and IA-32 Architectures Software Developer's Manuals Vol 2B)
So when you type:
You're telling the CPU to return to the instruction immediately after the
call
, and to pop 4 bytes off the stack. This is great if you pushed 4 bytes onto the stack before the call.Note that this has nothing to do with the return value. In fact, a procedure in Assembly has no way of specifying that a value is a return value. This is all done by convention. Most compilers of which I am aware will use
EAX
to hold the return value, but this is true only because the calling function will expect the result there.So your calling code would be:
and your function that returns the value 4 would be:
It all depends on the calling convention being used. I won't repeat the Wikipedia article here, just read the definition.
In the C calling convention, for example, the return value would be in EAX/AX/AL. Your single-instruction does not have one: It is a void function taking around 4 bytes of parameters (possibly a single int) that does nothing. As it is the callee's duty to clean up the stack in this calling convention, ignoring to do that and replacing the call with a 'mov ax' does not work.
Also I suspect you may be tinkering with 32-bit assembly while reading a 16-bit document. It's not a big problem, but you should be aware of the differences.
I don't think the return value is stored in the register AX