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]