assembly 在程序集8086中将十六进制转换为十进制

5f0d552i  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(139)

我正试图创建一个代码,将作为输入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

字符串
我希望代码能正常工作,但它显示了一个错误对话框“除法溢出”。所以我决定查看寄存器的值。
直到第mov al,res行,寄存器的状态为:

由于x86处理器使用big endian,结果是预期的。然而,在下一条指令之后:
div hundredval寄存器的状态变为:



这就是问题所在。当A1 = 161时,余数保持> 100。那么我该如何解决这个问题呢?

rxztt3cl

rxztt3cl1#

并且由于x86处理器使用大端,
不正确!x86使用little endian:在内存中,低位字节存储在高位字节之前。

cmp al,57
  jbe sethex1
  cmp al,65
  jae sethex1 
  lea dx,msg1
  mov ah,09h
  int 21h

sethex1:

字符串
您当前的程序错误地允许字符“:;<=>?@”通过!现在,您只需(重新)显示提示符,然后愉快地继续,就像字符是正确的一样(“0123456789 ABCDEF”)。
快速解决办法是:

cmp al, 57
  jbe sethex1
  cmp al, 65
  jae sethex1 
  jmp L1
sethex1:


但更好的办法是

cmp al, '9'
  jbe sethex1
  cmp al, 'A'
  jb  L1
sethex1:


后者允许在标签 * sethex 1 * 中失败。

conv2dec:

  mov al,16
  mul cl
  add al,bl


您输入的第一个十六进制数字存储在 * hex 1 * 变量中,然后转换为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]


上面的内容应该涵盖了这些错误,但是关于这个程序中的代码还有更多可以说的。一定要阅读Displaying numbers with DOS,一旦你得到了程序的工作,你可以考虑把它发布在我们的配套网站https://codereview.stackexchange.com/questions/tagged/assembly上。

相关问题