assemblyemu8086

Converting a 4-digit Decimal Input from ASCII to proper Integer form


I'm taking a 4 digit input and storing inside a variable. That part is perfectly fine. I can then retrieve the value and print it as well. I'm trying to convert it to integer so I can perform Arithmetic Operations on it.

This is the code I'm using:

; ASCII -> Integer

mov al, [operand1 + 2] ; Load the first digit

sub al, 30h ; Subtract 30h

mov ah, 0 ; Clear AH

mov cx, 3 ; Set the loop counter to 3

lea si, [operand1 + 2] ; Load the address of the first digit

@loop:

mov bl, 10 ; Load 10

mul bl ; Multiply AX by 10

inc si ; Increment SI

mov dl, [si] ; Load the next digit

sub dl, 30h ; Subtract 30h

adc al, dl ; Add the digit to AL with carry

loop @loop ; Repeat until CX = 0

; The result is in AX

The concept that I'm going with here is that if operand 1 stores 1234, the first digit is loaded (1) and converted to integer after having 30H subtracted from the ASCII 31H. After that I'm multiplying this digit by 10 so that the 01H eventually becomes 0aH, which is decimal 10. The one is actually in the thousands place, so by multiplying by 10 three times I hope to achieve the 1000. The next digit is being added and moved to the next higher place as well.

Is the concept that I'm trying to apply correct? The code works just fine when I enter 1234 in Operand1 but when I enter 5678 it results in 022E instead of the right 162E.

I can't figure out how to fix this.


Solution

  • Check the instruction manual for mul bl — that is doing al × bl => ax, so it is a widening 8-bit multiplication.

    The value 123 (in hex 0x7B) fits in 8 bits, so the multiplication of 123 × 10 works with the widening multiplication to yield 0x4CE (1230), and you can add 4 to that to get 1234.

    However, with the other number, 5678, 567 takes two bytes to represent, in hex we have 0x237, So doing an 8-bit multiplication, that's ignoring the upper byte and multiplying 0x37 × 10, which results in 0x226, then add the 8, to get 0x22e.


    Looks like you're also doing 8-bit addition, which will appear to work for many numbers, but try 4096 for example, and the lack of carry into ah will result in an incorrect addition.  You'll want to zero extend the next character converted from ascii to numeric to full 16-bit, then do 16-bit addition (e.g. on ax).

    So, for 4096, we have 409 × 10 = 4090, in hex 0xFFA, then a 16-bit addition of 6 will yield the proper 0x1000, whereas an 8-bit addition of 6 will be 0xFA + 6, which is 0x100, though addition is not widening so the 1 is lost, and the result of the 8-bit addition is 0x00, while the full register will then hold 0xF00, an incorrect translation of 4096.