汇编:如何将十六进制输入转换为十进制?

时间:2014-02-19 03:56:21

标签: assembly hex decimal x86-16

我在这个问题上找到了很多问题,但是,我无法运行我的代码。我的程序应采用十六进制值,检查它是否是有效的十六进制字符,然后将十六进制值显示为十进制值。如果它是小写十六进制字符,则需要将其转换为大写。所有这些都需要循环。

除了将十六进制转换为十进制之外,我完成了所有这些操作。我有程序中的代码,我认为应该转换它,但它不会编译。我将列出代码下面的编译器错误。如果标签convert:中的代码被注释掉(除了最后一行,“jmp display”),那么程序将按原样运行,但显然不会将值显示为小数。

使用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,它也会挂断。数字不会挂起,但仍然不会显示值。

现在我已经运行了至少我可以修复它,但是,任何指导都表示赞赏。感谢Gene让我开始运行。

2 个答案:

答案 0 :(得分: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!

答案 1 :(得分:0)

check_for_upper:

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

这应该是:

    jl handle_digit_error

因为Ucase“A”是41h,Lcase“a”是61h