2016-11-15 3 views
0

Этот код преобразует шестнадцатеричную цифру в шестнадцатеричную цифру в десятичную, работает, копирует Интернет, но я хочу понять немного лучше, как это работает, и добавить цикл, в котором я могу встать до 4 цифр. Мне нужна помощь в том, как выполнить этот цикл.Преобразование с шестнадцатеричной точностью в десятичную (максимум 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 
+0

Я попытался запустить, но произошла странная ошибка. Сборка: hextodec.asm hextodec.asm (13): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU hextodec.asm (40): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU hextodec.asm (50): ошибка A2085: команда или регистр не принимается в текущем режиме ЦП hextodec.asm (53): ошибка A2081: отсутствует операнд после унарного оператора hextodec.asm (169): фатальная ошибка A1008: несогласованная макросъемка –

+0

Я исследовал на leea эквивалентно mov со смещением, но, похоже, ошибка в объявлении str, ошибки продолжаются. Сборка: hextodec.asm hextodec.asm (11): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU - hextodec.asm (38): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU - hextodec.asm (48): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU - hextodec.asm (76): ошибка A2085: инструкция или регистр не принимаются в текущем режиме CPU - hextodec.asm (95): ошибка A2150: регистр слов не может быть первый операнд - 158 –

+0

Я заменил его, теперь только ошибка теперь в SHL AX, 4. Ошибка hextodec.asm (95) A2150: регистр слова не может быть первым операндом –

ответ

0

Я нашел старую программу, которая делает то, что вам нужно, но она сильно отличается от вашей. Я вложу его сюда, потому что он может вам помочь. Я добавил свой код и внес некоторые изменения. Вот как это работает:

  • Захват шестнадцатеричного числа как строки с использованием int 21h ah = 0Ah (не char 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: эта услуга requieres переменной с тремя секциями:

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).

Смежные вопросы