【问题标题】:How do I translate assembly code to C? [closed]如何将汇编代码翻译成 C? [关闭]
【发布时间】:2017-04-23 16:31:12
【问题描述】:

我无法理解如何将此汇编代码翻译成 C。它很短,只有几行,答案应该是一行。

char_out:
    subq   $8, %esp
    movsbl  %dil, %edi    # Parameter 1 in %dil / %edi
    call    putchar       # put char is a C function that writes (prints)
    addq    $8, %rsp      # a single char to stdout (the screen).
    ret
void char_out(char P1)
{
    //insert here
}

【问题讨论】:

  • 只是putchar(P1);
  • 请求某人做你的工作的问题不适用于 *。向我们展示您到目前为止所做的尝试以及您遇到的问题,我们很乐意为您提供帮助。
  • @olivercharlesworth 开个玩笑,但你为什么要更改链接?
  • 我知道汇编代码中有一个指针。第一行 subq 设置标志。但我不确定下一行对 movsbl 做了什么。下一行将调用定义的 put char 方法,addq 将是 %rsp = %rsp + 8
  • 请勿将代码作为图片发布。

标签: c assembly x86


【解决方案1】:
char_out:
    # Allocate 8 bytes on the stack by subtracting 8 from the stack pointer.
    # 
    # This is done for conformance to the calling convention expected by the
    # 'putchar' function, which we're about to call.
    subq   $8, %esp

    # This is the weirdo AT&T mnemonic for the MOVSX instruction, which does a
    # move with sign extension. This means that it extends a small value
    # (here, a BYTE-sized value in DIL) into a larger value (here, a
    # DWORD-sized value in EDI), in a way that properly accounts for the
    # value's sign bit.
    # 
    # This is necessary because the 'putchar' function expects to be passed a
    # 32-bit 'int' parameter.
    movsbl  %dil, %edi

    # It's obvious what this does: it calls the 'putchar' function.
    call    putchar

    # Clean up the stack, undoing what we previously did to the stack pointer
    # at the top of the function (the 'subq' instruction).
    addq    $8, %rsp

正如 Lashane 已经评论的那样,这个汇编代码等同于以下 C 代码:

void char_out(char P1)
{
    putchar(P1);
}

或者,我想你也可以说:

void char_out(char P1)
{
    int temp = (int)P1;     // movsbl
    putchar(temp);
}

但 C 编译器会为您隐式执行此操作,因此无需显式显示扩大范围。

【讨论】:

  • 谢谢,这很有帮助。我唯一的困惑是程序集中 subq 和 addq 的目的。能详细点吗?
  • 不知道我还能说什么,我还没有说。查看堆栈在 x86 架构上的工作方式。当你想在堆栈上分配空间时,你从堆栈指针中减去;当您想释放该空间时,您添加到堆栈指针。堆栈指针始终存储在ESP 寄存器中,这就是subadd 指令的作用。我也已经解释了为什么它这样做,即使您没有使用堆栈:putchar 函数显然希望这是它的调用约定的一部分。这取决于实现,所以我不能多说。
  • @ninchicken :因为64-bit System V ABI 需要它。在 3.2.2 堆栈帧 部分中,它说“输入参数区域的结尾应在 16(32 或 64,如果 __m256 或 __m512 在堆栈上传递)字节边界上对齐换句话说,当控制转移到函数入口点时,值(%rsp + 8)总是16的倍数(32或64)。堆栈指针%rsp总是指向最近分配的末尾堆栈帧"
最近更新 更多