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

      

+3


source to share


4 answers


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.

+4


source


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

      

+3


source


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).

+1


source


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 ...

      

0


source







All Articles