使用EMU8086,有没有直接的方法来打印变量的十六进制值?

时间:2015-08-19 17:07:45

标签: assembly x86

我在Windows 7 HP x64,Intel i3-2330m PC上使用EMU8086。

我花了大约两周时间研究和修改这个汇编语言程序,以便打印用户输入的整数的十六进制值。我没有发现直接从内存位置打印值。如有必要,我可以编写代码来将字符串转换为十六进制。但是,我试图避免额外的代码行来执行此操作。 (我认为这称为优化。)

我的研究引导我comment on this site by Corbin说:

  

非常不愉快。您必须确定小数的值   string(" 100"),然后创建一个十六进制相同值的新字符串   (" 0x64&#34)。它与您用于进行转换的算法相同   你的头;因为你必须处理,所以它有点复杂   使用ASCII编码。

这些都没有指示我想要执行任务的方式。

我已经逐步编写并测试了代码,并获得了所需的结果。通过观察变量并查看CX寄存器,我可以确认它们的值是我想要打印的值。

我在这里包含我的代码。这可能是丑陋的,肯定是过度评论。评论是为了我的利益,帮助我学习/记住我在进步时所做的一切。

 ; program name: convert_decimal_to_hex
 ; by W K
 ; August, 2015
 ; This program accepts an integer between 1 and 10000 and
 ; prints the hexadecimal value to the console
 ;
 ;
 #MAKE_COM# ;instruct compiler to make COM file
 include emu8086.inc    ;use include file for macros
 ORG 100h   ;directive for COM program, set offset to 100h
 ;
 MOV DX, offset msg1    ;moves value of msg1 to the data register
 ;                       
 MOV AH, 9  ;moves the value 9 to the high accumulator register
            ;to be used with the interrupt
 INT 21h    ;invokes interrupt to print string to DOS window
 ;
 MOV DX,13  ;these lines
  MOV AH,2  ;create a
  INT 21h   ;newline
  MOV DX,10 ;and
  MOV AH,2  ;move the cursor
  INT 21h   ;to the newline
 ;
 CALL SCAN_NUM  ;calls macro to scan numeric keyboard input
                ;error catching is included in macro
                ;number is stored in CX 
  MOV DX,13 ;these lines
  MOV AH,2  ;create a
  INT 21h   ;newline
  MOV DX,10 ;and
  MOV AH,2  ;move the cursor
  INT 21h   ;to the newline
 ;  
 MOV DX, offset msg2    ;moves value of msg2 to the data register
 MOV AX, CX ;copies scanned number to AX to be printed
            ;as part of message
 ;MOV AH, 9  ;moves the value 9 to the high accumulator register
             ;to be used with the interrupt
 ;INT 21h    ;invokes interrupt to print string to DOS window 


 CALL PRINT_NUM_UNS  ;prints hexadecimal value at end of msg2
 MOV CONVERTEDNUMBER, CX
 ;                       
 MOV AH, 9  ;moves the value 9 to the high accumulator register
            ;to be used with the interrupt
 INT 21h    ;invokes interrupt to print string to DOS window
 ;
 MOV AX, 0  ;wait for any key
 INT 16h    ;prevents window from closing immediately
 ;
 msg1 db "Type an integer between 1 and 10000, and press enter. $"    
    ;declare string variable 
 msg2 db " in hexadecimal is: $" 
 ;
 DEFINE_SCAN_NUM    ;defines macro from include file
                    ;gets multidigit signed number from keyboard
 DEFINE_PRINT_NUM_UNS   ;defines macro from include file
                        ;prints unsigned number in AX
 ;                                                   
 CONVERTEDNUMBER DW 0   ;declare variable
 ;
 RET    ;return to operating system
 END    ;directive to stop compiler

是否存在直接打印变量值或CX寄存器值而不编写代码行以转换用户输入的字符串值的过程?任何对文章,代码示例或其他有用建议的引用都将不胜感激。

1 个答案:

答案 0 :(得分:1)

DOS仅为您提供中断以将字符写入标准输出(INT 21H / AH=2表示单个字符,INT 21H / AH=9表示$ - 终止字符串()。

所以你 必须首先将你要打印的任何数字转换为字符串,无论你希望显示数字的基数。幸运的是,这很容易做到。下面是一个如何打印32位十六进制数字的例子(我将把它留作练习来剥离前导零):

; Input:
; EAX = value to print
;
print_hex:
    mov cx,8        ; print 8 hex digits (= 32 bits)
    .print_digit:
        rol eax,4   ; move the currently left-most digit into the least significant 4 bits
        mov dl,al
        and dl,0xF  ; isolate the hex digit we want to print
        add dl,'0'  ; and convert it into a character..
        cmp dl,'9'  ; ...
        jbe .ok     ; ...
        add dl,7    ; ... (for 'A'..'F')
    .ok:            ; ...
        push eax    ; save EAX on the stack temporarily
        mov ah,2    ; INT 21H / AH=2: write character to stdout
        int 0x21
        pop eax     ; restore EAX
        loop .print_digit
        ret

基数10或基数2的打印数量差别不大。它只是当我们处理2的幂(如16或2)的基数时,我们可以使用移位(或在我的代码中旋转)和AND而不是除法和余数。