什么可以导致汇编语言程序显示“垃圾”?

时间:2020-12-14 03:14:12

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', '$'
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:

输出是:

E:\ece323\software\lab2>MAIN.EXE
?F ^?¶ ? N?   ?               -!-

Hello, Adam-

What is going on here?

这里发生了什么?

5 个解决方案

#1


2  

My guess is that your DS does not point to your data-segment.

我猜您的DS并未指向您的数据段。

Int21 Function 0x09 takes the string from DS:DX.

Int21函数0x09从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).

请记住,DX只是一个16位寄存器。要访问16位范围之外的数据,必须使用段寄存器。这些被称为DS和ES用于数据,CS用于代码,SS用于堆栈(在i386上也有FS和GS)。

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.

您加载的确切地址由16 * segment_register + offset_register给出。 Int21无法猜测你的DS在哪里,所以你必须在调用中断之前加载它。

I guess you have never initialized your DS register, so it most likely points to the code, not the data-segment.

我猜你从来没有初始化你的DS寄存器,所以它很可能指向代码,而不是数据段。

Try to replace your

尝试更换你的

  MOV DX, offset MSG

by:

  LDS DX, MSG  ; Check that, it's been ages since I've written 16 bit code.

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.

不幸的是,自从我上次使用16位汇编程序以来已经有好几年了,所以我无法检查它,但LDS应该可以解决这个问题。

You may also load DS indirectly at your program startup by something like this:

您也可以通过以下方式在程序启动时间接加载DS:

  MOV AX, SEG DATA  ; check that - can be SEGMENT or so as well.
  MOV DS, AX

#2


0  

Try the following change:

请尝试以下更改:

DATA    SEGMENT 'DATA'
ERROR_MSG DB 'DS:DX is wrong'
MSG DB  0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB      00H
DATA ENDS

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 (?)

如果显示错误消息,那么DS:DX是错误的,所以DS不指向DATA段,或者'OFFSET MSG'由于某种原因是错误的...我的asm生锈但是尝试ADDR而不是OFFSET(? )

If the error-message doesn't display, the problem happened before execution reached PRINT_MSG.

如果未显示错误消息,则在执行到达PRINT_MSG之前发生问题。

#3


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.

Nils是对的,需要设置DS寄存器才能使用int 21的这个函数。首先尝试使用EAX转换的第二部分,它应该可以正常工作。

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.

并且在字符串之后不需要0 char。第9个函数不适用于空终止字符串,这个'$'char工作而不是0。

#4


0  

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... :-) ).

看起来你是PSP的一部分。这是一个.COM吗?如果您忘记了ORG 100h汇编程序指令,OFFSETs将不会指向您认为应该指向的位置......有趣的是,只需从MOV OFFSET切换到LEA也将“正常工作”。 MASM非常聪明,能够弄清楚当你使用LEA时你正在做什么,而它可能不会使用OFFSET(是的,我很久以前就用这种方式学到了所有这些...... :-))。

#5


-1  

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.

我的猜测是你可能没有以“真实”模式运行,这对于一般的MSDOS程序(以及具体的Int 21h中断)来说是必需的。

Windows has been running exclusively in "Protected" mode since Windows 95; The Command Prompt has been in Protected mode since, I think, Windows 2000.

自Windows 95以来,Windows一直在“受保护”模式下运行;我认为,命令提示符一直处于保护模式,Windows 2000。

You may want to try create a shortcut do you EXE, and then setting the Compatibility options in the shortcut.

您可能想尝试创建EXE的快捷方式,然后在快捷方式中设置兼容性选项。

#1


2  

My guess is that your DS does not point to your data-segment.

我猜您的DS并未指向您的数据段。

Int21 Function 0x09 takes the string from DS:DX.

Int21函数0x09从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).

请记住,DX只是一个16位寄存器。要访问16位范围之外的数据,必须使用段寄存器。这些被称为DS和ES用于数据,CS用于代码,SS用于堆栈(在i386上也有FS和GS)。

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.

您加载的确切地址由16 * segment_register + offset_register给出。 Int21无法猜测你的DS在哪里,所以你必须在调用中断之前加载它。

I guess you have never initialized your DS register, so it most likely points to the code, not the data-segment.

我猜你从来没有初始化你的DS寄存器,所以它很可能指向代码,而不是数据段。

Try to replace your

尝试更换你的

  MOV DX, offset MSG

by:

  LDS DX, MSG  ; Check that, it's been ages since I've written 16 bit code.

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.

不幸的是,自从我上次使用16位汇编程序以来已经有好几年了,所以我无法检查它,但LDS应该可以解决这个问题。

You may also load DS indirectly at your program startup by something like this:

您也可以通过以下方式在程序启动时间接加载DS:

  MOV AX, SEG DATA  ; check that - can be SEGMENT or so as well.
  MOV DS, AX

#2


0  

Try the following change:

请尝试以下更改:

DATA    SEGMENT 'DATA'
ERROR_MSG DB 'DS:DX is wrong'
MSG DB  0AH, 0DH, 'Hello, Adam', '$'
CHAR    DB      00H
DATA ENDS

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 (?)

如果显示错误消息,那么DS:DX是错误的,所以DS不指向DATA段,或者'OFFSET MSG'由于某种原因是错误的...我的asm生锈但是尝试ADDR而不是OFFSET(? )

If the error-message doesn't display, the problem happened before execution reached PRINT_MSG.

如果未显示错误消息,则在执行到达PRINT_MSG之前发生问题。

#3


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.

Nils是对的,需要设置DS寄存器才能使用int 21的这个函数。首先尝试使用EAX转换的第二部分,它应该可以正常工作。

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.

并且在字符串之后不需要0 char。第9个函数不适用于空终止字符串,这个'$'char工作而不是0。

#4


0  

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... :-) ).

看起来你是PSP的一部分。这是一个.COM吗?如果您忘记了ORG 100h汇编程序指令,OFFSETs将不会指向您认为应该指向的位置......有趣的是,只需从MOV OFFSET切换到LEA也将“正常工作”。 MASM非常聪明,能够弄清楚当你使用LEA时你正在做什么,而它可能不会使用OFFSET(是的,我很久以前就用这种方式学到了所有这些...... :-))。

#5


-1  

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.

我的猜测是你可能没有以“真实”模式运行,这对于一般的MSDOS程序(以及具体的Int 21h中断)来说是必需的。

Windows has been running exclusively in "Protected" mode since Windows 95; The Command Prompt has been in Protected mode since, I think, Windows 2000.

自Windows 95以来,Windows一直在“受保护”模式下运行;我认为,命令提示符一直处于保护模式,Windows 2000。

You may want to try create a shortcut do you EXE, and then setting the Compatibility options in the shortcut.

您可能想尝试创建EXE的快捷方式,然后在快捷方式中设置兼容性选项。