我试图了解如何从ARM中的基本程序中正确退出,并且我已经看到很多代码使用PUSH {lr}
保存调用函数的返回地址(假设调用者使用了BL
将寄信人地址保存在lr
中,以便以后检索它并使用POP {pc}
跳转到寄信人地址。在这些情况下,lr
寄存器被BL
更改了,因此我可以使用它来处理main / _start函数中的子例程,但是使用下面的代码将值压入堆栈将只是0x0 ,导致退货时出错。
.text
.global main
main:
PUSH {lr}
MOV r0, #42
POP {pc}
.end
我运行了很多外部代码,它们使用此确切方法从主函数中返回而没有Segmentation Fault
,但是当我尝试使用gdb调试器运行此基本程序时,很明显{ {1}}在main的第一行中保持为零,从而在返回时产生错误。本质上,我的问题是在将lr
推入主函数中的堆栈时如何获取正确的值。
我用过
lr
编译可执行文件。
编辑:我发现使用
$ as -g ex.s -o ex && ld -e main ex.o -o ex
链接该程序部分地回答了我的问题,看着gdb的输出,我发现 $ gcc ex.o -o ex
似乎用正确的值初始化gcc
,从而使示例程序正常退出。但是,我仍然想像以前一样使用lr
时是否有一种获取此地址的方法。
答案 0 :(得分:4)
ELF入口点不是功能,没有用户空间调用者可以返回,并且任何地方都没有返回地址。您所获得的只是指向argc
的堆栈指针,然后指向argv[]
数组(不是指向它的指针),然后是env[]
。
您需要进行sys_exit
系统调用(例如libc _exit(2)
函数)。
与ld -e main ex.o -o ex
链接将创建一个静态可执行文件,并以main
作为ELF入口点。从默认的_start
更改名称不会对您有任何帮助,只会让所有人感到困惑。我不推荐。