我有一些应该显示短消息的代码。这是相关的代码:
DATA SEGMENT 'DATA'
MSG DB 0AH, 0DH, 'Hello, Adam', '$'
CHAR DB 00H
DATA ENDS
CODE SEGMENT 'CODE'
PRINT_MSG:
MOV AH, 09H ;Command to print string of characters
MOV DX, OFFSET MSG ;Mov address of message into DX
INT 21H ;DOS Interrupt
JMP WAITING ;Loop back to waiting state
CODE ENDS
输出是:
E:\ece323\software\lab2>MAIN.EXE
?F ^?¶ ? N? ? -!-
Hello, Adam-
这里发生了什么?
答案 0 :(得分:2)
我的猜测是您的DS未指向您的数据段。
Int21函数0x09从DS:DX获取字符串。
请记住DX只是一个16位寄存器。要访问16位范围之外的数据,必须使用段寄存器。这些被称为DS和ES用于数据,CS用于代码,SS用于堆栈(在i386上也有FS和GS)。
您加载的确切地址由16 * segment_register + offset_register给出。 Int21无法猜测你的DS在哪里,所以你必须在调用中断之前加载它。
我猜你从来没有初始化你的DS寄存器,因此它很可能指向代码,而不是数据段。
尝试更换
MOV DX, offset MSG
由:
LDS DX, MSG ; Check that, it's been ages since I've written 16 bit code.
不幸的是,自从我上次使用16位汇编程序以来已经好几年了,所以我无法检查它,但是LDS应该可以解决这个问题。
您也可以通过以下方式在程序启动时间接加载DS:
MOV AX, SEG DATA ; check that - can be SEGMENT or so as well.
MOV DS, AX
答案 1 :(得分:0)
请尝试以下更改:
DATA SEGMENT 'DATA'
ERROR_MSG DB 'DS:DX is wrong'
MSG DB 0AH, 0DH, 'Hello, Adam', '$'
CHAR DB 00H
DATA ENDS
如果显示错误消息,那么DS:DX是错误的,因此DS不指向DATA段,或者'OFFSET MSG'由于某种原因出错...我的asm生锈但是尝试ADDR而不是OFFSET(?)
如果未显示错误消息,则问题在执行到达PRINT_MSG之前发生。
答案 2 :(得分:0)
Nils是对的,需要设置DS寄存器才能使用int 21的这个函数。首先尝试使用EAX转换的第二部分,它应该可以正常工作。
字符串后面的0字符串不需要。第9个函数不适用于空终止字符串,这个'$'char工作而不是0。
答案 3 :(得分:0)
看起来你正在展示PSP的一部分。这是一个.COM吗?如果您忘记了ORG 100h汇编程序指令,OFFSETs将不会指向您认为应该指向的位置......有趣的是,只需从MOV OFFSET切换到LEA也将“正常工作”。 MASM非常聪明,能够弄清楚当你使用LEA时你正在做什么,而它可能不会使用OFFSET(是的,我很久以前就用这种方式学到了所有这些...... :-))。
答案 4 :(得分:-1)
我的猜测是你可能没有以“Real”模式运行,这对于MSDOS程序(特定是Int 21h中断)来说是必需的。
自Windows 95以来,Windows一直在“受保护”模式下运行;我认为命令提示符一直处于保护模式,Windows 2000。
您可能想尝试创建EXE的快捷方式,然后在快捷方式中设置兼容性选项。