程序集转换十六进制到十进制(最多4位)

时间:2016-11-15 15:22:12

标签: assembly hex decimal dosbox

此代码将1位十六进制转换为十进制,它正在工作,复制互联网,但我想了解它如何工作,并添加一个循环,我可以达到4位数。我想要一个帮助如何执行此循环。

我正在使用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

1 个答案:

答案 0 :(得分:0)

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

  • 使用int 21h ah = 0Ah(不是char by char)将十六进制数字捕获为字符串。
  • 将十六进制字符串转换为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的一些解释啊= 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)。