问题描述
这个小程序只打印在外壳中编写的2个argv。
.global main
main:
ldr r2, [r1,#8]
ldr r1, [r1,#4]
ldr r0, =message_format
bl printf
mov r0, #0
message_format:
.asciz "argv: %s %s
"
我希望它以0代码退出,所以我将#0放在R0中,但:
root@kali-pi:~/Desktop/arm_test# ./arggggg 1 2
argv: 1 2
Segmentation fault
root@kali-pi:~/Desktop/arm_test# echo $?
139
我如何修复此问题?
推荐答案
我如何修复此问题?
汇编程序没有结尾:
因为计算机的内存通常比汇编程序长,所以汇编程序后面有一些数据。由于CPU不区分数据和代码,因此它会将汇编程序后面的字节解释为代码。
示例:
假设您有拇指代码,程序后面的RAM包含字节1、2、3和4。然后CPU会将您的程序解释为:
ldr r2, [r1,#8]
ldr r1, [r1,#4]
ldr r0, =message_format
bl printf
mov r0, #0
lsls r1, r0, #8
lsls r3, r0, #16
...
CPU将一直运行,直到找到出错的指令。
您有两种其他用户已经在评论中写下的可能性:
1)显式使用Exit()函数或类似的
您可以调用exit()
函数立即退出程序。
此操作类似于调用printf()
函数。
2)main()函数返回
您可以使用bx lr
从main()
函数返回。
遗憾的是,printf()
函数将覆盖lr
的值,因此简单的bx lr
将导致无限循环。
您必须在调用printf()
之前保存lr
寄存器,并在以后恢复它。
示例:
push {lr}
ldr r2, [r1,#8]
ldr r1, [r1,#4]
ldr r0, =message_format
bl printf
mov r0, #0
pop {lr}
bx lr
如果您正在编译Thumb代码,pop {lr}
将不起作用。请改用pop {r1}
和bx r1
。
如果您确定main()
函数和调用main()
函数的函数属于相同的代码类型(ARM或Thumb),则也只能在末尾使用一条指令:pop {pc}
。
在只支持Thumb代码的Cortex M CPU上工作或在不支持Thumb的旧ARM CPU上工作时就是这种情况。