- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在模拟 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 21h
和 Int 20h
。 int 20h
由于上一节中给出的原因而失败。
在 COM 程序中,CS 是包含 PSP 和您的代码的段。 PSP 是段的前 256 个字节,也是 COM 程序的原点 (ORG) 为 100h 的原因。这就是为什么 Int 20h
可以在这种环境中工作,前提是您不在代码中自行更改 CS。
关于assembly - IBM 5150 - int 21h 损坏段寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73587054/
我尝试在安装了多类型 MFC 库的 visual studio 2015 MFC 上运行以前编写的 MFC c++ 代码。 但是,我这里仍然有 12 个关于缺少函数的错误: IntelliSense:
我正在学习 OOP 并且有疑问。假设我有一个包含 ClassB.h 的文件 ClassA.h,并且在某些时候我的 ClassB.h 需要包含 ClassA .h。 这会产生一个错误,我想我明白为什么会
我开始使用 CUDA 进行编程,在一些示例中我找到了包含文件 cuda.h、cuda_runtime.h 和 cuda_runtime_api.h 包含在代码中。有人可以向我解释一下这些文件之间的区别
我有一些生成正则表达式的代码。那么下面的表达式实际上是: ^(?:\s*((exclude|include|hide|show|protect|risk|dir-merge|merge)),\s*((
我一直在查看一些源代码,以更好地了解我们使用的这款游戏的核心,并编写更可靠、更快速的插件。然后我发现了这段奇怪的代码...... public void setMaxH(double amount)
通常我们会使用标准类型作为 std::unordered_map 的键和值.但现在我需要自定义我自己的键和值类。 键类在block_cache_key.h 中定义如下: #ifndef BLOCK_C
例如,我想要两个头文件,它们可以依赖于另一个头文件中的函数。 //Header1.h file #include Header2.h void h1(){ //... func1(); } v
我正在研究来自 Sedgewick 的 Shell 排序 Algorithms in C part 1-4在第 172 页。 我使用 size (数组的长度),而不是 l和 r (开始和结束);所以我
我在 macOS BigSur 上通过 VMWare 使用 Ubuntu 20.04.2 LTS。我安装了最新版本的 tcl、tcl-dev、tk 和 tk-dev - 版本 8.6。我想编译 Arc
我用我的 glu 和 gl 头文件构建了一个 OpenGL 程序,默认包含在 windows 7 专业版中。现在,我买了一本描述 OpenGL 游戏开发的书。这本书的作者说,我必须在我的项目中包含 g
我想在 token 中保留特殊字符,同时仍对特殊字符进行 token 化。说我有话 "H&R Blocks" 我想将其标记为 "H", "R", "H&R", "Blocks" 我读了http://w
关于 hash 作为 trans 参数的另一个问题。在下面的代码中,简单地使用 hash 会给出不正确的结果,但是将其替换为 keys 和 values 会使其正确。怎么了? my @alph1 =
我已经编写了一个 C 程序,它获取屏幕像素的 RGB 值 (0-255),并知道其位置 (x,y)。它可以在 Linux 中运行,但是当我尝试在 Visual Studio (Windows) 中编译
我已经使用 Windows 7 专业版中默认包含的 glu 和 gl 头文件构建了一个 OpenGL 程序。现在,我买了一本描述 OpenGL 游戏开发的书。这本书的作者说,我必须将glew head
#include using namespace std; #include //#include int main() { initscr();
h:messages h:form 内的组件还显示与外部组件相关的消息。 如何限制它只显示与包含 h:form 内的组件相关的消息? 我不喜欢用单独的h:message来使我的代码膨胀。每个输入组件的
我下载了示例代码和 cpp 文件,其中包含 list.h、queue.h 和 vector.h 等头文件,如果我尝试构建,我会收到“ fatal error :没有这样的文件或目录编译终止”我想我应该
我有一个编译成功的桌面项目,但是在我向项目添加新配置以支持 Windows Mobile 平台后,我收到以下错误: error C2146: syntax error : missing ';' be
有很多关于这个错误的帖子,但我无法解决它,我希望你能拿出解决方案。我在 Ubuntu 机器上。 ~/graphmap2$ 在这个文件夹中,我下载了 zlib。可以看图 经过一番谷歌搜索后,我还注意到没
是否可以在 Visual C++ 中使用以下 header : 图.h dos.h bios.h 最佳答案 据我所知,无法在 Visual C++ 中使用它, 与此同时,我希望您关注 Open Wat
我是一名优秀的程序员,十分优秀!