大会:如何转换输入十六进制为十进制?(Assembly: How to convert hex in

2019-10-19 09:09发布

我发现在这个问题上的许多问题,但是,我一直没能得到我的代码运行。 我的程序应该采取十六进制值,检查,看它是否是一个有效的十六进制字符,然后显示的十六进制值作为一个十进制值。 如果它是一个小写十六进制字符那么它需要被转换为大写。 这一切都需要在一个循环。

我有这一切,除了转换十六进制到十进制完成。 我已经在计划中,我认为应该把它转换的代码,但它不会编译。 我将列出下面的代码的编译器错误。 如果在标签转换的代码:被注释掉了(除了最后一行,“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!

上面已经被编辑和现在的代码编译和运行。 但是,现在还没有从十六进制做转换为十进制正确。 它根本不显示数值,只是空白。 它也将自动挂断,如果输入一个字母,甚至一个字母AF。 一些不挂起来,但还是不显示的值。

现在,我有它运行至少我可以修复它的工作,然而,任何指导表示赞赏。 由于基因的让我和运行。

Answer 1:

NASM存储器操作数用方括号来表示取消引用。 因此,例如,你会想:

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

在NASM手册说明这一点。 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!


Answer 2:

check_for_upper:

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

这应该是:

    jl handle_digit_error

作为UCASE “A” 是41H和LCASE “a” 是61H



文章来源: Assembly: How to convert hex input to decimal?