Call and Return
The Art of Procedures and Functions

Today, we'll be looking at two new instructions: CALL A = Jump to the address A. RETN = Return to the address that was directly after the last CALL instruction used. As you can see, CALL is sort of pointless without RETN (using a jump would be easier). It is the "returning feature" that makes CALL so useful.
    Address   Instruction
    004937F4  MOV EDX,ECX
    004937F6  MOV EAX,EDX
    004937F8  CALL 00494000   ;jump to address 494000
    004937FD  INC EAX
    004937FE  CMP EAX,500
    00493803  JE 00450129

    ;pretend there is a lot of code inbetween here.

    00494000  ADD EAX,100
    00494005  ADD EDX,100
    0049400B  SUB ECX,60
    0049400E  RETN            ;Return to address 4937FD and execute INC EAX.
Here's a diagram of what the code is doing: You can use the CALL instruction to perform a certain action that you might want to repeat. Let's say you make the code at 494000 refill the player's health completely, then RETN back. The RETN will always go back to the right place (directly after the CALL 494000 you used). So you would be able to use CALL 494000 at any given time to refill the player's health, without having to worry about JMPing back to the right address, because RETN automatically does it for you. This type of CALL... RETN sequence is called a procedure, or even more fancy, a "subroutine". How CALL really works All right, the first definitions of CALL and RETN weren't explained fully. CALL and RETN require the stack: CALL A = Jump to the address A. Push the address of the instruction right after this CALL onto the stack. RETN = Pop the address on the top of the stack, then return to that address. Now you know that CALL and RETN both use the stack. So messing with the stack in the middle of a CALL would be bad, right? Indeed. Please DON'T do this:
    Address   Instruction
    004937F8  CALL 00494000      ;jump to address 494000
    004937FD  DEC EAX

    ;pretend there is a lot of code inbetween here.

    00494000  PUSH 200    ;pushes 200 onto the stack.
    00494005  RETN        ;Returns to the WRONG place: Address 200.
If you PUSH 200 before a RETN, the RETN doesn't know that the top of the stack is 200. It still thinks that the top of the stack is the "return address". So what does it do? It returns to address 200, which isn't even inside the Cave Story program! You just "returned" into a bunch of garbage. This is OKAY:
    Address   Instruction
    004937F8  CALL 00494000      ;jump to 494000
    004937FD  DEC EAX

    ;pretend there is a lot of code inbetween here.

    00494000  PUSH 200   ;push 200 onto the stack.
    00494005  POP EAX    ;removes the 200 and stores it into EAX, leaving the stack unmodified.
    00494006  RETN       ;return to the right place... address 004937FD.
Since you removed whatever you put on the stack before doing a Return, the RETN now works properly. Navigation Previous Lesson: Jump Instructions Next Lesson: Translating Ideas into ASM Table of Contents