To learn how to write functions and procedures in Assembly Language, along with an understanding of how to pass parameters to functions and procedures in Assembly Language, and returning values from functions and procedures in Assembly Language.
Working with functions and procedures in Assembly Language is quite similar to how one works with functions and procedures in a high level language. There is the function/procedure name, parameters to pass to the function/procedure, and a return_value from the function/procedure if there is one.
Parameters can be passed to functions/procedures by_value or by_reference. Global variables in the program can also be accessed by functions and procedures. In assembly language, parameters whether they are passed by_value or by_reference can be passed with the value or reference in a register or pushed onto the stack. It is considered good practice with passing the data in registers for 64 bit architectures rather than passing on the stack for consideration of not worrying about performance issues when the stack values are not lined up on 64 bit memory bus boundaries. All examples are done with NASM.
... ; code before the call
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
... ; do code for function here
ret ; return from the function back to the calling code
... ; code before the call
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
... ; do code for function here
ret ; return from the function back to the calling code
section .data
some_val dd 5
some_val2 dd 6
result dd 0
ret_val dd 0
section .text
global main
main:
mov eax, some_val ; this example has some_val being passed by value in eax register
lea esi, [some_val2]; esi contains the pointer to some_val2, being passed by reference
lea edi, [result] ; edi contains the pointer to variable named result, passed by reference
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
add eax, [esi] ; get the content pointed by esi, and add it to eax, this is: eax = eax + &esi in a C/C++ way of things
mov [edi], eax ; store value of eax in memory location pointed by edi.
ret ; return from the function back to the calling code
section .data
some_val dd 5
some_val2 dd 6
sum dd 0
ret_val dd 0
section .text
global main
main:
mov eax, [some_val] ; load [some_val] value into eax
push eax ; this example has some_val being passed by value pushed on the stack
lea eax, [some_val2]; esi contains the pointer to some_val2, being passed by reference
push eax ; push memory address pointed by esi onto stack
lea eax, [sum] ; edi contains the pointer to variable named result, passed by reference
push eax ; push memory address pointed by edi onto stack
call some_function ; call some_function
add esp, 12 ; 12 bytes were pushed on stack, readjust stack pointer to remove them
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
push ebp ; set up stack frame
mov ebp, esp ; ebp points to the stack pointer
mov eax, [ebp+16] ; [ebp+12] contains the value of eax passed on the stack
mov esi, [ebp+12] ; esi points to memory address of second parameter
mov edi, [ebp+8] ; edi points to memory address of third parameter
add eax, [esi] ; add eax to value pointed by esi
mov [edi], eax ; store value of eax in memory location pointed by [edi].
pop ebp ; restore old base pointer
ret ; return from the function back to the calling code
section .data
some_val dq 5
some_val2 dq 6
sum dq 0
ret_val dq 0
section .text
global main
main:
mov rbp, rsp; for correct debugging
mov rax, [some_val] ; this example has some_val being passed by value in rax register
lea rsi, [some_val2]; esi contains the pointer to some_val2, being passed by reference
lea rdi, [sum] ; edi contains the pointer to variable named result, passed by reference
call some_function ; call some_function
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
add rax, [rsi] ; get the content pointed by rsi, and add it to rax, this is: rax = rax + &rsi in a C/C++ way of things
mov [rdi], rax ; store value of rax in memory location pointed by rdi.
ret ; return from the function back to the calling code
section .data
some_val dq 5
some_val2 dq 6
sum dq 0
ret_val dq 0
section .text
global main
main:
mov rax, [some_val]
push rax ; this example has some_val being passed by value pushed on the stack
lea rax, [some_val2]; rax contains the pointer to some_val2, being passed by reference
push rax ; push memory address pointed by rax onto stack
lea rax, [sum] ; rax contains the pointer to variable named result, passed by reference
push rax ; push memory address pointed by rax onto stack
call some_function ; call some_function
add rsp, 24 ; clear out the stack, we pushed 24 bytes onto stack, adding 24 to rsp "pops" the 24 bytes off stack
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
push rbp
mov rbp, rsp
mov rax, [rbp+32] ; [rbp+32] contains the value of rax passed on the stack
mov rsi, [rbp+24] ; [rbp+24] contains the value of second parameter pointer passed on the stack
mov rdi, [rbp+16] ; [rbp+16] contains the value of third parameter pointer passed on the stack
add rax, [rsi] ; add content of [rsi] to rax
mov [rdi], rax ; store value of rax in memory location pointed by [rdi].
pop rbp
ret ; return from the function back to the calling code
... ; code before the call
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
... ; do code for function here
mov eax, a_ret_val ; returns a_ret_val as the return value
ret ; return from the function back to the calling code
... ; code before the call
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
... ; do code for function here
mov rax, a_ret_val ; returns a_ret_val as the return value
ret ; return from the function back to the calling code
... ; code before the call
mov eax, some_val ; this example has some_val being passed by value in eax register
lea esi, [some_val2]; esi contains the pointer to some_val2, being passed by reference
lea edi, [result] ; edi contains the pointer to variable named result, passed by reference
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
add eax, [esi] ; get the content pointed by esi, and add it to eax, this is: eax = eax + &esi in a C/C++ way of things
ret ; return from the function back to the calling code, eax is the return value
... ; code before the call
push some_val ; this example has some_val being passed by value pushed on the stack
lea esi, [some_val2]; esi contains the pointer to some_val2, being passed by reference
push esi ; push memory address pointed by esi onto stack
lea edi, [result] ; edi contains the pointer to variable named result, passed by reference
push edi ; push memory address pointed by edi onto stack
call some_function ; call some_function
... ; code after the call, you have the corresponding pops from the above pushes here IF the function does not
; remove them. It is important to have functions be documented as to how they behave and do any clean up
... ; code after the call
mov eax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
mov eax, [ebp+12] ; [ebp+12] contains the value of eax passed on the stack
add eax, [ebp+8] ; add content of [ebp+8] to eax, and content of eax is returned to calling code as return value
ret ; return from the function back to the calling code
... ; code before the call
mov rax, some_val ; this example has some_val being passed by value in rax register
lea rsi, [some_val2]; esi contains the pointer to some_val2, being passed by reference
lea rdi, [result] ; edi contains the pointer to variable named result, passed by reference
call some_function ; call some_function
... ; code after the call
... ; code after the call
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
add rax, [rsi] ; get the content pointed by rsi, and add it to rax, this is: rax = rax + &rsi in a C/C++ way of things
ret ; return from the function back to the calling code, with return value in rax
... ; code before the call
push some_val ; this example has some_val being passed by value pushed on the stack
lea rsi, [some_val2]; rsi contains the pointer to some_val2, being passed by reference
push rsi ; push memory address pointed by rsi onto stack
lea rdi, [result] ; rdi contains the pointer to variable named result, passed by reference
push rdi ; push memory address pointed by rdi onto stack
call some_function ; call some_function
... ; code after the call, you have the corresponding pops from the above pushes here IF the function does not
; remove them. It is important to have functions be documented as to how they behave and do any clean up
... ; code after the call
mov rax, ret_val ; main should have a return value, in place of whatever ret_val is
ret ; return from your main
some_function: ; some_function label (in MASM, you would use some_function proc, with some_function endp after the code block)
mov rax, [rbp+24] ; [rbp+24] contains the value of rax passed on the stack
add rax, [rbp+16] ; add content of [rbp+16] to rax
ret ; return from the function back to the calling code, with return value in rax
. . . . . . . . . ( end of section Assembly Language Functions and Procedures) <<Contents | Index>>