为什么我的汇编代码进入无限循环?

时间:2018-09-30 14:50:36

标签: loops for-loop assembly x86

我正在尝试组装clEnqueueFillBuffer

这就是我要尝试用C语言编写的内容:

for loop

这是我的汇编代码的样子:

#include <stdio.h>
int main(){
    for(int i = 0; i < 10; i++){
        printf("%d\n", i);
    }
    return 0;
}

运行此代码时,我得到当前输出:

.text
.globl _main


loop0.0:
  movl -4(%rbp), %eax           #eax = i
  cmpl $10, %eax                #compare i with 10
  jg loop0.2                    #if 10 > i goto loop0.2

loop0.1:
  leaq _format(%rip), %rdi      #set arg1 to format
  movl -4(%rbp), %esi           #set arg2 to i
  call _printf                  #printf(format, i)

  movl -4(%rbp), %esi           #set esi to i
  addl $1, %esi                 #esi++
  movl %esi, -4(%rbp)           #i = esi
  jmp loop0.0

_main:                           #int main
  pushq %rbp
  movq %rsp, %rbp

  movl $0, -4(%rbp)              #i = 0
  jmp loop0.0                    #goto  loop0.0
  loop0.2:

  xor %eax, %eax                 #return 0;

  popq %rbp
  retq


.data
  _format:
    .asciz "%d\n"

以此类推



为什么我的代码先显示0 2 2 2 2 2 2 (应显示),然后无限显示两次?我希望我的注释是正确的,因为这是我认为每一行代码所做的。

2 个答案:

答案 0 :(得分:3)

Main不会为i分配堆栈空间,因此对printf的调用将覆盖i。

添加说明

sub $16, %rsp

紧接着

mov %rsp, %rbp

并添加

add $16, %rsp

就在

之前
pop %rbp

减去16而不是4的原因是为了保持堆栈对齐。

答案 1 :(得分:2)

不要将i保留在被call阻塞的红色区域中(请参阅@prl的答案),i保留在寄存器中

您似乎正在遵循(可怕的)反优化编译器输出样式,该输出将所有内容存储到内存中进行调试。

在函数中保存/恢复rbx,并将ebx用于i。 (要在call _printf之前保持16字节的堆栈对齐,请不要制作堆栈帧,因为您不需要为本地人使用任何堆栈空间。)

顺便说一句,这没错,但是在函数入口点之前放置一些函数体(您的循环)是非常不常规的。通常,您的代码过于复杂。这就像您从针对C函数的优化编译器中获得的东西一样。 (我没有检查https://godbolt.org/,但建议您看看。)

_main:                   #int main
    push  %rbx           # save RBX and realign the stack by 16

    xor   %ebx, %ebx
.loop:                    # do {
    mov   %ebx, %esi
    lea   _format(%rip), %rdi
    xor   %eax,%eax          # %al = 0 FP args in XMM registers
    call  _printf            # printf(format, i)

    inc   %ebx               # i++

    cmp   $10, %ebx
    jl  .loop             # }while(i<10)

    xor   %eax, %eax                 #return 0;
    pop   %rbx
    ret

 # Read-only data can go in .rodata
 # only mutable static data needs to go in .data
.section .rodata
  _format:    .asciz "%d\n"