十六进制到十进制的汇编转换(最多 4 位)

Assembly Conversion hexadecimal to decimal (4 digit max)

此代码将 1 位十六进制数转换为十进制数,它可以工作,复制互联网,但我想更好地了解它是如何工作的,并添加一个循环,我最多可以得到 4 digits.I 会就像有关如何执行此循环的帮助。

我正在使用 masm16 和 DosBox。

    .model small
.stack 100h
.data
msg1 db 10,13,'ENTER A HEX DIGIT:$'
msg2 db 10,13,'IN DECIMAL IS IT:$'
msg3 db 10,13,'DO YOU WANT TO DO IT AGAIN?$'
msg4 db 10,13,'ILLEGAL CHARACTER- ENTER 0-9 OR A-F:$'

.code

again:

   mov ax,@data
   mov ds,ax
   lea dx,msg1
   mov ah,9
   int 21h

   mov ah,1
   int 21h

   mov bl,al

   jmp go

go:

   cmp bl,'9'
   ja hex
   jb num
   je num

 hex:

    cmp bl,'F'
    ja illegal

   lea dx,msg2
   mov ah,9
   int 21h

    mov dl,49d
    mov ah,2
    int 21h

    sub bl,17d
    mov dl,bl
    mov ah,2
    int 21h

    jmp inp

 inp:

    lea dx,msg3
    mov ah,9
    int 21h

    mov ah,1
    int 21h

    mov cl,al
    cmp cl,'y'
    je again
    cmp cl,'Y'
    je again
    jmp exit

 num:

   cmp bl,'0'
   jb illegal

   lea dx,msg2
   mov ah,9
   int 21h

   mov dl,bl
   mov ah,2
   int 21h

   jmp inp

 illegal:

       lea dx,msg4
       mov ah,9
       int 21h

       mov ah,1
       int 21h

       mov bl,al

       jmp go

exit:
end

我发现了一个旧程序可以满足您的需求,但它与您的程序有很大不同。我会把它贴在这里,因为它可以帮助你。我添加了您的一些代码并进行了一些其他更改。它是这样工作的:

  • 使用 int 21h ah=0Ah(不是逐个字符)将十六进制数捕获为字符串。
  • 将十六进制字符串转换为 AX 中的数字。验证每个字符。
  • 将 AX 转换为字符串以将其转换为十进制显示。
  • 询问用户是否想再做一次。

这是代码,只需复制粘贴即可 运行:

.model small
.stack 100h
.data

msg1 db 10,13,10,13,'ENTER 1 TO 4 HEX DIGITS:$'
msg2 db 10,13,'IN DECIMAL IS IT:$'
msg3 db 10,13,10,13,'DO YOU WANT TO DO IT AGAIN (Y/N)?$'
msg4 db 10,13,'ILLEGAL CHARACTER- ENTER 0-9 OR A-F:$'

hex  db 5,?,5 dup(?) ;VARIABLE WITH 3 SECTIONS.
buffer  db 6 dup('$') ;RESULT COULD HAVE 5 DIGITS.

.code
  mov  ax, @data
  mov  ds, ax

again:

;CLEAR BUFFER (IN CASE IT HOLDS PREVIOUS RESULT).
  call clear_buffer

;DISPLAY 'ENTER 1 TO 4 HEX DIGITS:$'
  mov  ah, 9
  lea  dx, msg1
  int  21h

;CAPTURE HEX NUMBER AS STRING.
  mov  ah, 0ah
  lea  dx, hex
  int  21h

;CONVERT HEX-STRING TO NUMBER.
  lea  si, hex+2        ;CHARS OF THE HEX-STRING.
  mov  bh, [si-1]       ;SECOND BYTE IS LENGTH.
  call hex2number       ;NUMBER RETURNS IN AX.

;CONVERT NUMBER TO DECIMAL-STRING TO DISPLAY.
  lea  si, buffer
  call number2string    ;STRING RETURNS IN SI (BUFFER).

;DISPLAY 'IN DECIMAL IS IT:$'
  mov  ah, 9
  lea  dx, msg2
  int  21h            

;DISPLAY NUMBER AS STRING.
  mov  ah, 9
  lea  dx, buffer
  int  21h

