我一直在模拟的IBM 5150、PC-DOS 1.0、IBM Macro Assembler 1.0上玩汇编。
我从一个简单的“Hello World”开始:
stack segment stack
db 80h dup(?)
stack ends
data segment
msg db 'Hello World!',13,10,'$'
data ends
code segment
assume cs:code,ds:data
mov dx, seg msg
mov ds, dx
mov dx, offset msg
mov ah, 09h
int 21h
int 20h
code ends
end
可悲的是,程序在输出后崩溃。通过 debug 我发现,在21 h中断后,DS,CS和IP寄存器被损坏。
a:debug hello.exe
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=0080 BP=0000 SI=0000 DI=0000
DS=049F ES=049F SS=04B1 CS=04AF IP=0000 NV UP DI PL NZ NA PO NC
04AF:0000 BAB004 MOV DX,04B0
-t
AX=0000 BX=0000 CX=0000 DX=04B0 SP=0080 BP=0000 SI=0000 DI=0000
DS=049F ES=049F SS=04B1 CS=04AF IP=0003 NV UP DI PL NZ NA PO NC
04AF:0003 8EDA MOV DS,DX
-t
AX=0000 BX=0000 CX=0000 DX=04B0 SP=0080 BP=0000 SI=0000 DI=0000
DS=04B0 ES=049F SS=04B1 CS=04AF IP=0005 NV UP DI PL NZ NA PO NC
04AF:0005 BA0000 MOV DX,0000
-t
AX=0000 BX=0000 CX=0000 DX=0000 SP=0080 BP=0000 SI=0000 DI=0000
DS=04B0 ES=049F SS=04B1 CS=04AF IP=0008 NV UP DI PL NZ NA PO NC
04AF:0008 B409 MOV AH,09
-t
AX=0900 BX=0000 CX=0000 DX=0000 SP=0080 BP=0000 SI=0000 DI=0000
DS=04B0 ES=049F SS=04B1 CS=04AF IP=000A NV UP DI PL NZ NA PO NC
04AF:000A CD21 INT 21
-t
Hello World!
AX=0040 BX=0000 CX=0000 DX=0000 SP=FD24 BP=0000 SI=0000 DI=0000
DS=0040 ES=049F SS=04B1 CS=FFFF IP=FFFF OV DN EI NG ZR AC PE CY
FFFF:FFFF 00EA ADD 21
有人能解释一下为什么吗?
我为PC-DOS 2.0写了一个类似的程序,它工作了。(只是用21 h,4Ch来终止,PC-DOS 1.0不支持)
PS:我这样做是出于对历史的好奇,所以...
1条答案
按热度按时间sdnqo3pr1#
我可以肯定地回答你问题的一部分:当
Int 21h/AH=4Ch
在DOS1.0中不可用时,如何正确地退出DOS.EXE程序?主要的方法是使用
Int 20h
,但是有一个警告。当你使用Int 20h
时,你必须将 CS 设置为Program Segment Prefix (PSP)所在的段。问题是在EXE程序中,CS 不指向PSP段,而是指向一个单独的代码段!一般的解决方法是利用 DS(和 ES)在启动时指向一个EXE程序的PSP段。你也可以利用PSP的第一个字中有一条
Int 20h
指令。我们可以使用一个FAR Return to PSP_Segment:0000 h来执行PSP中的Int 20h
来退出程序。终止DOS.EXE程序的代码可能如下所示:
我相信在DEBUG的原始版本中可能存在一个bug,但我不能确定,而且我手边没有PC-DOS 1. 0环境来试用它。我开始认为trace正在跟踪多条指令,可能会同时执行
Int 21h
和Int 20h
。int 20h
由于上一节中给出的原因而失败。备注
在COM程序中,CS 是包含PSP和您的代码的段。PSP是段的前256个字节,也是COM程序的起点(ORG)为100 h的原因。这就是为什么
Int 20h
在这种环境下工作,前提是您自己在代码中不更改 CS。