是什么导致汇编语言程序显示"垃圾邮件"?

时间:2020-03-06 14:21:20  来源:igfitidea点击:

我有一些应该显示一条短消息的代码。这是相关的代码:

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-

这里发生了什么?

解决方案

我的猜测是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

我的猜测是,我们可能未在"真实"模式下运行,这通常对于MSDOS程序(特定而言是Int 21h中断)有效。

从Windows 95开始,Windows一直以"受保护"模式运行。我认为,自Windows 2000以来,命令提示符一直处于"保护"模式。

我们可能想尝试创建一个EXE快捷方式,然后在快捷方式中设置"兼容性"选项。

尝试以下更改:

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之前。

Nils是正确的,为了使用int 21的此功能,需要设置DS寄存器。首先尝试用EAX转换的第二部分,它应该可以正常工作。

并且不需要在字符串后输入0 char。第9个函数不适用于以null结尾的字符串,该'$'char代替0起作用。

看起来我们正在显示PSP的一部分。这是一个.COM吗?如果我们忘记了ORG 100h汇编程序指令,则偏移量不会指向我们认为应该的位置...作为一个有趣的旁注,只需将MOV OFFSET切换到LEA也会"起作用"。 MASM很聪明,可以弄清楚我们在使用LEA时在做什么,而它可能与OFFSET无关(是的,很久以前,我很难学到这一切... :-))。