x86_64 通过将函数参数存放在栈中的方式来实现参数传递。
# PURPOSE: Program to illustrate how functions work
# This program will compute the value of
# 2^3 + 5^2
## Everything in the main program is stored in registers,
# so the data section doesn’t have anything.
.section .data.section .text.globl _start
_start:push $3 # 将第二个参数入栈push $2 # 将第一个参数入栈call power # 调用函数power,call会自动将函数返回地址入栈,# 也就是下一条指令的地址add $16, %rsp # move the stack pointer back,# 通过移动栈顶指针的方式将保存在栈中的数据清理掉push %rax # save the first answer before# calling the next functionpush $2 # push second argumentpush $5 # push first argumentcall power # call the functionadd $16, %rsp # move the stack pointer backpop %rbx # The second answer is already# in %rax. We saved the# first answer onto the stack,# so now we can just pop it# out into %rbx,将第二次计算的结果从栈中弹出存放到rbx寄存器中add %rax, %rbx # add them together# the result is in %rbxmov $1, %rax # exit (%rbx is returned)int $0x80# PURPOSE: This function is used to compute
# the value of a number raised to
# a power.
#
# INPUT: First argument - the base number
# Second argument - the power to
# raise it to
#
# OUTPUT: Will give the result as a return value
#
# NOTES: The power must be 1 or greater
#
# VARIABLES:
# %rbx - holds the base number
# %rcx - holds the power
#
# -8(%rbp) - 将计算后的结果放在栈中
#
# %rax is used for temporary storage
#
.type power, @function
power:push %rbp # 将旧的栈基址入栈mov %rsp, %rbp # 当前rsp指向旧的栈基址,获取传入参数时需要加上返回地址和旧栈基址的偏移# 因为存在两次入栈,一次是返回地址入栈,一次是rpb指针入栈sub $8, %rsp # 在栈中申请8字节用于存放计算结果的内存mov 16(%rbp), %rbx # 获取栈中传入的第一个参数,值存放在rbxmov 24(%rbp), %rcx # 获取栈中传入的第一个参数,值存放在rcxmov %rbx, -8(%rbp) # store current resultpower_loop_start:cmp $1, %rcx # if the power is 1, we are doneje end_powermov -8(%rbp), %rax # move the current result into %eaximul %rbx, %rax # multiply the current result by# the base numbermov %rax, -8(%rbp) # 将计算结果更新到栈中dec %rcx # decrease the powerjmp power_loop_start # run for the next powerend_power:mov -8(%rbp), %rax # return value goes in %raxmov %rbp, %rsp # restore the stack pointerpop %rbp # restore the base pointerret
编译方式:as w_power.s -o w_power.o;ld w_power.o -o w_power
结果查看:执行w_power之后,echo $?查看计算结果。
使用专用寄存器来传递函数调用参数,rdi用来存放第一参数,rsi用来存放第二个参数,并且把第一计算的结果存放在栈中。
# PURPOSE: Program to illustrate how functions work
# This program will compute the value of
# 2^3 + 5^2
## Everything in the main program is stored in registers,
# so the data section doesn’t have anything.
.section .data.section .text.globl _start
_start:mov $2, %rdi # 将第一个参数存入rdimov $3, %rsi # 将第二个参数存入rsicall power # 调用函数power,call会自动将函数返回地址入栈,# 也就是下一条指令的地址push %rax # 将第一次计算的结果存放在栈中mov $5, %rdi # 将第一个参数存入rdimov $2, %rsi # 将第一个参数存入rsicall powerpop %rbx # 获取第一次的计算结果add %rax, %rbx # 第一次计算结果rbx与第二次计算结果rax的值相加# the result is in %rbxmov $1, %rax # exit (%rbx is returned)int $0x80# PURPOSE: This function is used to compute
# the value of a number raised to
# a power.
#
# INPUT: First argument - the base number
# Second argument - the power to
# raise it to
#
# OUTPUT: Will give the result as a return value
#
# NOTES: The power must be 1 or greater
#
# VARIABLES:
# %rdi - 第一个参数
# %rsi - 第二个参数
#
# -8(%rbp) - 将计算后的结果放在栈中
#
# %rax is used for temporary storage
#
.type power, @function
power:push %rbp # 将旧的栈基址入栈mov %rsp, %rbp # 当前rsp指向旧的栈基址,获取传入参数时需要加上返回地址和旧栈基址的偏移# 因为存在两次入栈,一次是返回地址入栈,一次是rpb指针入栈sub $8, %rsp # 在栈中申请8字节用于存放计算结果的内存mov %rdi, -8(%rbp) # store current resultpower_loop_start:cmp $1, %rsi # if the power is 1, we are doneje end_powermov -8(%rbp), %rax # move the current result into %eaximul %rdi, %rax # multiply the current result by# the base numbermov %rax, -8(%rbp) # 将计算结果更新到栈中dec %rsi # decrease the powerjmp power_loop_start # run for the next powerend_power:mov -8(%rbp), %rax # return value goes in %raxmov %rbp, %rsp # restore the stack pointerpop %rbp # restore the base pointerret