一个汇编语言程序从写到最终执行的简要过程。
程序代码如下:
;assume是假设
assume cs:codesg
;伪指令
;段名 segment
codesg segment
mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax
;程序返回,没有下面2句,程序发生逻辑错误
mov ax,4c00H
int 21H
codesg ends
;段名 ends
end
;end是汇编程序的结束标记
过程:
**编译**T1.asm文件,如图:
一般来说,有两类错误使我们得不到所期望的目标文件:
在编译过程中,我们提供一个输入:T1。最多可以的到三个输出:目标文件(.obj)、目标文件(.lst)、交叉引用文件(.crf)。目标文件使我们最终得到的结果,而另外两个只是中间结果,可以让编译器忽略对它们的生成。
**连接**T1.obj文件,如图:
这个程序中有一个警告错误:“没有栈段”,这里我们不理会这个错误。
第一个是输入:目标文件。输出是:可执行文件名、映像文件的生成、库文件的连接。
连接的作用:
运行后没有任何结果,这很正常!因为我们是对寄存器做操作,并不是显示到屏幕上。
按照上面原理,我们来看一下4.7节中的T1.exe的执行过程(思考相关的问题)。
问题 4.1
此时,有一个正在运行的程序将 T1.exe 中的程序加载入内存,这个正在运行的程序是什么?它将程序加载入内存后,如何使程序得以运行?
问题 4.2
程序运行结束后,返回到哪里?
我们来了解一下操作系统的外壳。
操作系统是一个由多个功能模块组成的庞大、复杂的软件系统。任何通用的操作系统,都要提供一个称为
shell(外壳)的程序,用户(操作人员)使用这个程序来操作计算机系统进行工作。
DOS中有一个程序command.com,在这个程序在DOS中称为命令解释器,也就是DOS系统的shell。
DOS启动时,先完成其他重要的初始化工作,然后运行 command.com,command.com运行后,执行完
其他的相关任务后,在屏幕上显示出由当前盘符和当前路径组成的提示符,比如:“c:\”或“c:\windows”等,
然后等待用户的输入。
用户可以输入所要执行的命令,比如,cd、dir、type等,这些命令由command执行,command执行完
这些命令后,再次显示由当前盘符和当前路径组成的提示符,等待用户的输入。
如果用户要执行一个程序,则输入该程序的可执行文件的名称,command首先根据文件名找到可执行文件,
然后将这个可执行文件中的程序加载入内存,设置CS:IP指向程序的入口。此后,command暂停运行,CPU运行
程序。程序运行结束后,返回到command中,command再次显示当前盘符和当前路径组成的提示符,等待用户的
输入。
在DOS中,command处理各种输入:命令或要执行的程序的文件名。我们就是通过command来进行工作的。
现在来回答问题4.1和4.2中所提到的问题。
(1) 在DOS中直接执行T1.exe时,是正在运行的command,将T1.exe中的程序加载入内存;
(2) command设置CPU的CS:IP指向程序的第一条指令(即程序的入口)。从而使程序得以运行;
(3) 程序运行结束后,返回command中,CPU继续运行command。
在编写程序的时候,常常会出现我们的语法没有错误,而逻辑出现错误。这个时候我们就需要拿起强有力的工具,就是我们的 Debug 。
通过command的命令:Debug T1.exe
由上图,我们可以知道两个信息。
我们可以用Debug T1.exe实验一下,如图。
发现DS=075A,CS=076A,但是,发现一个SS和书上的不一样,一个是相差10H,而实际上我们做的实验是相差了09H,我想可能标准不一样吧。我们忽略细节(找不到为什么,不过我们只要知道 PSP 是256个字节就对了)。
当我们执行到 int 21h 的时候,需要使用 p命令,这里不说明原因(因为t命令是单步执行,而p是跳出循环)。
q命令 退出Debug。
这里先吐槽一下,前面2章教我们使用命令的时候,我做笔记是有点想吐的。因为太冗余了,我们只要记住某些命令就行了。可能是本人认为学习汇编是为了学习汇编语言的思想。也许我们需要使用到比如像“中断”这样模式的编程。
(1)将下面的程序保存为 t1.asm 文件,将其生成可执行文件 t1.exe 。
(2)用 Debug 跟踪 t1.exe 的执行过程,写出每一步执行后,相关寄存器中的内容和栈顶的内容。
assume cs:codesg
codesg segment
mov ax,2000h ;ax = 2000h
mov ss,ax ;ss = 2000h
mov sp,0 ;sp = 0h
add sp,10 ;sp = 10h
pop ax ;ax = 0h
pop bx ;bx = 0h
push ax ;ss:e = 0h
push bx ;ss:c = 0h
pop ax ;ax = 0h
pop bx ;ax = 0h
mov ax,4c00h
int 21h
codesg ends
end
(3)PSP的头两个字节是CD 20,用 Debug 加载 t1.exe,查看PSP的内容。
(注意,一定要做完这个实验才能进行下面的课程。)