如何让程序在print tf完成后带着0退出?

人气:840 发布:2022-10-16 标签: assembly printf return arm

问题描述

这个小程序只打印在外壳中编写的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 lrmain()函数返回。

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

467