0

I've a problem with my assembly code.I want to convert the user input character between A-F into their respective decimal number.

Sample output:

Enter a character from A-F: B In decimal it is 11.

I can't handle the conversion.please help me.Thanks This is the code

.model small
.stack 100h
.data
        msg1 db 'Enter a character from A_F:$ '
        msg2 db 'In decimal it is:$'
        char db ?
.code
MAIN PROC
        mov ax,@data
        mov ds,ax

        mov ah,09h                ;Displaying msg1
        mov dx,offset msg1
        int 21h
        mov ah,01h                ;Taking input
        int 21h
        mov char,al

        mov ah,2                    ;For go to next line
        mov dl,0dh
        int 21h
        mov dl,0ah
        int 21h                        ;Displaying msg2
        mov ah,09h
        mov dx,offset msg2
        int 21h                
        mov ah,02h          ;converting character   
        sub char,30h
        mov dl,char
        int 21h

        mov ah,4ch
        int 21h
MAIN ENDP
END MAIN
hamxa rajput
  • 1
  • 1
  • 4

1 Answers1

0

so you can cheat and just have a lookup table (there is an even simpler cheat). But the right way is to just do the math. You have to convert from base 2 or technically base 16 to base 10. Tou can easily move around from base 2 to base 8 (octal) to base 16 (hexadecimal) with just bit manipulation because 8 and 16 are powers of 2. But 10 is not a power of 2 you cannot do this with bit manipulation.

One that we are more familiar with is time base 60 for hours minutes seconds. 1 hour is 60 minutes one minute is 60 seconds so how many hours is 4321 seconds? how do you solve that? how many seconds in an hour? 60*60 = 3600 right? two hours is 7200 seconds so 4321 is somewhere between one and to, exactly it is 4321/3600 or 1 remainder 721. or 1 hour 721 seconds. how many minutes in 721 seconds? 721/60 = 12 remainder 1 so 4321 seconds is 1 hour 12 minutes 1 second. just for a check 3600*1 + 12*60 + 1 = 4321. or (60^2)*1 + (60^1)*12 + (60^0)*1 - 4321.

What about 0x1234 to decimal? our calculator tells us 4660. the short answer is work your way down in powers of 10 that are at or higher than the number. so a 16 bit number cannot be larger than 65535 so 10000ths place or 10^4. 0x1234 / 10000 = 0 remainder 0x1234. take the remainder 0x1234 / 1000 = 4 remainder 0x294 (660), take the remainder 0x294 / 100 = 6 remainder 0x3C (60), take the remainder 0x3C / 10 = 6 remainder 0, take the remainder 0 / 1 = 0. grab all the quotients 04660 so the answer is 4660 decimal.

So the letter B is the ascii number 0x42, lower case 0x62 so you have to be careful there. 0x42 - 0xB = 0x37.

So subtracting off 0x30 from the ascii characters 0-9 gives you the number 0 - 9. But if you know/assume this is a (hex) number and it is greater than 0x39 then subtract off 0x37 instead. 0x42 - 0x37 = 0xB, 0x62 - 0x37 = 0x2B, you can and with 0xF and clean that up for upper vs lower case.

4 bits the largest number is 15 so to convert from base 2/16 to base 10 we only need to deal with 10^1 and 10^0. so 0xB / 10 = 1 remainder 1 1/1 = 1, take the quotients 0xB = 11 decimal.

the simplest cheat here is if your inputs are limited between 0xA and 0xF that is 10 to 15. you know that all the numbers divided by 10 are 1 remainder 0 to 5. so just subtract off 10 and you get 0 to 5.

Next problem, you are taking 0x42 (character B) and subtracting off 0x30, that is a 0x12, device control one on the ascii chart basically makes no sense to try to use int21 ah = 2 with that character. to print out the number 11 you need to print a 0x31 then another 0x31. if your input was F the answer is 15 you send out a 0x31 and a 0x35. the cheat is to take 0x46 your input ('F'), subtract off 0x37 to get 0xF, then subtract off 10 to get 0x5, print the 0x31 for the 10 then add 0x30 to the 0x5 to get 0x35 and print that. you can combine the 0x37 and 10 subtraction to 0x41.

'A' = 0x41,  0x41 - 0x41 = 0x00, 0x00+0x30 = 0x30 = '0'
'B' = 0x42,  0x42 - 0x41 = 0x01, 0x01+0x30 = 0x31 = '1'
'C' = 0x43,  0x43 - 0x41 = 0x02, 0x02+0x30 = 0x32 = '2'
'D' = 0x44,  0x44 - 0x41 = 0x03, 0x03+0x30 = 0x33 = '3'
'E' = 0x45,  0x45 - 0x41 = 0x04, 0x04+0x30 = 0x34 = '4'
'F' = 0x46,  0x46 - 0x41 = 0x05, 0x05+0x30 = 0x35 = '5'

or even more optimized to your specific input limits

'A' = 0x41, 0x41 - 0x11 = 0x30 = '0'
'B' = 0x42, 0x42 - 0x11 = 0x31 = '1'
'C' = 0x43, 0x43 - 0x11 = 0x32 = '2'
'D' = 0x44, 0x44 - 0x11 = 0x33 = '3'
'E' = 0x45, 0x45 - 0x11 = 0x34 = '4'
'F' = 0x46, 0x46 - 0x11 = 0x35 = '5'

you might want to go so far as to limit check and if the input character is less than 0x41 or greater than 0x46 maybe output a '?' (0x3F) instead of a numeric response.

so your conversion is wrong in two ways, first you are forgetting it takes two characters to output the numbers between 10 and 15. second the result of your math needs to be a character that makes sense (between 0x30 and 0x35)

old_timer
  • 69,149
  • 8
  • 89
  • 168