我只是为了好玩,开始学习 x86 架构的汇编程序,这是我一直想了解更多的东西。我正在使用在 IBM PC DOS 2000 (VM) 下运行的 Microsoft Macro Assembler v6.11,一切都运行良好,操作系统、汇编器、链接器等。但是当我尝试运行此程序时:
.model small
.stack 100h
.data
hello db 10,13,"Hello World$"
.code
main proc
lea dx, hello
mov ah, 9h
int 21h
main endp
end main
最后我得到了一堆奇怪的字符和Hello, world,但是进程崩溃了,因为它在DOS下运行,我别无选择,只能ctrl-atl-delete并重新启动。我想知道我做错了什么?我的猜测是我不知何故出界了,但我显然对此还了解得不够。
我执行以下操作来汇编和链接程序:
ml hello.asm
这不会产生错误或警告,我也尝试过手动汇编和链接程序:
masm hello.asm
link hello.obj
这也没有给出错误或警告,但程序仍然无法运行
该程序已在IBM PC DOS 2000和Microsoft Windows 98 SE下进行了测试,结果是相同的,只不过它只是运行该程序的进程在Windows下崩溃。
这是生成的列表,如果有任何用处:
Microsoft (R) Macro Assembler Version 6.11 12/20/23 15:42:42
hello.asm Page 1 - 1
.model small
.stack 100h
0000 .data
0000 0A 0D 48 65 6C 6C hello db 10,13,"Hello World$"
6F 20 57 6F 72 6C
64 24
0000 .code
0000 main proc
0000 8D 16 0000 R lea dx, hello
0004 B4 09 mov ah, 9h
0006 CD 21 int 21h
0008 main endp
end main
Microsoft (R) Macro Assembler Version 6.11 12/20/23 15:42:42
hello.asm Symbols 2 - 1
Segments and Groups:
N a m e Size Length Align Combine Class
DGROUP . . . . . . . . . . . . . GROUP
_DATA . . . . . . . . . . . . . 16 Bit 000E Word Public 'DATA'
STACK . . . . . . . . . . . . . 16 Bit 0100 Para Stack 'STACK'
_TEXT . . . . . . . . . . . . . 16 Bit 0008 Word Public 'CODE'
Procedures, parameters and locals:
N a m e Type Value Attr
main . . . . . . . . . . . . . . P Near 0000 _TEXT Length= 0008 Public
Symbols:
N a m e Type Value Attr
@CodeSize . . . . . . . . . . . Number 0000h
@DataSize . . . . . . . . . . . Number 0000h
@Interface . . . . . . . . . . . Number 0000h
@Model . . . . . . . . . . . . . Number 0002h
@code . . . . . . . . . . . . . Text _TEXT
@data . . . . . . . . . . . . . Text DGROUP
@fardata? . . . . . . . . . . . Text FAR_BSS
@fardata . . . . . . . . . . . . Text FAR_DATA
@stack . . . . . . . . . . . . . Text DGROUP
hello . . . . . . . . . . . . . Byte 0000 _DATA
0 Warnings
0 Errors
更新
我发现了这个:
TITLE Hello World
.model small
.stack 100h
.data
message BYTE "Hello World",0dh,0ah,0
.code
main PROC
mov ax,@data
mov ds,ax
mov ah,40h
mov bx,1
mov cx,SIZEOF message
mov dx,OFFSET message
int 21h
.exit
main ENDP
END main
这个程序工作正常,没有乱码输出,根据评论,我的印象是“$”是字符串的终止,但上面的程序似乎将 0dh,0ah,0 附加到定义的字节中“message” 我试图在我原来的 hello world 程序中调整它,但输出是相同的,也许有更多的乱码输出。我会尝试比较这两个程序。
我得到了一堆奇怪的字符,最后是“你好,世界”
DOS.PrintString 函数 09h 需要 DS:DX 寄存器对中的远指针。当您的 .EXE 可执行文件启动时,DS 段寄存器指向 PSP(程序段前缀),但在这种情况下,您需要使其指向您的
hello消息所在的
.data
部分:
mov ax, @data
mov ds, ax
“一堆奇怪的字符”实际上是 PSP 和
.code
部分的文本表示,最后是 .data
部分的(清晰的)文本。
但是进程崩溃了
每个程序都需要对其调用者进行退出(父进程通常是操作系统),而您没有提供退出!在第二个程序(您找到的)中,这是通过提及
.exit
来处理的。mov ax, 4C00h ; DOS.TerminateWithExitcode
int 21h
之后,父进程可以使用函数 4Dh 检查此退出代码。
mov ah, 4Dh ; DOS.GetExitcode
int 21h ; -> AH exitcode system, AL exitcode child
我的印象是“$”是字符串的终止,但上面的程序似乎将 0dh,0ah,0 附加到为“message”定义的字节中,我尝试在我原来的 hello world 程序中调整它,但输出是相同的
$ 终止符专门与 DOS.PrintString 函数 09h 一起使用。该另一个程序没有使用函数 09h,而是使用 DOS.WriteFileOrDevice 函数 40h 以及 STDOUT 的预定义句柄 1。因为它的操作基于字节数,所以 message 以零结尾并不重要。然而,它会显示一个空格字符,有时可能会有点混乱。
13,10
或不去 13,10
DOS 中的换行需要回车符 (13) 和换行符 (10)。在真实的 DOS 环境中,顺序并不重要,几乎每个人都使用 (13, 10),但某些模拟器可能不喜欢其中之一。我相信是 emu8086 不是特别喜欢 (13, 10)。