32-bit NASM: Print the contents of the printf register
I am new to assembly. I have a different output for the following simple code from the expected one. each time before the call, the printf
content eax
is shifted to the right by some number. What am I doing wrong? Thank.
code:
;file name : testing.asm
;assemble and link with:
;nasm -f elf testing.asm && gcc -m32 -o testing testing.o
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 15 ; int a=15
str: db "content in eax=%d", 10, 0
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
mov ebp, esp
mov eax, [a] ; put a from store into register
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
shr eax, 1
push eax ; eax content should be 1>>1 = 0
push dword str
call printf ; printf(str,content_of_eax)
mov esp, ebp ; takedown stack frame
mov eax, 0 ; normal, no error, return value
ret ; return
Output:
content in eax=7
content in eax=4
content in eax=8
Expected Result:
content in eax=7
content in eax=1
content in eax=0
source to share
printf
returns its result to eax
, the original value is lost.
You have to reload it from [a]
or use a register that is saved in function calls such as esi
, but you also have to save and restore it before returning to the caller. You must place the arguments passed in printf
with add esp,8
after each call to maintain stack consistency.
source to share
In the data section, you can just use equate for a
, since you only use this variable once and don't change it (I'll name it value
).
fmt db "content in eax=%d",0xa,0
value equ 15
In the main function, I'm pretty sure (correct if I'm wrong) that you must save the underlying pointer before updating it with the stack pointer.
main:
push ebp
mov ebp, esp
Now you can create a local variable to store the current value you are working on.
sub esp, 4
From there, you just continue fetching, moving, and storing the value on the stack before each call printf
.
mov eax, value ; move 15 into eax
shr eax, 1 ; make first shift
mov dword[ebp-4], eax ; store result in local variable
push eax ; eax = 7
push fmt
call printf
add esp, 8 ; clean eax & fmt off the stack
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 2 ; make second shift
mov dword[ebp-4], eax ; store result back in variable
push eax ; eax = 1
push fmt
call printf
add esp, 8
mov eax, [ebp-4] ; fetch last shift result from variable
shr eax, 1 ; make last shift
push eax ; eax = 0
push fmt
call printf
add esp, 8
add esp, 4 ; clean local variable
And then remember, before you get back when you free the stack frame, which you also reclaim (pop) the base pointer.
mov esp, ebp
pop ebp
This should output:
content in eax=7
content in eax=1
content in eax=0
source to share
Remember that printf will return the number of characters sent to the output. So when you do this:
call printf ; printf(str,content_of_eax)
shr eax, 2
You are actually changing the printf result:
- "content in eax = 7 \ n" is 17 characters, so shitfting by 2 gives: 17/4 = 4
Before transferring, you need to store the value (either in a stored register, or on the stack, or in memory).
source to share
This answer seems to be not the best solution, I am currently keeping it due to the discussion below
Like others, printf
will return the result in eax. The result of printf is the number of bytes written.
Since you pushed the result of the operation shr
onto the stack, you can get them again using pop
, for example:
shr eax, 1 ; eax content should be 15>>1 = 7
push eax
push dword str ; string to be printed
call printf ; printf(str,content_of_eax)
pop eax
pop eax
shr eax, 2
push eax ; eax content should be 7>>2 = 1
push dword str
call printf ; printf(str,content_of_eax)
# and so on ...
source to share