在汇编语言中确定返回值时遇到问题

Posted

技术标签:

【中文标题】在汇编语言中确定返回值时遇到问题【英文标题】:Having trouble determining the return value in assembly language 【发布时间】:2022-01-14 09:58:21 【问题描述】:

我是汇编语言/代码领域的新手。我觉得很难理解,但我尽力了。我只是在处理作业需要回答的一些问题时遇到了问题。

    如果我通过 echo $? 我需要找出特定程序的返回值?作为终端中的命令,我得到 10 作为答案。但是我老师的答题纸上说答案是 9。

    我需要通过检查汇编代码的转储来找出(同一程序的)main 的返回值。同样,我认为答案是 10,因为 0xa = 10。但是,答题纸再次说答案是 9。我是否需要默认从返回值中减去 1 或其他什么?如果有,为什么?

    0x000000000000069f <+0>:     55               push    %rbp
    0x00000000000006a0 <+1>:     48 89 e5         mov    %rsp,%rbp
    0x00000000000006a3 <+4>:     bf 05 00 00 00   mov    $0x5,%edi
    0x00000000000006a8 <+9>:     e8 9d ff ff ff   callq  0x64a <okfisbup>
    0x00000000000006ad <+14>:    b8 0a 00 00 00   mov    $0xa,%eax
    0x00000000000006b2 <+19>:    5d               pop   %rbp
    0x00000000000006b3 <+20>:    c3               retq   
    

当我运行程序时,使用 ./(filename),这就是我得到的。

 iteratie: 1, buffer address  : 0x7ffe4052d0e0
 iteratie: 2, buffer address  : 0x7ffe4052d1c0
 iteratie: 3, buffer address  : 0x7ffe4052d2a0
 iteratie: 4, buffer address  : 0x7ffe4052d380
 iteratie: 5, buffer address  : 0x7ffe4052d460

这是 okfisbup 的转储:

   0x000000000000064a <+0>:     push   %rbp
   0x000000000000064b <+1>:     mov    %rsp,%rbp
   0x000000000000064e <+4>:     sub    $0xd0,%rsp
   0x0000000000000655 <+11>:    mov    %edi,%eax
   0x0000000000000657 <+13>:    mov    %al,-0xc4(%rbp)
   0x000000000000065d <+19>:    movzbl -0xc4(%rbp),%eax
   0x0000000000000664 <+26>:    sub    $0x1,%eax
   0x0000000000000667 <+29>:    mov    %al,-0x1(%rbp)
   0x000000000000066a <+32>:    cmpb   $0x0,-0x1(%rbp)
   0x000000000000066e <+36>:    je     0x67b <okfisbup+49>
   0x0000000000000670 <+38>:    movzbl -0x1(%rbp),%eax
   0x0000000000000674 <+42>:    mov    %eax,%edi
   0x0000000000000676 <+44>:    callq  0x64a <okfisbup>
   0x000000000000067b <+49>:    movzbl -0xc4(%rbp),%eax
   0x0000000000000682 <+56>:    lea    -0xc0(%rbp),%rdx
   0x0000000000000689 <+63>:    mov    %eax,%esi
   0x000000000000068b <+65>:    lea    0xb6(%rip),%rdi        # 0x748
   0x0000000000000692 <+72>:    mov    $0x0,%eax
   0x0000000000000697 <+77>:    callq  0x520 <printf@plt>
   0x000000000000069c <+82>:    nop
   0x000000000000069d <+83>:    leaveq 
   0x000000000000069e <+84>:    retq

【问题讨论】:

从你的散文来看,我认为你是对的。不过,我们还没有看到大会。 -- 让你的老师解释为什么应该是 9。 如果是 10,那么它必须是 10。没有添加或减去任何内容 输出应该是 10。你的老师/导师或任何应该解释你为什么她/他认为输出是 9。这是她/他的工作。 OTOH,我们不知道 okfisbup 是什么……有什么你没有告诉我们的吗? 术语:echo $? 显示最后一个命令的“退出状态”。程序具有退出状态,它来自于 _exit() 系统调用的 arg 或由于信号导致的异常终止。从main 返回确实会导致 main 的返回值被传递给退出系统调用,因此返回值成为退出状态。 (或者至少是它的低 8 位。) 感谢您发布okfisbup 的转储。这个函数似乎做了一些递归的东西打印一些似乎与实际问题无关的缓冲区地址。它绝对不会调用exit(9)。你需要问问你的老师。从我们可以看出你的老师错了。 【参考方案1】:
    movq $0xa, %eax
    popq rbp
    retq

返回值为10。答题卡错了。

如果没有给出代码,并且使用 $?透露了 10 个。这就够了。

编辑:okfisbup 的反汇编现已发布。它只调用自己和printf

【讨论】:

我编辑了我的问题,添加了 okfisbup 的 disas 转储。我希望它有所帮助。很抱歉造成混乱。 我想知道okfisbup 玩有趣的游戏,比如弄乱它的返回地址以跳过mov $0xa, %eax,但似乎没有类似的东西。只是一个非常无聊且未优化的函数,在打印其他未使用的本地数组的地址时会递归。 @NateEldredge:如果这是我的答案,我会对一项明显不公平的家庭作业大声疾呼。它调用 exit 至少是一个合理的家庭作业。【参考方案2】:

返回值为10,你的老师错了

https://godbolt.org/z/8YsnvPahM

int main(void)

    return 10;


main:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    $10, %eax
        popq    %rbp
        ret

【讨论】:

以上是关于在汇编语言中确定返回值时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

汇编语言程序设计的一般步骤是啥?

在 Swift 字典中重置值时崩溃

使用keil编程常遇到c语言问题;main被重复定义了,如何破?

使用keil编程常遇到c语言问题;main被重复定义了,如何破?

汇编语言程序从设计到最后执行需经过哪几个步骤

如何用汇编语言读取内存值