illegal: ;JUMP HERE WHEN INVALID CHARACTER FOUND.

;DISPLAY 'DO YOU WANT TO DO IT AGAIN (Y/N)?$' 
  mov  ah, 9
  lea  dx, msg3
  int  21h

;CAPTURE KEY.
  mov  ah, 1
  int  21h
  cmp  al,'y'
  je   again
  cmp  al,'Y'
  je   again

;TERMINATE PROGRAM.  
  mov  ax, 4c00h
  int  21h 

;---------------------------------------------  
;FILL VARIABLE "BUFFER" WITH "$".
;EVERYTIME THE USER WANTS TO DO IT AGAIN, THE
;PREVIOUS RESULT MUST BE CLEARED.

clear_buffer proc
  lea  si, buffer
  mov  al, '$'
  mov  cx, 5  
clearing:
  mov  [si], al
  inc  si
  loop clearing

  ret
clear_buffer endp

;---------------------------------------------  
;INPUT  : BH = STRING LENGTH (1..4).
;         SI = OFFSET HEX-STRING.
;OUTPUT : AX = NUMBER.

hex2number proc
      MOV  AX, 0       ;THE NUMBER.
   Ciclo:
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;     SHL  AX, 4       ;SHIFT LEFT LOWER 4 BITS.
;SHIFT LEFT AL AND AH MANUALLY 4 TIMES TO SIMULATE SHL AX,4.
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

      MOV  BL, [ SI ]  ;GET ONE HEX CHAR FROM STRING.

      call validate

      CMP  BL, 'A'     ;BL = 'A'..'F' : LETTER.
      JAE  letterAF    ;BL = '0'..'9' : DIGIT.
   ;CharIsDigit09.
      SUB  BL, 48      ;CONVERT DIGIT TO NUMBER.
      JMP  continue   
   letterAF:               
      SUB  BL, 55      ;CONVERT LETTER TO NUMBER.
   continue: 
      OR   AL, BL      ;CLEAR UPPER 4 BITS.
      INC  SI          ;NEXT HEX CHAR.
      DEC  BH          ;BH == 0 : FINISH.
      JNZ  Ciclo       ;BH != 0 : REPEAT.
   Fin:
      RET
hex2number endp

;---------------------------------------------  
;INPUT : BL = HEX CHAR TO VALIDATE.

validate proc
    cmp bl, '0'
    jb  error     ;IF BL < '0'
    cmp bl, 'F'
    ja  error     ;IF BL > 'F'
    cmp bl, '9'
    jbe ok        ;IF BL <= '9'
    cmp bl, 'A'
    jae ok        ;IF BL >= 'A'
error:    
    pop  ax       ;REMOVE CALL VALIDATE.
    pop  ax       ;REMOVE CALL HEX2NUMBER.
;DISPLAY 'ILLEGAL CHARACTER- ENTER 0-9 OR A-F$'
    mov  ah, 9
    lea  dx, msg4
    int  21h
    jmp  illegal  ;GO TO 'DO YOU WANT TO DO IT AGAIN (Y/N)?$'
ok:    
    ret
validate endp

;---------------------------------------------  
;INPUT : AX = NUMBER TO CONVERT TO DECIMAL.
;        SI = OFFSET STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING.

number2string proc
  mov  bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  dx, 0 ;NECESSARY TO DIVIDE BY BX.
  div  bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
  push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
  inc  cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  ax, 0  ;IF NUMBER IS
  jne  cycle1 ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
  lea  si, buffer
cycle2:  
  pop  dx        
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
  loop cycle2  

  ret
number2string endp  

;------------------------------------------

end

关于 int 21h ah=0Ah 的一些解释:此服务需要一个包含三个部分的变量:

hex  db 5          ;MAX LENGTH ALLOWED (4 CHARS).
     db ?          ;LENGTH ENTERED BY USER.
     db 5 dup(?)   ;STRING CHARS (PLUS ENTER AT THE END).

第一部分是允许的最大字符数(最后加上ENTER键,即char 0Dh),这就是为什么如果我们想要4个字符,我们必须定义5个。第二部分是输入的长度用户(在用户按下 ENTER 后定义)。最后一部分是字符串本身以及用户输入的字符(最后是 ENTER 键,这是 char 0Dh)。