我正在尝试创建一个代码,它将输入 1 个十六进制形式的 8 位数字并生成等值的十进制数。
这是我的代码:
data segment
msg1 db 10,13, "Give me a valid hex number:$"
hex1 db 0
hex2 db 0
hundred db 0
hundredrem db 0
decade db 0
decaderem db 0
unit db 0
unitrem db 0
res db 0
hundredval db 100
decadeval db 10
unitval db 1
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
L1:
mov ax,data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
mov ah,01h
int 21h
cmp al,48
jb L1
cmp al,70
ja L1
cmp al,57
jbe sethex1
cmp al,65
jae sethex1
lea dx,msg1
mov ah,09h
int 21h
sethex1:
mov hex1,al
jmp L2
L2:
mov ah,01h
int 21h
cmp al,48
jb L1
cmp al,70
ja L1
cmp al,57
jbe sethex2
cmp al,65
jae sethex2
lea dx,msg1
mov ah,09h
int 21h
sethex2:
mov hex2,al
jmp maincalc
maincalc:
cmp hex1,60
ja calclettsHex1
jb calcnumsHex1
calclettsHex1:
mov bl,hex1
sub bl,55
jmp movetoHex2
calcnumsHex1:
mov bl,hex1
sub bl,48
jmp movetoHex2
movetoHex2:
cmp hex2,60
ja calclettsHex2
jb calcnumsHex2
calclettsHex2:
mov cl,hex2
sub cl,55
jmp conv2dec
calcnumsHex2:
mov cl,hex2
sub cl,48
jmp conv2dec
conv2dec:
mov al,16
mul cl
add al,bl
mov res,al
mov al,res
div hundredval
mov hundredrem,ah
mov hundred,al
mov al,hundredrem
div decadeval
mov decaderem,ah
mov decade,al
mov al,decaderem
div unitval
mov unit,ah
mov dl,hundred
add dl,30h
mov ah,02h
int 21h
mov dl,decade
add dl,30h
mov ah,02h
int 21h
mov dl,unit
add dl,30h
mov ah,02h
int 21h
我期望代码能够工作,但随后它向我显示了一个错误对话框“Division Overflow”。所以我决定查看寄存器的值。
直到第
mov al,res
行,寄存器的状态是这样的:
并且由于 x86 处理器使用 big endian ,所以结果是预期的。然而,在下一条指令之后:
div hundredval
寄存器的状态变成这样:
这就是造成问题的原因。当 A1 = 161 时,余数保持 > 100。那么我该如何解决这个问题?
并且由于 x86 处理器使用大尾数法,
不正确! x86 使用 Little Endian:在内存中,低字节存储在高字节之前。
cmp al,57 jbe sethex1 cmp al,65 jae sethex1 lea dx,msg1 mov ah,09h int 21h sethex1:
您当前的程序错误地允许字符“:;<=>?@”通过!现在,您只需(重新)显示提示,然后愉快地继续,就好像该角色是正确的角色一样(“0123456789ABCDEF”)。
快速解决方法是:
cmp al, 57
jbe sethex1
cmp al, 65
jae sethex1
jmp L1
sethex1:
但更好的解决办法是:
cmp al, '9'
jbe sethex1
cmp al, 'A'
jb L1
sethex1:
后者允许在标签中出现掉落sethex1。
conv2dec: mov al,16 mul cl add al,bl
您输入并存储在 hex1 变量中并随后在 BL 寄存器中转换为其 [0,15] 值的第一个十六进制数字是 最高有效位。因此,that 是您必须乘以 16 的数字。
conv2dec:
mov al, 16
mul bl
add al, cl
div hundredval mov hundredrem,ah mov hundred,al mov al,hundredrem div decadeval mov decaderem,ah mov decade,al mov al,decaderem div unitval mov unit,ah
所有这些
div
操作都是字节大小,因为除数hundredval、decadeval和unitval已使用DB
定义。因此,除法将使用整个 AX 寄存器作为其被除数。div hundredval
,AX 包含 [0,255] 范围内的值,所以没问题。然而,在 div decadeval
的情况下,您加载 AL 但允许 AH 保留其最后的值。您必须事先将 AH 归零。div unitval
指令也存在同样的问题,但这里的解决方案不是将 AH 归零,而是不执行除以 1 的冗余(但有些人可能会称之为愚蠢)操作。您的 decaderem 等于您的 unit .
div hundredval
mov hundred, al ; [0,2]
mov al, ah
mov ah, 0
div decadeval
mov decade, al ; [0,9]
mov unit, ah ; [0,9]
上面应该涵盖了错误,但是关于这个程序中的代码还有更多可以说的。请务必阅读使用 DOS 显示数字,一旦程序开始运行,您可以考虑将其发布到我们的配套网站https://codereview.stackexchange.com/questions/tagged/ assembly。