I have found many questions on this issue, however, I have not been able to get my code to run. My program should take a hex value, check to see if it is a valid hex character, then display the hex value as a decimal value. If it is a lower case hex character then it needs to be converted to upper case. All this needs to be in a loop.
I have all of this done except for converting the hex to decimal. I have the code in the program I think should convert it, but it will not compile. I will list the compiler errors below the code. If the code in the label convert: is commented out(except for the last line, "jmp display") then the program will run as it should, but obviously will not show the value as a decimal.
Compiling with nasme: "nasm -fbin getChar.asm -o getChar.com -l getChar.lst"
I am running the program in dosbox.
; This program gets a char from user and prints it out as a decimal
org 100h ; program start point
section .data
msgIn: DB 13, 10, "Enter a Hex Digit: $"
msgOut: DB 13, 10, "Decimal Value: $"
msgOpt: DB 13, 10, "Enter another?(y or n): $"
errMsg: DB 13, 10, "Illegal character, Enter 0..9 or A..F: $"
HNUM: DB 19H
NUM: DB 0
D: DB 10h
H: DB 16
CNT: DB 0
section .text
continue: ; start of loop
mov dx, msgIn ; offset address of message to display
mov ah, 9 ; print string function
int 21h
mov ah, 1 ; keyboard input sub-program
int 21h ; read character into al
mov cl, al
legal: ; compare input to see if valid
cmp cl, 48 ; cl < 0
jl end_if ; yes, error msg
cmp cl, 70 ; cl > F
jg check_case ; yes, error msg
jmp prntMsg2 ; print value of input
check_case: ; check case of input
cmp cl, 97 ; cl < a
jl end_if ; yes, error msg
cmp cl, 102 ; cl > f
jg end_if ; yes, error msg
jmp to_upper ; need to send to function to convert to upper case
; then pass to prntMsg2
to_upper:
and al, 223 ; convert to upper case(0DFh)
jmp prntMsg2
end_if: ; error message if invalid input
mov ah, 9
mov dx, errMsg ; print error message
int 21h
jmp continue ; get a new value
prntMsg2: ; print second message*****
mov dx, msgOut ; offset of second message
mov ah, 9 ; print string function
int 21h ; display message
convert:
mov cx, 00
mov dx, 00
L6: mov ax, 00
mov al, [HNUM]
div word [D]
mov [HNUM], al
mov bx, ax
mov cl, 0
mov ax, 1
L5:
cmp cl, 00
je L7
mul word [H]
sub cl, 1
jmp L5
L7:
mul bh
add dx, ax
add word [CNT], 1
cmp word [HNUM], 0
jg L6
mov [NUM], dl
jmp display
display: ; display character
mov dl, al
mov ah, 2 ; print char function
int 21h
mov ah, 9 ; see if user wants to do it again
mov dx, msgOpt
int 21h
mov ah, 1
int 21h
mov bl, al
cmp bl, 'y' ; bl = y
jne exitPrg ; no, end
jmp continue ; get a new value
exitPrg: ; exit program
mov ah, 4ch ; exit to DOS function
int 21h ; see you later!
The code above has been edited and now compiles and runs. However, it is still not doing the conversion from hex to decimal correctly. It simply doesn't display a value, just blank. It will also hang up if a letter is entered, even a letter a-f. A number does not hang it up, but still a value is not displayed.
Now that I have it running at least I can work on fixing it, however, any guidance is appreciated. Thanks Gene for getting me up and running.
NASM memory operands use square brackets to denote dereferencing. So for example you will want:
The NASM Manual explains this. RTFM!
Without the brackets, the labels are treated as immediate operands equal to the address of the memory location. The first line is no syntax error, but causes
al
to be loaded with the low byte of the address ofHNUM
. Not what you wanted. Thediv
is an error because 8086 has no instruction to divide by an immediate quantity. And themov
is nonsense because you can't write to an immediate value.So the error messages are telling you what's wrong. In the lines referenced, the operands do not comport with their instructions.
Addition
I went ahead and installed dosbox and NASM. Indeed NASM is not quite as smart as MASM about inferring operand types. So for the
div
instruction you needbyte
, (notword
) as now reflected above. I could not grok your algorithm. It's more complicated than necessary. Here is my version:check_for_upper:
this should go be:
as Ucase "A" is 41h, and Lcase "a" is 61h