- 第一章 CPU 简介
- 第二章 Hello,world!
- 第三章 函数开始和结束
- 第四章 栈
- Chapter 5 printf() 与参数处理
- Chapter 6 scanf()
- CHAPER7 访问传递参数
- Chapter 8 一个或者多个字的返回值
- Chapter 9 指针
- Chapter 10 条件跳转
- 第 11 章 选择结构 switch()/case/default
- 第 12 章 循环结构
- 第 13 章 strlen()
- Chapter 14 Division by 9
- chapter 15 用 FPU 工作
- Chapter 16 数组
- Chapter 17 位域
- 第 18 章 结构体
- 19 章 联合体
- 第二十章 函数指针
- 第 21 章 在 32 位环境中的 64 位值
- 第二十二章 SIMD
- 23 章 64 位化
- 24 章 使用 x64 下的 SIMD 来处理浮点数
- 25 章 温度转换
- 26 章 C99 的限制
- 27 章 内联函数
- 第 28 章 得到不正确反汇编结果
- 第 29 章 花指令
- 第 30 章 16 位 Windows
- 第 31 章 类
- 三十二 ostream
- 34.2.2 MSVC
- 34.2.3 C++ 11 std::forward_list
- 34.3 std::vector
- 34.4 std::map and std::set
5.3 ARM:3 个参数
习惯上,ARM 传递参数的规则(参数调用) 如下:前 4 个参数传递给了 R0-R3 寄存器,其余的参数则在栈中。这和 fastcall 或者 win64 传递参数很相似
5.3.1 Non-optimizing Keil + ARM mode(非优化 keil 编译模式 + ARM 环境)
#!bash
.text:00000014 printf_main1
.text:00000014 10 40 2D E9 STMFD SP!, {R4,LR}
.text:00000018 03 30 A0 E3 MOV R3, #3
.text:0000001C 02 20 A0 E3 MOV R2, #2
.text:00000020 01 10 A0 E3 MOV R1, #1
.text:00000024 1D 0E 8F E2 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d
"
.text:00000028 0D 19 00 EB BL __2printf
.text:0000002C 10 80 BD E8 LDMFD SP!, {R4,PC}
所以 前四个参数按照它们的顺序传递给了 R0-R3, printf() 中的格式化字符串指针在 R0 中,然后 1 在 R1,2 在 R2,3 在 R3. 到目前为止没有什么不寻常的。
5.3.2 Optimizing Keil + ARM mode(优化的 keil 编译模式 + ARM 环境)
#!bash
.text:00000014 EXPORT printf_main1
.text:00000014 printf_main1
.text:00000014 03 30 A0 E3 MOV R3, #3
.text:00000018 02 20 A0 E3 MOV R2, #2
.text:0000001C 01 10 A0 E3 MOV R1, #1
.text:00000020 1E 0E 8F E2 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d
"
.text:00000024 CB 18 00 EA B __2printf
表 5.7: Optimizing Keil + ARM mode
这是在针对 ARM optimized (-O3) 版本下的,我们可以 B 作为最后一个指令而不是熟悉的 BL。另外一个不同之处在 optimized 与之前的(compiled without optimization) 对比发现函数 prologue 和 epilogue(储存 R0 和 LR 值的寄存器),B 指令仅仅跳向另一处地址,没有任何关于 LR 寄存器的操作,也就是说它和 x86 中的 jmp 相似,为什么会这样?因为代码就是这样,事实上,这和前面相似,主要有两点原因 1) 不管是栈还是 SP(栈指针),都有被修改。2)printf() 的调用是最后的指令,所以之后便没有了。完成之后,printf() 函数就返回到 LR 储存的地址处。但是指针地址从函数调用的地方转移到了 LR 中!接着就会从 printf() 到那里。结果,我们不需要保存 LR,因为我们没有必要修改 LR。因为除了 printf() 函数外没有其他函数了。另外,除了这个调用外,我们不需要再做别的。这就是为什么这样编译是可行的。
5.3.3 Optimizing Keil + thumb mode
#!bash
.text:0000000C printf_main1
.text:0000000C 10 B5 PUSH {R4,LR}
.text:0000000E 03 23 MOVS R3, #3
.text:00000010 02 22 MOVS R2, #2
.text:00000012 01 21 MOVS R1, #1
.text:00000014 A4 A0 ADR R0, aADBDCD ; "a=%d; b=%d; c=%d
"
.text:00000016 06 F0 EB F8 BL __2printf
.text:0000001A 10 BD POP {R4,PC}
表 5.8:Optimizing Keil + thumb mode
和 non-optimized for ARM mode 代码没什么明显的区别
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论