0

Can someone please explain what's up with this code? I thought I understood this, but apparently I don't.

    global main
    extern printf
    extern scanf

section .data

numberFormat:   db '%d', 10, 0

section .text

  main:

    push rbp        
    mov r8, 2       

  loop:

    add r8, 1
    mov rdi, numberFormat
    mov rsi, r8
    mov rax, 0
    call printf

    cmp r8, 15
    jl loop

    mov rax, 0      ; normal exit
    ret

my question is, why does this print out only number 3 instead of all numbers between 3 and 15

iPodpadec
  • 21
  • 8
  • If you assemble and run it the output should give you a good idea of what the code does. Things that are important to know: Linux x86-64 calling convention for variadic functions like printf, and understanding how the _C_ library printf works As well this code is missing a `pop rbp` before the `ret` so you likely have a crash – Michael Petch Dec 05 '17 at 20:49
  • What's your question specifically? What is wrong with it? Does it fail to link or fail at runtime? – Chuck Walbourn Dec 05 '17 at 20:50
  • Note that writing conforming x64 native assembly for Windows is challenging because you have to follow some specific alignment rules for the exception-unwinding. See [MSDN](https://learn.microsoft.com/en-us/cpp/build/unwind-helpers-for-masm) – Chuck Walbourn Dec 05 '17 at 20:51
  • Im writing on linux. @ChuckWalbourn my question is, why does this print out only number 3 instead of all numbers between 3 and 15. – iPodpadec Dec 05 '17 at 20:56
  • 1
    Because r8 is a volatile register (caller saved) and it is being overwritten by `printf`. You could use RBX, RBP, R12–R15 which are preserved across a function call. – Michael Petch Dec 05 '17 at 21:02
  • @MichaelPetch Adding pop rbp doesn't fix this problem. Program executes without crashing, it just doesnt do what i want it to haha – iPodpadec Dec 05 '17 at 21:02
  • You cannot use r8 to store your counter `Of these, %rax​, %rcx​, %rdx​, %rdi​, %rsi​, %rsp​, and %r8-r11​ are considered caller-save registers, meaning that they are not necessarily saved across function calls` from some reference about x86-64 bits programming. – rafix07 Dec 05 '17 at 21:03
  • @MichaelPetch could you convert your comment to an answer, so i can make it an answer. This solved my problem. Thanks to rafix07 aswell! – iPodpadec Dec 05 '17 at 21:07
  • I'm pretty sure this is a duplicate of another question. But you have my blessing to answer your own question. – Michael Petch Dec 05 '17 at 21:08
  • This question is close in nature to: https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call – Michael Petch Dec 05 '17 at 21:09
  • Possible duplicate of [What registers are preserved through a linux x86-64 function call](https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call) – Michael Petch Dec 05 '17 at 21:10
  • @MichaelPetch There are many similar questions. I however didnt find straight answer:/ – iPodpadec Dec 05 '17 at 21:11

1 Answers1

2

Because r8 is a volatile register (caller saved) and it is being overwritten by printf. You could use RBX, RBP, R12–R15 which are preserved across a function call. – Michael Petch

iPodpadec
  • 21
  • 8