assembly - call printf with 64 bit memory content

0

I want to add the number 0xFFFFFFFF with himself and then print the result to screen. For this, I'm using the memory location result to hold the results (that may be up to 64bit). In order to call printf, I need to push it to stack but this: push qword [result] not compiled. there is any way to send the 64 bit number to printf?

section .data
fmt1: dq "%x", 10, 0
result: dd 0,0

section .text
    extern printf  

assFunc:

mov edx,0
mov eax, 0xFFFFFFFF
add eax, 0xFFFFFFFF
adc edx,0


mov [result],edx
mov [result+4],eax

push [result]
push fmt1
call printf
add esp,8 
assembly
x86
asked on Stack Overflow Apr 26, 2020 by go vegan • edited Apr 26, 2020 by Jester

1 Answer

3

There are a few mistakes in your code.

The fmt string is defined with dq which defines groups of QWORDs (64-bit items). This has the effect of padding (with zero bytes) every string to multiple of 8 bytes.
In this case, you would lose the new line char.
Use db instead.

It's also better to follow the little endian convention and store the high part of a number in the higher addresses.
edx is the high part of the result, store it in [result + 4] and store eax (the lower part) in [result].
This makes it easy for other programmers to reason about your code. By the same length, you can also use xor edx, edx to set edx to zero.

Finally, the printing part.
First of all, the correct format string is %llx since the model used by the mainstream compilers in 32-bit mode is LL64 (i.e. long is still 32 bits, while long long is 64 bits).

The ABI says you have to pass long long arguments on the stack and that their alignment is 4 bytes (which means, you don't have to add any padding).
Furthermore, the ABI mandates that the stack to be aligned on 16 bytes boundary just before the call instruction but, by sheer luck, using three pushes is what was needed to keep it aligned anyway. Since x86 are little endian machines, this can be accomplished with:

push DWORD [result+4]
push DWORD [result]
push fmt1
call printf
add esp, 10h

The whole code:

SECTION .data

  fmt1:   db "%llx", 10, 0
  result: dd 0, 0


SECTION .text

    EXTERN printf  

assFunc:

  mov edx,0
  mov eax, 0xFFFFFFFF
  add eax, 0xFFFFFFFF
  adc edx,0

  mov [result],eax
  mov [result+4],edx

  push DWORD [result+4]
  push DWORD [result]
  push fmt1
  call printf
  add esp, 0ch 

  ret

Note that you don't actually need to store the result in the result variable, you can

push edx
push eax

directly, instead of

push DWORD [result+4]
push DWORD [result]
answered on Stack Overflow Apr 26, 2020 by Margaret Bloom

User contributions licensed under CC BY-SA 3.0