当我试图运行一个调用一个非常简单的ARM汇编函数的C程序时,我现在遇到了一个奇怪的问题。这是我的C代码:
#include <stdio.h>
#include <stdlib.h>
extern void getNumber(int* pointer);
int main()
{
int* pointer = malloc(sizeof(int));
getNumber(pointer);
printf("%d\n", *pointer);
return 0;
}这是我的组装代码:
.section .text
.align 4
.arm
.global getNumber
.type getNumber STT_FUNC
getNumber:
mov r1, #0
str r1, [r0]
bx lr到目前一切尚好。但是,如果我在mov r7, #0的顶部添加一行getNumber,则程序在试图访问pointer时会出现分段错误。在使用gdb检查它之后,我现在注意到指针本身存储在一个非常低的地址中,比如0xa。
现在,我做了一些研究,显然r7是拇指代码的帧指针(根据这)。但是,我清楚地指出,我不想在我的汇编代码中使用.arm线中的拇指指令。为什么它会失败呢?
我正在使用arm- Linux -gnueabihf-gcc编译.c和.s文件,我正在一个基于Cortex-A8的运行Arch的板上运行这个程序。
编辑:如果我使用-fomit-框架-指针标志编译,程序运行良好。但是,我仍然想知道为什么它使用r7作为帧指针。
编辑2:即使我使用.code 32而不是.arm,它仍然失败。
发布于 2014-06-13 22:56:56
ARM程序调用标准指定以下内容:
子例程必须保留寄存器r4-r8、r10、r11和SP (以及指定r9为v6的PCS变体中的r9 )的内容。
因此,如果汇编语言子程序使用它,则必须保存和恢复r7。
您可能通过不编译拇指模式来避免小型测试程序的问题,但您只是意外地避免了这个问题。任何链接到您的程序集例程的内容都有权期望保留r7。
发布于 2014-06-13 22:12:55
你破坏程序是因为你破坏了帧指针,就像你刚才提到的。这个大会没有韵律,也没有理由。只是那只手臂为某些东西保留了特定的寄存器。与x86类似,尤其是堆栈指针。
对于要避免的寄存器,这里有一个非常好的参考:http://msdn.microsoft.com/en-us/library/ms253599(v=vs.80).aspx
发布于 2014-06-13 22:21:04
我终于明白了:执行$ arm-linux-gnueabihf-gcc -v向我展示了我的编译器正在使用的默认选项。其中包括:--with-mode=thumb。
用-marm编译修复了它。现在它正在按预期工作!
编辑:在阅读这里的评论时,我意识到我弄错了。我应该保存/恢复r7,这样它就不会破坏我程序的其余部分。幸运的是,我现在从一个玩具项目中学到了这个,而不是在做一些真实的事情时学到的!
https://stackoverflow.com/questions/24214405
复制相似问题