@KemyLand 对于你的回答,我还有一个例子:源代码为:void test1(){}无效测试(int i){测试1();}无效主(){测试(1);}我使用上面相同的编译命令,然后得到以下程序集:main.o:文件格式elf32-littlearm.text 节的反汇编:00000000 <test1>:无效测试1(){}0: e12fff1e bx lr00000004 <测试>:无效测试(int i){4: e52de004 推送 {lr} ;(str lr, [sp, #-4]!)8: e24dd00c sub sp, sp, #12c: e58d0004 str r0, [sp, #4]测试1();10: ebffffffe bl 0 <test1>}14: e28dd00c 添加 sp, sp, #1218: e49de004 pop {lr} ;(ldr lr, [sp], #4)1c:e12fff1e bx lr00000020 <主>:无效主(){20: e92d4008 推{r3, lr}测试(1);24: e3a00001 mov r0, #128:ebffffffe bl 4 <test>}2c: e8bd4008 pop {r3, lr}30:e12fff1e bx lr如果第一个例子中的 push {r3, lr} 是为了使用较少的指令,为什么在这个函数 test() 中,编译器不只使用一条指令?push {r0, lr}它使用 3 个指令而不是 1 个.push {lr}sub sp, sp #12str r0, [sp, #4]顺便说一句,为什么它用12来代替sp,堆栈是8字节对齐的,它可以用4来代替吗? 解决方案根据标准 ARM Embedded ABI,r0 到 r3 用于将参数传递给函数,以及其返回值,同时lr(又名:r14)是链接寄存器,其目的是保存函数的返回地址.很明显必须保存 lr,否则 main() 将无法返回给它的调用者.现在臭名昭著的是,每条 ARM 指令都需要 32 位,正如您提到的,ARM 的调用堆栈对齐要求是 8 字节.而且,作为奖励,我们使用了 Embedded ARM ABI,因此应优化代码大小.因此,通过推送未使用的寄存器(不需要 r3,因为 test() 不接受参数也不返回任何内容),然后弹出一条 32 位指令,而不是添加更多指令(从而浪费宝贵的内存!)来操作堆栈指针.毕竟,可以得出结论,这只是 GCC 的优化.I tried to write a simple test code like this(main.c):main.cvoid test(){}void main(){ test();}Then I used arm-non-eabi-gcc to compile and objdump to get the assembly code:arm-none-eabi-gcc -g -fno-defer-pop -fomit-frame-pointer -c main.carm-none-eabi-objdump -S main.o > outputThe assembly code will push r3 and lr registers, even the function did nothing.main.o: file format elf32-littlearmDisassembly of section .text:00000000 <test>:void test(){} 0: e12fff1e bx lr00000004 <main>:void main(){ 4: e92d4008 push {r3, lr} test(); 8: ebfffffe bl 0 <test>} c: e8bd4008 pop {r3, lr} 10: e12fff1e bx lrMy question is why arm gcc choose to push r3 into stack, even test() function never use it? Does gcc just random choose 1 register to push?If it's for the stack aligned(8 bytes for ARM) requirement, why not just subtract the sp? Thanks.==================Update==========================@KemyLand For your answer, I have another example:The source code is:void test1(){}void test(int i){ test1();}void main(){ test(1);}I use the same compile command above, then get the following assembly:main.o: file format elf32-littlearmDisassembly of section .text:00000000 <test1>:void test1(){} 0: e12fff1e bx lr00000004 <test>:void test(int i){ 4: e52de004 push {lr} ; (str lr, [sp, #-4]!) 8: e24dd00c sub sp, sp, #12 c: e58d0004 str r0, [sp, #4] test1(); 10: ebfffffe bl 0 <test1>} 14: e28dd00c add sp, sp, #12 18: e49de004 pop {lr} ; (ldr lr, [sp], #4) 1c: e12fff1e bx lr00000020 <main>:void main(){ 20: e92d4008 push {r3, lr} test(1); 24: e3a00001 mov r0, #1 28: ebfffffe bl 4 <test>} 2c: e8bd4008 pop {r3, lr} 30: e12fff1e bx lrIf push {r3, lr} in first example is for use less instructions, why in this function test(), the compiler didn't just using one instruction?push {r0, lr}It use 3 instructions instead of 1.push {lr}sub sp, sp #12str r0, [sp, #4]By the way, why it sub sp with 12, the stack is 8-bytes aligned, it can just sub it with 4 right? 解决方案 According to the Standard ARM Embedded ABI, r0 through r3 are used to pass the arguments to a function, and the return value thereof, meanwhile lr (a.k.a: r14) is the link register, whose purpose is to hold the return address for a function.It's obvious that lr must be saved, as otherwise main() would have no way to return to its caller.It's now notorious to mention that every single ARM instruction takes 32 bits, and as you mentioned, ARM has a call stack alignment requirement of 8 bytes. And, as a bonus, we're using the Embedded ARM ABI, so code size shall be optimized. Thus, it's more efficient to have a single 32-bit instruction both saving lr and aligning the stack by pushing an unused register (r3 is not needed, because test() does not take arguments nor it returns anything), and then pop in a single 32-bit instruction, rather than adding more instructions (and thus, wasting precious memory!) to manipulate the stack pointer.After all, it's pretty logical to conclude this is just an optimization from GCC. 这篇关于为什么 ARM gcc 在函数开始时将寄存器 r3 和 lr 压入堆栈?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
09-17 15:50