什么会导致汇编语言程序显示“垃圾”?
我有一些代码应该显示一条短消息。 这是相关代码:
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-
这里发生了什么?
I have some code which is supposed to display a short message. Here's the pertinent code:
DATA SEGMENT 'DATA'
MSG DB 0AH, 0DH, 'Hello, Adam', '
And the output is:
E:\ece323\software\lab2>MAIN.EXE
?F ^?¶ ? N? ? -!-
Hello, Adam-
What is going on here?
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
And the output is:
What is going on here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
尝试以下更改:
如果显示错误消息,则 DS:DX 错误,因此 DS 未指向 DATA 段,或者“OFFSET MSG”由于某种原因错误......我的 asm 生锈,但尝试 ADDR而不是 OFFSET (?)
如果错误消息未显示,则问题发生在执行到达 PRINT_MSG 之前。
Try the following change:
If the error-message displays then DS:DX is wrong, so either DS doesn't point to the DATA segment, or 'OFFSET MSG' is wrong for some reason...my asm is rusty but try ADDR instead of OFFSET (?)
If the error-message doesn't display, the problem happened before execution reached PRINT_MSG.
Nils 是对的,需要设置 DS 寄存器才能使用 int 21 的这个功能。首先尝试使用 EAX 转换的第二部分,它应该肯定可以工作。
并且字符串后面不需要 0 个字符。 第 9 个函数不适用于以 null 结尾的字符串,这个 '$' 字符可以代替 0。
Nils is right, DS register need to be set in order to use this function of int 21. Try the second part with EAX transition first, it should work for sure.
And there's no need in 0 char after the string. 9-th function doesn't work with null terminated strings, this '$' char works instead of 0.
看起来你正在显示 PSP 的一部分。 这是 .COM 吗? 如果您忘记了 ORG 100h 汇编器指令,OFFSET 将不会指向您认为应该指向的位置...有趣的是,只需从 MOV OFFSET 切换到 LEA 也将“起作用”。 当你使用 LEA 时,MASM 足够聪明,能够弄清楚你在做什么,而使用 OFFSET 时它可能不会(是的,我很久以前就艰难地学到了这一切......:-))。
Looks like you're display part of the PSP. Is this a .COM by any chance? If you forget the ORG 100h assembler directive, OFFSETs will not point where you think they should... As an interesting side note is that just switching from MOV OFFSET to LEA will also "work". MASM is smart enough to figure out what you're doing when you use LEA, whereas it may not with OFFSET (yeah, I learned all this the hard way a long time ago... :-) ).
我的猜测是,您可能没有在“实”模式下运行,而“实”模式是一般 MSDOS 程序(特别是 Int 21h 中断)工作所必需的。
自 Windows 95 以来,Windows 一直只在“受保护”模式下运行; 我认为从 Windows 2000 起,命令提示符就一直处于保护模式。
您可能想尝试创建一个 EXE 快捷方式,然后在快捷方式中设置兼容性选项。
My guess is that you are probably not running in "Real" mode, which is needed for MSDOS programs in general (and Int 21h interrupts in specific) to work.
Windows has been running exclusively in "Protected" mode since Windows 95; The Command Prompt has been in Protected mode since, I think, Windows 2000.
You may want to try create a shortcut do you EXE, and then setting the Compatibility options in the shortcut.
我的猜测是你的 DS 没有指向你的数据段。
Int21 函数 0x09 从 DS:DX 获取字符串。
请记住,DX 只是一个 16 位寄存器。 要访问 16 位范围之外的数据,必须使用段寄存器。 数据称为 DS 和 ES,代码称为 CS,堆栈称为 SS(i386 上也有 FS 和 GS)。
您加载的确切地址由 16 * segment_register + offset_register 给出。 Int21 无法猜测您的 DS 在哪里,因此您必须在调用中断之前加载它。
我猜您从未初始化过 DS 寄存器,因此它很可能指向代码,而不是数据段。
尝试将你的替换
为:
不幸的是,自从我上次使用 16 位汇编器以来已经有很多年了,所以我无法检查它,但 LDS 应该可以解决问题。
您还可以通过以下方式在程序启动时间接加载 DS:
My guess is that your DS does not point to your data-segment.
Int21 Function 0x09 takes the string from DS:DX.
Remember that DX is only a 16 bit register. To access data outside the 16 bit range you have to use segment registers. These are called DS and ES for data, CS for code and SS for the stack (there are FS and GS on i386 as well).
The exact address you load from is given by 16 * segment_register + offset_register. Int21 cannot guess where your DS is, so you have to load it prior to call the interrupt.
I guess you have never initialized your DS register, so it most likely points to the code, not the data-segment.
Try to replace your
by:
Unfortunatley it's been years since I've last played with 16 bit assembler, so I can't check it, but LDS should do the trick.
You may also load DS indirectly at your program startup by something like this: