如何让程序在 printf 完成后以 0 退出?

How to let the program exit with a 0 after printf finished?

这个小程序只打印 shell 中写的 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\n"

我希望它以 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

我该如何解决这个问题?

How could I fix this?

汇编程序没有“结束”:

由于您的计算机内存通常比汇编程序长,因此在汇编程序之后有一些数据。并且由于CPU不区分数据和代码,它会将汇编程序后面的字节解释为代码。

示例:

假设您的程序包含字节 1、2、3 和 4 之后有 Thumb 代码和 RAM。那么 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() 函数的 Return

您可以使用 main() 函数中的 bx lr 到 return。

不幸的是,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 上工作时就是这种情况。