assembly 打印内存时出现奇怪的符号“Int 21 h/AH= 09 h”

xmakbtuz  于 2022-12-23  发布在  其他
关注(0)|答案(2)|浏览(282)

我在DOSBox中使用TASM、TLINK和TD(调试器)。
我最近尝试编写一个简单的ASM 8086程序,该程序将打印地址0100h处的值。当我打印结果时,得到的输出如下所示:

我的代码是:

.MODEL SMALL
.STACK
.DATA
.CODE
.STARTUP

MOV SI,0100H
MOV WORD PTR[SI],31
MOV DX,0
MOV AH,09H
MOV DX,[SI]
INT 21H

MOV AH,4CH
INT 21H

END
gblwokeq

gblwokeq1#

AH设置为09H的情况下调用21H中断,将打印寄存器DX中以$结尾的字符串。在您的情况下,DX包含31H,这将指向(我假设)垃圾,这就是为什么您打印随机符号。
在调用print syscall之前,在数据段中创建要打印的字符串,并使DX寄存器指向它。

5hcedyr0

5hcedyr02#

我认为这里有一点误解,还没有解决。存储在计算机内存中的数字不能按原样打印。在汇编中,数字必须转换为字符串,并且您需要打印该字符串。谢天谢地,这相当简单。因为ASCII被设计成0到9的任何一位数的基数为10的数字的字符串表示是它的值加上0x30。也就是说,'0' = 30h'1' = 31h等。唯一的问题是默认情况下数字是以二进制存储的,这意味着将数字打印为十六进制比打印为十进制要容易得多。0x0n形式的单个十六进制数字到其ASCII值的转换因子相当容易:

; AL = the digit you wish to print, ranges from 0x00 to 0x0F
cmp al,0Ah
jb noCorrectHex
add al,7    ; converts 0x0A to 0x41 = 'A' , 0x0B to 0x42 = 'B', etc. 
noCorrectHex:
add al,'0'  ; evaluates to "add al,30h"

如果你从你的单词的最左边的数字开始(在把它从存储器装入寄存器之后),然后从左到右,你可以用这个方法按顺序打印数字。我用DOS中断打印单个字符,而不是字符串。

PrintHex:
; AL = the byte you wish to print.
; this prints the hexadecimal representation of a byte to the screen.

push ax
   shr al,1
   shr al,1
   shr al,1
   shr al,1
   call PrintHexChar
pop ax
and al,0Fh

;fallthrough is intentional

PrintHexChar:
cmp al,0Ah
jb noCorrectHex
   add al,7    ; converts 0x0A to 0x41 = 'A' , 0x0B to 0x42 = 'B', etc. 
noCorrectHex:
add al,'0'  ; evaluates to "add al,30h"

mov ah,02h
mov DL,AL
int 21h
ret

这里有另一种方法来执行数学转换一个十六进制数字到ASCII,这是有点难以遵循的事情,但它不需要任何分支(我不知道这是更好或更坏,只是做更可读的版本,但你得到相同的结果)

PrintHexChar:
and al,0Fh ;clear C and A flags. Required even if top 4 bits are already 0. 
daa
add al,0F0h
adc al,40h

mov ah,02h
mov DL,AL
int 21h
ret

相关问题