函数调用过程的汇编代码分析(arm64指令集),顺便关注一下栈空间的分配与回收。
本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频
下述C语言程序包含了一个简单的add()函数,该函数接受两个整型参数,计算并返回两者的和。
main()函数调用执行了add()函数来计算3+2的和,并将计算结果打印出来。
#include
int add(int a, int b){
int t = a + b;
return t;
}
int main(){
int x = 3;
x = add(x,2);
printf("%d",x);
return 1;
}
为了从机器指令层面理解上述函数调用过程中的传参、跳转、返回等行为,我们在浏览器中访问了下述网站:
在粘贴相关代码并选择ARM64 gcc 9.3选项后,我们得到下述汇编语言指令序列:
add(int, int):
sub sp, sp, #32
str w0, [sp, 12]
str w1, [sp, 8]
ldr w1, [sp, 12]
ldr w0, [sp, 8]
add w0, w1, w0
str w0, [sp, 28]
ldr w0, [sp, 28]
add sp, sp, 32
ret
.LC0:
.string "%d"
main:
stp x29, x30, [sp, -32]!
mov x29, sp
mov w0, 3
str w0, [sp, 28]
mov w1, 2
ldr w0, [sp, 28]
bl add(int, int)
str w0, [sp, 28]
ldr w1, [sp, 28]
adrp x0, .LC0
add x0, x0, :lo12:.LC0
bl printf
mov w0, 1
ldp x29, x30, [sp], 32
ret
第2 ~ 11行:函数add()的实体
第2行:将栈指针(stack pointer)寄存器sp的值减去32,结果仍存储到sp中。显然,该指令事实上为自动变量分配了栈空间。
第10行:在函数返回前,将栈指针(stack pointer)寄存器的值增加32,结果仍存储到sp中。显然,该指令事实上回收了栈空间,回收的数量与分配的数量一致。
第3行:将寄存器w0中的32位数值存储到内存地址sp+12处,结合后续代码可以知道,sp+12处存储的即是形参a。
第4行:将寄存器w1中的32位数值存储到内存地址sp+8处,结合后续代码可以知道,sp+8处存储的即是形参b。
第5行:将存储于sp+12处的形参a值装入寄存器w1。
第6行:将存储于sp+8处的形参b值装入寄存器w0。
第7行:将寄存器w1和w0的值相加,结果存入w0,此处事实上相加的即是形参a和b。
第8行:将寄存器w0中的32位数值存入地址sp+28处。可以推测,sp+28处存储的即为自动变量t。
第9行:将sp+28处的自动变量t装入寄存器w0, 结合后续代码可知,w0寄存器被用于向函数的调用者返回计算结果。
第11行:返回x30寄存器所标识的地址继续执行,此时,x30寄存器所标识的地址为上述代码的第22行。
第14 ~ 29行:函数main()的实体
第17行:将整数3存入w0寄存器。
第18行:将w0中的32位值存入sp+28处。合理推测,sp+28处为变量x的存放位置。
第19行:将整数2存入w1寄存器,结合add()代码可知,add()通过w1寄存器获得参数b。
第20行:将sp+28处的变量x的值存入寄存器w0。结合add()代码可知,add()通过w0寄存器获得参数a。
第 21行:在准备好函数调用的参数(a,b分别在w0和w1寄存器内)后,branch & link指令完成两件工作:
当add()函数完成任务后,第11行ret指令将返回x30寄存器标识的地址继续执行,即返回代码的第22行。
第22行:将w0寄存器的23位数值装入内存地址sp+28处。结合add()函数代码可知,此时的w0寄存器事实上存储的是add()函数的计算结果。这行代码事实上取得了add()函数的返回值,并将其存入x变量(sp+28)。
在代码的后续部分,我们还看到main()函数对printf()函数的调用… 略。
为了帮助更多的年轻朋友们学好编程,作者在B站上开了两门免费的网课,一门零基础讲Python,一门零基础C和C++一起学,拿走不谢!
简洁的C及C++
Python编程基础及应用
如果你觉得纸质书看起来更顺手,目前Python有两本,C和C++在出版过程中。
Python编程基础及应用
Python编程基础及应用实验教程