ARMv7架构下如何从main()返回超过8位的数值?
我写了一段ARMv7代码计算1到100的和,结果存在r1里,最后把r1移到r0返回给操作系统。但我听说退出码只用到r0的最低8位,那像1到100的和(5050,远大于255)这种超过8位的数值,该怎么正确返回呢?
附上我的代码:
@ looping.s @ 计算1到100的整数和 .text .balign 4 .global main main: MOV r1, #0 @ r1 = 0 作为累加和 MOV r2, #0 @ r2 = 0 作为计数器 loop: ADD r2, r2, #1 @ 计数器 = 计数器 + 1 ADD r1, r1, r2 @ 累加和 = 累加和 + 计数器 CMP r2, #100 @ 计数器 - 100 BLT loop @ 若计数器 < 100 则跳转到循环开头 MOV r0, r1 @ 将累加和存入r0 BX lr @ 将求和结果返回给操作系统
回答:
嘿,这个问题戳中了一个很常见的误区!确实,不管是ARM还是x86架构,POSIX标准都规定进程的退出码只使用返回寄存器的最低8位——这意味着任何超过255的数值都会被自动截断(比如你算的5050,5050除以256的余数是186,所以实际返回给操作系统的退出码会是186,而不是完整的5050)。
如果想要完整传递超过8位的计算结果,别再打退出码的主意啦,它本来就不是用来干这个的。这里有几个更合理的方案:
1. 把结果打印到标准输出(最推荐)
Unix/Linux的设计哲学里,退出码只用来表示进程的执行状态(0=成功,非0=失败,不同数值对应不同失败类型),传递计算结果的正确方式是用标准输出。你可以直接调用C库的printf来打印结果:
修改后的代码如下:
@ looping.s @ 计算1到100的整数和并打印结果 .data fmt_str: .asciz "1到100的和是:%d\n" @ 定义格式化输出字符串 .text .balign 4 .global main main: MOV r1, #0 @ r1 = 0 作为累加和 MOV r2, #0 @ r2 = 0 作为计数器 loop: ADD r2, r2, #1 @ 计数器自增1 ADD r1, r1, r2 @ 累加当前计数器的值 CMP r2, #100 @ 比较计数器是否到100 BLT loop @ 没到100就继续循环 @ 调用printf输出结果 LDR r0, =fmt_str @ 第一个参数:格式化字符串的地址 MOV r1, r1 @ 第二个参数:计算得到的累加和 BL printf @ 调用printf函数 @ 设置退出码为0,表示程序执行成功 MOV r0, #0 BX lr
编译运行后,你就能直接在终端看到完整的5050,而不是被截断的数值。
2. 将结果写入文件
如果需要把结果持久化,或者不想用终端输出,可以调用系统调用把结果写入文件。这种方法需要用到open、write、close等函数,步骤会繁琐一些,但适合需要保存结果的场景。
3. 通过共享内存或管道传递(适合进程间通信)
如果你的程序是作为另一个程序的子进程运行,需要把结果传递给父进程,可以用管道或者共享内存的方式。不过这种场景比较特殊,大部分情况下用标准输出就足够了。
总结一下:退出码就老老实实用来表示程序状态,传递大数值结果就用标准输出——这是最符合系统设计逻辑的做法~
内容的提问来源于stack exchange,提问作者Conor Egan

