The instruction "call" is used to call another function. The function can then return using "ret" (call stores the return address to jump back to on the stack, which we'll talk about at the next lecture). Here's an example:
mov edi,7 ; pass a function parameter call otherFunction ; run the function below, until it does "ret" add eax,1 ; modify returned value ret otherFunction: ; a function "declaration" in assembly mov eax,edi ; return our function's only argument ret
this in NetRun now!)
Notice how a
function declaration in assembly looks exactly like a jump label.
The only real difference is you can get back from a function by
calling "ret" to return to whoever called you.
By default, the assembler assumes functions you call are defined later in the same file, like we did above. To call an external function, such as NetRun's "print_int", or a standard C library function like "exit", you need to tell the assembler the function is "extern". "extern" isn't actually an instruction--it doesn't show up in the disassembly--it's just a message to the assembler, often called a pseudoinstruction. In C++ or C, header files tend to contain declarations of extern functions, and so play the same role as extern in the assembler.
we'd call the UNIX function "exit",
which ends the program:
extern exit ; tell assembler function is defined elsewhere call exit ; call the function
(Try this in NetRun now!)
we'd call the standard C library function "getchar",
which reads one ASCII character from cin, and returns it in eax.
extern getchar call getchar ret
(Try this in NetRun now!)NetRun includes a couple of useful functions designed to be easy to call from assembly. For example, "read_input" parses an integer from cin, and returns it in eax (or rax):
extern read_input call read_input ; eax has the read-in integer now add eax,10000 ret
(Try this in NetRun now!)To show integers, "print_long" takes one long integer in edi (or rdi), and prints it on the screen:
mov edi, 17 ; function argument goes into print_long in edi (or rdi) extern print_long call print_long ret
(Try this in NetRun now!)One caution: if you call any function, that function has a perfect right to use eax, ecx, edx, esi, edi, and the other registers you can use. This makes it a little tricky to store data across a function call. For example, print_long will use eax, so this won't actually return 5:
mov eax, 5 ; I hope to return this mov edi, 3 ; function argument for print_long extern print_long call print_long ; CAUTION: print_long trashed eax! ret
this in NetRun now!)
is to save our registers before calling functions--we'll see how
to do this next lecture!