Home > Net >  Only the last 2 digits are being printed when converting to ASCII? [x86_32]-NASM
Only the last 2 digits are being printed when converting to ASCII? [x86_32]-NASM

Time:11-14

My code below, for some reason only outputs the last 2 digits of the number, regardless of how long the umber is... Can someone please tell me the issue/how to fix? Of course I want to print out the whole number, but it isn't letting me. please help, thank you

global _start

section .text
_start:
    mov eax, 6789       ; The number to be printed
    mov ebx, 0          ; count the digits
    mov ecx, 10         ; divisor

divide:
    mov edx, 0
    div ecx             ; divide the number into eax and edx | for 6789, eax = 678, edx = 9
    push ebx            ; push current count into the stack
    inc ebx             ; increase the number of digits
    push edx            ; push the value of remainder into the stack
    cmp eax, 0          ; check if eax = 0, means all digits are pushed into the stack
    jne divide

; Stack at the end of divide: (entry from left): 6, 3, 7, 2, 8, 1, 9, 0 ]
print:
    pop edx             ; take out the value pushed previously in the stack
    add edx, 0x30       ; Convert to ASCII
    mov [digit], edx    ; Save the value of edx to digit
    mov eax, 4          ;\
    mov ebx, 1          ; |---> use sys_write to print on screen
    mov ecx, digit      ; |
    mov edx, 1          ;/
    int 0x80

    pop ebx             ; Restore value of count to ebx from the stack
    cmp ebx, 0          ; compare whether count is equal to 0
    jnz print           ; if not 0, go back to print and print the next digit on the screen


concl:
    mov eax, 1
    mov ebx, 0
    int 0x80


section .data
    digit db 0

I have used gdb-(GEF) for debugging and the stack seems to be functioning properly, same with all the registers.

An example output would be for the number: 6789 The output is: 89

CodePudding user response:

A bad case of line continuation

mov [digit], edx    ; Save the value of edx to digit
mov eax, 4          ;\
mov ebx, 1          ; |---> use sys_write to print on screen
mov ecx, digit      ; |
mov edx, 1          ;/

Don't inadvertently put a backslash character at the end of a line because the assembler will consider it to be the signal for line continuation, which means that the line that follows gets stitched to the current line, and in your case it produces this:

mov [digit], edx    ; Save the value of edx to digit
mov eax, 4          ;    mov ebx, 1          ; |---> use sys_write to print on screen
mov ecx, digit      ; |
mov edx, 1          ;/

The part that loads EBX with the reference to STDOUT is now behind the semicolon and became a mere comment in the program. You won't find it in the executable file. The print loop will be using whatever happens to be in EBX.

In your test run with the number 6789, the first 2 iterations of the print loop were using EBX=4 and EBX=3, but the last 2 iterations were using EBX=2 and EBX=1. Now STDERR=2 and STDOUT=1, and both write to the screen. That's why you only ever got output for the last 2 digits.

Notwithstanding that you should write mov [digit], dl instead of mov [digit], edx, the code seems correct. Your unusual choice to double push is matched by double pop, so that is fine. You just need to remove that unlucky \

  • Related