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. Previous Lesson: Jump Instructions Next Lesson: Translating Ideas into ASM Table of Contents |