假设我有一个函数foo定义为:
def foo(x,y):
return x + y
说我有一个函数调用:
foo(2,3)
对应于x86-64:
movq $2 %rdi
movq $3 %rsi
call foo
我知道,如果函数foo
有一个返回值,它将存储在寄存器%rax
中。但这到底是什么意思呢?
程序集应该是这样的:
movq $2 %rdi
movq $3 %rsi
call foo
foo:
movq -8(%rsb) %rax
addq -16(%rsb) %rax
你能在汇编中完成foo的定义吗?它使用%rax
吗?如何使用%rax
?
我的问题是如何使用%rax来获得函数的返回值以及%rax
中的此值如何在调用者和被调用者之间传递。由于
为了说明这是如何工作的,我将使用函数foo
作为示例:
def foo(x,y):
return x + y
main:
z = foo(7,10) * 3
那么z
的值是如何计算的。(实际发生的情况可能是编译器会预先计算17*3并将其作为常量加载,但这对我试图演示的内容没有帮助。)
main:
mov $7, %edi # put integer args in 64-bit registers efficiently
mov $10, %esi # with zero-extension of 32-bit
call foo
#the ret instruction at the end of "foo" takes us back here
#the result of "foo" is now in %rax, and the rest of the program can use it.
mov %rax, %rdx # Save a copy of %rax so we can multiply by 3.
shl $1, %rax # multiply by 2
add %rdx, %rax # add the original, this means we effectively multiplied by 3.
# lea (%rax, %rax, 2), %rax # efficient way to multiply by 3
ret # exit program by returning from main()
####################################################
foo:
add %rsi, %rdi # add the two numbers
mov %rsi, %rax # return value in %rax
ret
# compilers would have used lea (%rdi, %rsi), %rax to copy-and-add