0

I've been trying to write an assembly procedure that prints a number. I wrote the procedure printc that prints a single character:

printc: push    ebp
        mov     ebp, esp

        mov     eax, 4
        mov     ebx, 1

        add     [ebp + 8], byte '0' 
        lea     ecx, [ebp + 8]

        mov     edx, 1

        int     0x80

        mov     esp, ebp
        pop     ebp

        ret

Then I tried to write printi so:

printi: push    ebp
        mov     ebp, esp

        mov     eax, [ebp + 8]

        cmp     eax, 0
        je      end

        mov     ebx, 10
        div     ebx

        push    eax
        call    printi

        push    edx
        call    printc

end:    mov     esp, ebp
        pop     ebp

        ret

Finally, I called printi:

_start: push    32 
        call    printi

And got Segmentation fault (core dumped). Any idea why?

Oval
  • 37
  • 8
  • 1
    Please run your program in a debugger (Google how to use `gdb`) and check at which line it crashes and what values the registers had at that point. This should greatly help. – CherryDT Apr 04 '20 at 08:40
  • 1
    Did you just let execution fall off the end of `_start` after `printi` returns? If it returns... This is why we have debuggers, stop wasting your time just looking at the segfault and find out how exactly the CPU runs your code. Also use `strace ./a.out` to see if you made any system calls successfully. BTW, see also [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) for a non-recursive loop that does this more efficiently. – Peter Cordes Apr 04 '20 at 08:58
  • Another problem: You use `push` to put parameters for `printc` onto the stack but you don't `pop` or otherwise discard these stack slots anywhere. See [NASM should I pop function argument after calling a function?](https://stackoverflow.com/questions/60830765/nasm-should-i-pop-function-argument-after-calling-a-function/60831084#60831084) – ecm Apr 04 '20 at 18:14

1 Answers1

1

As Peter Cordes correctly said, your program would fall off _start and return to undefined code, if it didn't crash earlier due to infinite recursion in printi.

The reason there is infinite recursion: you probably think that div ebx divides EAX by 10. It doesn't: it divides EDX:EAX 64-bit value by EBX, and you don't control EDX.

Zeroing out EDX before DIV allows the program to print something (but not the desired output), then crash when it falls off printi.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362