I'm trying to call printf to print an integer, put it doesn't print the right value:
section .data
an: db 1
format: db "num: %d" , 10, 0
section .text
global main
extern printf
main:
push ebp
mov ebp,esp
mov eax, [an]
push eax
push dword format
call printf
add esp, 8
mov esp,ebp
pop ebp
mov eax, 0
ret
this code prints "num: 1836412417"
put when I try to print a char it works!
section .data
an: db 'a'
format: db "num: %c" , 10, 0
section .text
global main
extern printf
main:
push ebp
mov ebp,esp
mov eax, [an]
push eax
push dword format
call printf
add esp, 8
mov esp,ebp
pop ebp
mov eax, 0
ret
now it prints "num: a"
so what's wrong with the first code ?!!
db
declares 8-bit (one byte) values, while %d
prints 32-bit (four byte) values on x86.
In effect, when loading 32-bit register eax
with mov eax, [an]
you are loading bits of letters "num"
to high bytes of the register. They are later printed as number, when using %d
or ignored when using %c
.
To declare 32 bit values you should use dd
, instead of db
.
@zch pointed out the issue. But if you really do want to print out a byte data item as an integer and don't have the luxury of redefining it, you can do it this way:
movsx eax, BYTE [an] ; [an] is a byte value to be printed with %d
push eax
push dword format
call printf
The movsx
instruction sign extends an 8-bit or 16-bit operand (in this case, the 8-bit operand, [an]
) into the 32-bit register, eax
. If it is unsigned, then you'd use movzx eax, [an]
(zero fill).
Normally in C, the promotion to integer is done implicitly. But in assembly, you need to do that yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With