assembly - function
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
------
推荐阅读