我正试图将r0-r5传递到函数check
中。但是,只有寄存器r0-r3是通过引用复制的。在我的主函数中,我有这个代码。
push {lr}
mov r0, #1
mov r1, #2
mov r2, #3
mov r3, #4
mov r4, #5
mov r5, #6
bl check
pop {lr}
bx lr
在我的check
函数中,我有这样的代码。这是在一个单独的文件中,也不确定这是否重要
m: .asciz "%d, %d ~ (%d, %d, %d)
...
push {lr}
ldr r0, =m
bl printf
pop {lr}
bx lr
其输出为2, 3 ~ (4, 33772, 1994545180)
。我正在尝试学习汇编,所以你能用谷歌来解释答案吗?我知道我需要使用堆栈,但我不确定如何使用它,我想学习如何使用。提前谢谢。
您可以尝试一下并查看
void check ( unsigned int, unsigned int, unsigned int, unsigned int, unsigned int );
void call_check ( void )
{
check(1,2,3,4,5);
}
arm linux gneabi gcc-c-O2 check.c-o check.oarm linux gneabi objdump-D检查.o
00000000 <call_check>:
0: e52de004 push {lr} ; (str lr, [sp, #-4]!)
4: e3a03005 mov r3, #5
8: e24dd00c sub sp, sp, #12
c: e58d3000 str r3, [sp]
10: e3a00001 mov r0, #1
14: e3a01002 mov r1, #2
18: e3a02003 mov r2, #3
1c: e3a03004 mov r3, #4
20: ebfffffe bl 0 <check>
24: e28dd00c add sp, sp, #12
28: e8bd8000 ldmfd sp!, {pc}
现在当然可以手工优化,仍然可以正常工作。也许他们在16字节/4字/64位的边界上保持堆栈对齐,这是对堆栈指针进行额外12字节修改的原因吗?不知道。但除此之外,您可以看到,由于您正在调用另一个函数,因此自然需要保存链接寄存器。r0-r3是显而易见的,然后根据eabi,堆栈上的第一件事就是第5个字的参数。
同样,对于您的check函数,您可以简单地让编译器让您开始。如果您查看您的代码,r0将作为您的第一个参数出现,然后通过将其更改为printf的第一个变量来废弃它。你需要6个参数才能传递给printf。你需要把它们移到一个参数上——第一个要检查的参数是第二个要检查,第二个是第三个要检查等等。所以代码必须进行移位(其中两个现在在堆栈上)。