1

can anyone explain why this code snippet goes into an infinite loop?

I presume it would have something to do with the printf function.

q1: .asciz "Hello World\n"

.global main

main:

    movq    %rsp, %rbp

    movq    $3, %rcx
    jmp     bottom

loop:
    movq    $0, %rax
    movq    $q1, %rdi
    call    printf

bottom:
    decq    %rcx
    cmpq    $0, %rcx
    jne     loop

end:
    movq    $0, %rdi
    call    exit
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
P. Daimaou
  • 51
  • 5
  • what assembler are you using.... I'm not sure what calling convention are you using my guess is you're misusing the ABI of libc that extends printf hence printf returning -1 constantly and you're stuck in an infinite loop – DrPrItay Aug 31 '16 at 16:52
  • I am compiliing with: as hello.s -o hello.o, then: gcc -o power power.o – P. Daimaou Aug 31 '16 at 16:54
  • RCX is destroyed according to https://en.wikipedia.org/wiki/X86_calling_conventions and https://ideone.com/fork/LKBgUL. Push RCX to preserve it and pop it later to restore it. – Jose Manuel Abarca Rodríguez Aug 31 '16 at 16:55
  • oh ok thanks understand it now – P. Daimaou Aug 31 '16 at 16:59
  • 2
    Rather than use _RCX_ which can be clobbered, use one of the non-volatile registers that are preserved by the function (per the System V 64-bit ABI). As well `decq %rcx` sets the Z flag based on the result of subtraction by 1. It is unnecessary to have `cmpq $0, %rcx`. If compiling against the C runtime (which appears to be the case) you don't need to call _exit_. Put the return value in `eax` and use `ret`. As well you can take advantage of the fact updating a 32-bit register automatically zero extends to the entire 64-bit register by the CPU. – Michael Petch Aug 31 '16 at 17:20
  • Zeroing a 64-bit register can be done with something like `xor %eax, %eax` . Moving the value 3 into a register could be done with `movq $3, %ecx` – Michael Petch Aug 31 '16 at 17:23
  • It is preferable to put data in a section other than the `.text` (code) section. Data you don't intend to change (like static strings) can be put in section `.rodata` . Data that is changed can be placed in `.data` – Michael Petch Aug 31 '16 at 17:33
  • @MichaelPetch Right now, I'm trying to get an input of a value through: # scan routine exponent `subq $8, %rsp leaq -8(%rbp), %rsi movq $exp, %rdi movq $0, %rax call scanf ` How could I put the value in my counter register (right now rcx, but probably will change it to some other register) ? – P. Daimaou Aug 31 '16 at 18:36

1 Answers1

1

The only registers that the called function is required to preserve are: rbp, rbx, r12, r13, r14, r15. All others are free to be changed by the called function.

Therefore, the likelihood is that printf is modifying the rcx register, so it never goes to 0.

If you push rcx and pop it later, that would prevent it from being modified.

Note it does not appear you are pushing args for printf. I think printf takes 2 args.

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126