2017-04-23 267 views
-3

我无法理解如何将此汇编代码转换为C.它非常短,只有几行,答案应该是一行代码。如何将汇编代码转换为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 
} 
+0

它只是'putchar(P1);' –

+0

询问某人做你的工作的问题不适用于StackOverflow。向我们展示您迄今为止所尝试的内容以及您遇到困难的地方,我们很乐意为您提供帮助。 –

+0

@olivercharlesworth这是一个很好的笑话,但你为什么改变链接? –

回答

2
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编译器会为你隐式执行,所以没有必要明确地显示扩展转换。

+0

谢谢,这是非常有帮助的。我唯一的困惑是程序集中subq和addq的用途。你能否详细说明一下? – ninchicken

+0

不知道还有什么我可以说,我没有说过。查看堆栈如何在x86架构上工作。当你想在栈上分配空间时,你从栈指针中减去;当你想释放这个空间时,你添加到堆栈指针。堆栈指针总是存储在“ESP”寄存器中,所以这就是'sub'和'add'指令的作用。我也已经解释了*为什么*它正在这样做,即使你没有使用堆栈:'putchar'函数显然期望这是它的调用约定的一部分。这是依赖于实现的,所以我不能说更多。 –

+0

@ninchicken:因为[64位系统V ABI](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf)需要它。在_3.2.2堆栈帧_它说“_输入参数区域的末尾应对齐在一个16(32或64,如果 __m256或__m512被传递堆栈)字节边界。换句话说,值 ( %rsp + 8)总是16(32或64)的倍数,当控制转移到函数入口点 。堆栈指针%rsp始终指向最后分配堆栈的结尾frame_“ –