2014-02-19 6 views
1

Я нашел много вопросов по этой проблеме, однако мне не удалось запустить мой код. Моя программа должна принимать шестнадцатеричное значение, проверить, является ли он действительным шестнадцатеричным символом, а затем отобразить шестнадцатеричное значение в виде десятичного значения. Если это шестнадцатеричный символ нижнего регистра, его необходимо преобразовать в верхний регистр. Все это должно быть в цикле.Сборка: как преобразовать шестнадцатеричный ввод в десятичный?

У меня все это сделано, за исключением преобразования шестнадцатеричного в десятичное. У меня есть код в программе, я думаю, должен его преобразовать, но он не будет компилироваться. Я буду перечислять ошибки компилятора под кодом. Если код в преобразовании метки: закомментирован (за исключением последней строки, «отображение jmp»), то программа будет работать как следует, но, очевидно, не будет показывать значение как десятичное.

Компиляция с NaSMe: "NASM -fbin getChar.asm -o getChar.com -l getChar.lst"

Я бег программы в 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! 

Этот код был отредактирован и теперь компилирован и работает. Тем не менее, он по-прежнему не делает преобразование из шестнадцатеричного в десятичное правильно. Он просто не отображает значение, просто пустое. Он также повесит трубку, если будет введена буква, даже буква a-f. Число не зависает, но все же значение не отображается.

Теперь, когда у меня это работает, по крайней мере, я могу поработать над его исправлением, однако любое руководство ценится. Спасибо, Джин, за то, что вы меня запустили.

ответ

0

Операторы памяти NASM используют квадратные скобки для обозначения разыменования. Так, например, вы хотите:

mov al, [HNUM] 
    div byte [D] 
    mov [HNUM], al 

NASM Manual объясняет это. RTFM!

Без кронштейнов эти метки обрабатываются как непосредственные операнды, равные адресу ячейки памяти. Первая строка не является синтаксической ошибкой, но вызывает загрузку al младшим байтом адреса HNUM. Не то, что вы хотели. Ошибка div является ошибкой, так как 8086 не имеет инструкции делиться на ближайшее количество. И mov - это бессмыслица, потому что вы не можете написать прямое значение.

Таким образом, сообщения об ошибках сообщают вам, что не так. В строках, на которые делается ссылка, операнды не соответствуют их инструкциям.

Добавление

Я пошел вперед и установил DOSBox и NASM. На самом деле NASM не так умен, как MASM, о выводе типов операндов. Поэтому для инструкции div вам необходимо byte, (не word), как показано на рисунке выше. Я не мог понять ваш алгоритм. Это сложнее, чем необходимо.Вот моя версия:

; This program gets a hex digit from user and prints it out as a decimal 

     org 100h  ; program start point 

section .data 

msgIn: DB  13, 10, "Enter a hex digit or q to quit: $" 
msgErr: DB  " isn't hex. Must be 0-9, A-F, or a-f.$" 
msgOut: DB  " has decimal value $" 
buffer: DB  "xxxxx" 
endBuf: DB  ".$" 
ten: DB  10 

section .text 

continue:    ; start user interaction 
     mov dx, msgIn ; offset address of message to display 
     mov ah, 9  ; print string function 
     int 21h 

get_hex_digit: 
     mov ah, 1 
     int 21h   ; read character into al 

check_for_quit: 
     cmp al, 'q'  ; handle quit character 
     je exit 
     cmp al, 'Q' 
     je exit 

check_for_digit: 
     cmp al, '0'  ; handle 0-9 
     jl check_for_upper 
     cmp al, '9' 
     jg check_for_upper 
     sub al, '0'  ; convert to numeric value 
     jmp print_decimal 

check_for_upper: 
     cmp al, 'A'  ; handle A-F 
     jl check_for_lower 
     cmp al, 'F' 
     jg check_for_lower 
     sub al, 'A'-10 ; convert to numeric value 
     jmp print_decimal 

check_for_lower: 
     cmp al, 'a'  ; handle a-f 
     jl handle_digit_error 
     cmp al, 'f' 
     jg handle_digit_error 
     sub al, 'a'-10 ; convert to numeric value 

print_decimal:   ; print al contents as decimal 0-255 
     mov di, endBuf ; set buffer pointer to char after digits 
next_digit: 
     dec di   ; advance buffer pointer to next char 
     xor ah, ah  ; clear high byte of ax for division 
     div byte [ten] ; ah = ax % 10, al = ax/10 
     add ah, '0'  ; convert ah to ascii 
     mov [di], ah ; copy to buffer 
     or al, al  ; set condition codes with al 
     jnz next_digit ; jump if more digits to print 

print_digits: 
     mov dx, msgOut ; offset address of message preamble 
     mov ah, 9  ; print string function 
     int 21h 
     mov dx, di  ; offset address of converted digits 
     mov ah, 9  ; print string function 
     int 21h 

     jmp continue ; otherwise, get next input 

handle_digit_error: 
     mov dx, msgErr ; offset address of message to display 
     mov ah, 9  ; print string function 
     int 21h 
     jmp continue 

exit:     ; exit program 
     mov ah, 4ch  ; exit to DOS function 
     int 21h   ; see you later! 
+0

спасибо за ответ, я дам этот снимок. – Beetle

+0

Это исправило это, мне также нужно было добавить слово, прежде чем использовать его. Я исправил код с исправлениями. Хотя я не получаю нужных результатов, теперь он работает. – Beetle

+0

Я сомневаюсь, что вам нужен спецификатор размера 'word', поскольку переменные являются байтами. –

0

check_for_upper:

cmp al, 'A'  ; handle A-F 
    jl check_for_lower 

это должно пойти быть:

jl handle_digit_error 

, как UCase "А" 41h и LCASE "а" 61h

Смежные вопросы