在汇编 8086 中将十六进制转换为十进制

问题描述 投票:0回答:1

我正在尝试创建一个代码,它将输入 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。那么我该如何解决这个问题?

assembly x86-16 emu8086 integer-division
1个回答
0
投票

并且由于 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
操作都是字节大小,因为除数hundredvaldecadevalunitval已使用
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

© www.soinside.com 2019 - 2024. All rights reserved.