【问题标题】:Translate pseudo code to assembly将伪代码翻译成汇编
【发布时间】:2015-11-05 20:29:07
【问题描述】:

我正在尝试将一些 C 伪代码转换为 i386 汇编代码,但从未正确完成。

n=1;
s=50;
a=0;  
while(n > 0) {
   a=s/n;
   n=n-1;
}
print a;

上面的代码要通过编译器翻译成汇编代码,结果是:

.data
variables: .space 104
msg: .asciz "Message %d\n"
.text
.global main
main:
    push    $1
    pop variables+52
    push    $50
    pop variables+72
    push    $0
    pop variables+0
L000:
    push    variables+52
    push    $0
    pop %ebx
    pop %eax
    cmp %ebx,%eax
    jl  L001
    push    variables+72
    push    variables+52
    pop %ebx
    pop %eax
    xor %edx,%edx
    idivl   %ebx
    push    %eax
    pop variables+0
    push    variables+52
    push    $1
    pop %ebx
    pop %eax
    sub %ebx,%eax
    push    %eax
    pop variables+52
    jmp L000
L001:
    push    variables+0
    push    $msg
    call    printf
    add $8,%esp
leave
ret

我无法让代码正确运行。它会导致分段错误。我得到的输出是:

Message 0
Segmentation fault (core dumped)

【问题讨论】:

  • 您知道有一个mov instruction 允许您将值移入和移出内存到寄存器。您使用一种效率较低的方法将事物压入堆栈并将它们弹出到目的地。
  • 如果 n 最初 > 0,这将简化为 a = s/1(即只是 s),否则保持 a 不变。实际上不需要在 asm 中创建循环。

标签: gcc assembly i386


【解决方案1】:

错误是“被零除”。 jl L001 如果 (njle L001(jle = 如果小于或等于则跳转)。

另外,leave 是错误的。没有需要反转的序言。删除它。

【讨论】:

  • 谢谢。我已经在这个编译器上工作了三天多一点,我的头开始有点乱了。
  • @seb :我建议使用 GCC -g3 选项进行编译以添加调试信息。然后使用 GNU 调试器 (gdb) 单步执行您的代码。更容易看到您的代码出了什么问题以及导致错误的原因。