如何让程序在 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 上工作时就是这种情况。
这个小程序只打印 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 上工作时就是这种情况。