1

I'm learning low-level things, and I've tried to write and execute a simple program, that prints the ASCII-code of entered character..

section .bss
    i   resb 1
    o   resb 8
    ; i for input, o for output

section .text
    global _start
_start:
    mov eax, 3
    mov ebx, 0
    mov ecx, i
    mov edx, 1
    int 0x80
    ; get one char

    mov ecx, o
    add ecx, 7
    mov edx, 0
    ; set ECX point at last of 8 bytes labeled o
    while:
        mov al, [i]
        mov bl, 0
        cmp al, bl
        jz  end
        mov bl, 10
        div bl
        add ah, '0'
        mov [i], al
        mov [ecx], ah
        dec ecx
        inc edx
        jmp while
    end:
    ; algo - to decimal

    mov eax, 4
    mov ebx, 1
    int 0x80
    ; ECX ready - was decremented until highest non-zero digit in loop
    ; so is EDX - incremented digit count times

    mov eax, 1
    mov ebx, 0
    int 0x80

Successfully compiled (nasm) and linked (ld), but at runtime:

Floating point exception (core dumped)

Once already fixed (really put 0 instead of 10 somehow), and it worked well, but was just intermediate test (printed digits in reversed order). Then I reserved 8-byte field to accumulate loop calculations right through left, and interrupt 4,1,..,.. after end, what brought me to some funny CPU stuff again.

Raping Google gave no result. What's wrong? Thanks in advance.

UPD: if you explore SOF questions on this subject because of a serious trouble with core dump exception, don't waste your time on this topic, in my case an epic and already solved problem occurred inside my head, made some school-level mistake.

  • This is not necessarily a floating point exception. Check if you aren't integer-dividing by zero. If you have a core dump, this should be pretty easy to inspect : fire up your debugger and print out the contents of the registers. – Daniel Kamil Kozar Jan 27 '18 at 22:09
  • Try using a debugger to find out where exactly your code crashes. – fuz Jan 27 '18 at 22:26
  • gdb register info showed: RAX is 300A (so AL is ten - ok, hundred div ten = ten, but why AH not zero), RBX is A (so divisor set correct - ten), RCX is some big number (should be, I use it as offset), RDX is 1. The last one tells me that loop worked well 1 time, but then crashed. I have no idea WTH is wrong. – Polazhinets.A Jan 27 '18 at 22:42
  • BTW, your loop is over-complicated. You don't need to store/reload `i`, or mess around with 8-bit partial registers. (On some CPUs, `div r8` is slightly faster than `div r32`, but if you cared about performance you'd multiply by a fixed-point inverse of 10 instead of using `div` at all. See https://stackoverflow.com/questions/13166064/how-do-i-print-an-integer-in-assembly-level-programming-without-printf-from-the/46301894#46301894 for the simple way (with Linux system calls) and the fast way, using the same (good) pointer-decrement method of filling a buffer you're using. – Peter Cordes Jan 28 '18 at 03:45

1 Answers1

1

Replace mov al, [i] with movzx ax, [i].
You are leaving at least 0x30 in ah which leads to ax >= 0x3000 that in turn prevents the result of the division between ax and 10 to fit in al.

ah is not zero because div bl sets it (it is the remainder of the division) but it is never cleared after the loop jumps back.
This also means that the first iteration works by accident: ah is initially zero because SYS_READ is 3 and thus the needed mov eax, 3 sets ah to zero before the loop is entered.

Also, you are not correctly setting the starting address of the string to print (it's always one byte less).

Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124