我在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寄存器值而不编写代码行以转换用户输入的字符串值的过程?任何对文章,代码示例或其他有用建议的引用都将不胜感激。
答案 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而不是除法和余数。