【汇编】函数调用中参数的汇编实现
示例C代码
// 参数远超寄存器数量 typedef struct { int Rn[100]; int pc; } reg; int framePoint(reg cpu) { return cpu.Rn[0] * cpu.pc; } int main() { reg cpu; cpu.Rn[0] = 1; cpu.pc = 2; return framePoint(cpu); }
对应汇编代码
// 编译器: armv7-a gcc (9.2.1) framePoint(reg): sub sp, sp, #16 @申请栈空间 str fp, [sp, #-4]! @保护main函数栈帧,等同于push {fp} add fp, sp, #0 @fp变成framePoint栈帧,同时也指向了栈顶 add ip, fp, #4 @定位到入栈口,让4个参数依次入栈 stm ip, {r0, r1, r2, r3} @r0-r3入栈保存 ldr r3, [fp, #4] @取值cpu.Rn[0] = 1 ldr r2, [fp, #404] @取值cpu.pc = 2 mul r3, r2, r3 @cpu.Rn[0] * cpu.pc mov r0, r3 @返回值由r0保存 add sp, fp, #0 @重置sp,和add fp, sp, #0配套出现 ldr fp, [sp], #4 @恢复main函数栈帧 add sp, sp, #16 @归还栈空间,sp回落到main函数栈顶位置 bx lr @跳回main函数 main: push {fp, lr} @入栈保存调用函数现场 add fp, sp, #4 @fp指向sp+4,即main栈帧的底部 sub sp, sp, #800 @分配800个线性地址,即main栈帧的顶部 mov r3, #1 @r3 = 1 str r3, [fp, #-408] @将1放置 fp-408处,即:cpu.Rn[0]处 mov r3, #2 @r3 = 2 str r3, [fp, #-8] @将2放置 fp-8处,即:cpu.pc mov r0, sp @r0 = sp sub r3, fp, #392 @r3 = fp - 392 mov r2, #388 @只拷贝388,剩下4个由寄存器传参 mov r1, r3 @保存由r1保存r3,用于memcpy bl memcpy @拷贝结构体部分内容,将r1的内容拷贝r2的数量到r0 sub r3, fp, #408 @定位到结构体剩余未拷贝处 ldm r3, {r0, r1, r2, r3} @将剩余结构体内容通过寄存器传参 bl framePoint(reg) @执行framePoint mov r3, r0 @返回值给r3 nop @用于程序指令的对齐 mov r0, r3 @再将返回值给r0 sub sp, fp, #4 @恢复SP值 pop {fp, lr} @出栈恢复调用函数现场 bx lr @跳回调用函数
栈空间变化
总结
- 代码中变量存放地址是由低地址到高地址
- 栈空间是地址向下增长的满栈,即从高地址到低地址存储
参考:https://blog.51cto.com/u_14940441/2729224
再牛逼的梦想也架不住傻逼似的坚持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2020-07-24 【C++】类概念及使用
2018-07-24 【emwin】多次删除同一窗口导致死机现象