Search code examples
assemblybinarydecimaldosnasm

Converting DEC to BIN value in dos assembly


I am reading input number in decimal format using buffered input (0Ah function of interrupt 21h), like this:

mov ah, 0Ah
mov dx, inputBuffer
int 21h

I declared the buffer this way:

inputBuffer     db  6
                db  0
                times 7 db  "$"

Now I want to cycle through the numbers and make a binary representation of this value, following code does this for me:

mov si, [inputBuffer+1]
mov di, 0
dec si

process_input_value:
xor dx, dx
mov ax, [inputValue]
mov dx, [inputBuffer+2+di]
sub dx, '0'
add ax, dx
mov bx, 10
mul bx
mov [inputValue], ax

inc di
cmp di, si
jb process_input_value

mov ax, [inputValue]
mov dx, [inputBuffer+2+di]
sub dx, '0'
add ax, dx
mov [inputValue], ax

The algorithm I use goes as follows:

  1. add number to buffer
  2. if it's not the last number multiply buffer by 10
  3. repeat

Unfortunately, when I later print out this value I always get the same output, no matter what I type in the beginning. The code that shows output (it just shows one ASCII character for each byte, but it's enough for me to notice the error):

mov ah, 2
mov dl, 10
int 21h
mov dx, [inputValue]
mov dl, dh
int 21h
mov dx, [inputValue]
int 21h
mov ah, 8
int 21h

It feels like there is a problem with the code which does the converting, but I have no idea what could be wrong.

I am using NASM.

EDIT: Answer from Guffa was just the solution I needed, it works perfectly now, thank you very much.


Solution

  • In this code you are getting two characters into dx:

    mov dx, [inputBuffer+2+di]
    

    You should be getting one character:

    xor dx, dx
    mov dl, [inputBuffer+2+di]
    

    (The clearing of dx first is so that you get a full 16 bit value so that you can easily add it to ax later.)

    Edit:

    The same when you are getting the length:

    xor ax, ax
    mov al, [inputBuffer+1]
    mov si, ax
    

    Edit 2:

    Also, as Bushmills points out, the logic that you are using to convert the value is a bit backwards. If you multiply the accumulator and then add the digit, you don't need additional code to handle the last digit, and you don't need a check to skip the loop if the input is a single digit (which was lacking in the code).

    With that logic the code would be:

    xor ax, ax
    mov di, ax
    mov al, [inputBuffer+1]
    mov si, ax
    dec si
    
    xor ax, ax
    process_input_value:
    mov bx, 10
    mul bx
    xor dx, dx
    mov dl, [inputBuffer+2+di]
    sub dl, '0'
    add ax, dx
    inc di
    cmp di, si
    jb process_input_value
    mov [inputValue], ax