function, enable program broken into pieces, so that for reuse & easy to maintain,
------
define function
function is the same as normal assembly instructions,
it has a label, and use ".type label_name, @function" to tell that this is a function,
.type label_name, @function
label_name is a label,
this line says that label_name is the start of a function,
and the function will be called via this label,
ret
this line is end of function,
------
step to use function
steps:
* before call:
* push params of function into stack in reverse order
* call function
call do 2 things:
* push %eip into top of stack, this will be the return address,
* set %eip to start address of called function, so that program will jump to function,
* inside function:
* save %ebp to stack
* move %esp to %ebp, so that easy to read param & make use of stack as storage,
* read params from stack,
the first param is at "8(%ebp)" now, because we push %ebp which take 4byte, and "call" push %eip which take 4byte,
*
* do logics
*
* put return value into %eax
* restore %esp from %ebp
* restore %ebp from stack
* ret
ret instruction return control to where it's called from, by pop top of stack to %eip,
remember that before call, the return address is at the top of stack, so before ret, should restore stack to before call, this is done by restore %esp,
* after return:
* adjust %esp to the position before push params of function,
* get return value from %eax,
*
------
recursive function
each function call has it's own stack,
first push stack for all recursive function call, then release all function call & stack & do calculation,
use pushed %ebp to keep track of %esp of previous call,
------
calling convention
means the basic rule to:
* pass param
* make use of registers
usually:
use stack to pass params, push in reverse order,
use %ebp to keep track of current %esp,
use pushed %ebp to keep track of previous %esp,
------
code
fun_sumofsquare.s
# function - sum of square
.section .data
nums:
.long 1,2,3,4,-5
num_count:
.long 5
.section .text
.globl _start
_start:
pushl num_count # second param, number count
pushl $nums # first param, start address of numbers
call square_sum # call function
addl $8, %esp # restore stack to status before push params of function
movl %eax, %ebx # status value for exit
jmp exit # exit
exit:
movl $1, %eax
int $0x80
# a function to caculate sum of square
# param:
# first param:
# start address of numbers
# second param:
# count of numbers
# storage:
# %edi:
# count of number remain
# %ecx:
# address of current number
# %ebx:
# value & square of current number
# %eax:
# sum of squares
.type square_sum, @function # function start
square_sum:
pushl %ebp # save %ebp to stack
movl %esp, %ebp # save %esp to %ebp, also use %esp as base address to get value from stack
movl 8(%ebp), %ecx # read first param, start address of numbers
movl 12(%ebp), %edi # read second param, count of numbers
movl $0, %eax
square: # one square
cmpl $0, %edi
jle square_sum_end
movl (%ecx), %ebx
imull %ebx, %ebx
addl %ebx, %eax
decl %edi
addl $4, %ecx
jmp square
square_sum_end: # end square function
movl %ebp, %esp # restore %esp, for ret
popl %ebp # restore %ebp
ret # function end
fun_factorial.s
# function - factorial .section .data num: .long 5 .section .text .globl _start _start: pushl num call factorial addl $4, %esp movl %eax, %ebx jmp exit exit: movl $1, %eax int $0x80 .type factorial, @function factorial: pushl %ebp movl %esp, %ebp movl 8(%ebp), %edi # read num movl $1, %eax jmp factorial_one factorial_one: cmpl $1, %edi jle factorial_end imull %edi, %eax decl %edi jmp factorial_one factorial_end: movl %ebp, %esp popl %ebp ret
fun_factorial_recusive.s
# function - factorial recursive
.section .data
num:
.long 5
.section .text
.globl _start
_start:
pushl num
call factorial
addl $4, %esp
movl %eax, %ebx
jmp exit
exit:
movl $1, %eax
int $0x80
# function for factorial - recursive, numbers are all pushed to stack, then do multiplication
# param:
# first param: number
# storage:
# when push stack:
# %eax -> number
# when pop stack:
# %ebx -> number
# %eax -> tmp result
# %ebx:
# current %esp
# pushed %ebx:
# store last %esp
.type factorial, @function
factorial:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
cmpl $1, %eax
jle factorial_end
decl %eax
pushl %eax
call factorial
movl 8(%ebp), %ebx
imull %ebx, %eax
jmp factorial_end
factorial_end:
movl %ebp, %esp
popl %ebp
ret
------