gpt4 book ai didi

assembly - IBM 5150 - int 21h 损坏段寄存器

转载 作者:行者123 更新时间:2023-12-05 01:49:57 25 4
gpt4 key购买 nike

我一直在模拟 IBM 5150、PC-DOS 1.0、IBM Macro Assembler 1.0 上玩汇编。 (86box 3.7.1)

我从一个简单的“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

可悲的是,程序在输出后崩溃了。通过调试我发现,在 21h 中断之后,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 写了一个类似的程序,它运行良好。(只用21h,4Ch结束,PC-DOS 1.0不支持)

PS:我这样做是出于对历史的好奇,所以...

最佳答案

我可以明确地回答你问题的一部分:当 Int 21h/AH=4Ch 时,你如何正确地退出 DOS .EXE 程序?在 DOS 1.0 中不可用?

主要方法是使用 Int 20h,但有一点需要注意。当您使用 Int 20h 时,您必须将 CS 设置为 Program Segment Prefix (PSP) 所在的段在。问题是在 EXE 程序中 CS 不指向 PSP 段,它指向一个单独的代码段!

一般的解决方案是利用 DS(和 ES)在启动时指向 EXE 程序中的 PSP 段这一事实。您还可以利用在 PSP 的第一个字中有一个 Int 20h 指令这一事实。我们可以使用一个FAR Return to PSP_Segment:0000h来执行PSP中的Int 20h来退出程序。

终止 DOS .EXE 程序的代码可能类似于:

stack    segment   stack
db 80h dup(?)
stack ends

data segment
data ends

code segment

main proc far ; Marking this `far` will make the
; assembler convert RET to a FAR RETURN

push ds ; DS = PSP, save PSP segment on stack

; Insert program code here.
; Make sure the stack is balanced when finished
; -----------------
assume cs:code,ds:data
mov dx, data
mov ds, dx
; -----------------

; Exit EXE program with FAR Return to PSP_Segment:0000h where
; an Into 20h resides in the word at offset 0000h in the PSP

xor ax, ax ; AX = 0
push ax ; Push 0 on the stack
; Note: `PUSH` with an immediate value
; wasn't a valid instruction on
; Intel 8088/8086 processors

; At this point the DS (PSP) pushed at the beginning of the program
; and the value 0000h forms a CS:IP FAR pointer on the stack

; A FAR return is done since
; procedure main was declared as FAR

ret ; Return to PSP_Segment:0000h via FAR pointer
; on the stack and execute
; the Int 20h at that address
main endp ; End of procedure main
code ends

end

我相信 DEBUG 的原始版本中可能存在导致跟踪问题的错误,但我不能确定,而且我手头没有 PC-DOS 1.0 环境来尝试它。我开始认为 trace 正在跟踪不止一条指令,并且可能同时执行 Int 21hInt 20hint 20h 由于上一节中给出的原因而失败。


注意事项

在 COM 程序中,CS 是包含 PSP 和您的代码的段。 PSP 是段的前 256 个字节,也是 COM 程序的原点 (ORG) 为 100h 的原因。这就是为什么 Int 20h 可以在这种环境中工作,前提是您不在代码中自行更改 CS

关于assembly - IBM 5150 - int 21h 损坏段寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73587054/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com