一个汇编语言程序从写出到最终执行的简要过程:
编写--》编译--》连接--》执行
原程序中的程序:
汇编源程序:
伪指令(编译器处理)
汇编指令(编译为机器码)
程序:原程序中最终由计算机执行、处理的指令或数据
4.2 源程序
标号
一个标号指代了一个地址
codesg:放在segment的前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址
程序的结构
定义一个段
实现处理任务
程序结束
段与段寄存器关联
程序返回
我们的程序最先以汇编指令的形式存在原程序中,经编译、连接后转变位机器码,存在在可执行文件中,
一个程序结束后,将CPU的控制全交还给使他得以运行的程序,我们称这个过程位:程序返回
应该在程序的末尾添加返回的程序段
mov ax,4c00H
int 21H
连接的作用有以下几个:
*当原程序很大时,可以将它分为多个原程序文件来编译,每个原程序编译成目标文件后,再用连接程序将他们连接到一起,生成一个可执行文件。
*程序中调用了某个库文件中的子程序,需要将这个库文件和该程序生成的目标文件连接到一起,生成一个可执行文件。
*一个源程序编译后,得到了存有机器码的目标文件,目标文件中的有些内容还不能直接用来生成可执行文件,连接程序将这些内容处理为最终的可执行消息。
所以,在只有一个原程序文件,而又不需要调用某个库中的子程序的情况下,也必须用连接程序对目标文件进行处理,生成可执行文件。
我们编译、连接的最终目的是用源程序文件生成可执行文件。
在这个过程中所产生的中间文件都可以忽略,我们可以用一种较为简捷的方式进行编译、连接。
4.7 1.exe的执行
1.exe的执行情况:
程序到底运行了没有?
程序当然运行了,只是从屏幕上不可能看到任何运行结果。
我们的程序没有像显示器输出任何信息。程序只是做了一些将数据送入寄存器和加法的操作,而这些事情,我们不可能从显示屏上看出来。
程序执行完成后,返回,屏幕上再次出现操作系统的提示符。
4.8 谁将可执行文件中的程序装载进入内存并使它运行?
在DOS中,可执行文件中的程序P1若要运行,必须有一个正在运行的程序P2,将P1从可执行文件中加载入内存,将CPU的控制权交给它,P1才能得以运行;
当P1运行完毕后,应该将CPU的控制权还给使它得以运行的程序P2.
1)我们在DOS中直接执行1.exe时,是正在运行的command将1.exe中的程序加载入内存。
2)command设置CPU的CS:IP指向程序的第一条指令(即程序的入口),从而使程序得以运行。
3)程序运行结束后,返回到command中,CPU继续运行command
汇编程序从写出到执行的过程:
为了观察程序的运行过程,我们可以是用debug。
debug可以将程序加载入内存,设置CS:IP指向程序的入口,但debug并不放弃对CPU的控制,这样,我们就可以是用debug的相关命令来单步执行程序,查看每条指令的执行结果。
debug将可执行文件加载入内存后,cx中存放的是程序的长度。
总结:程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为0,则程序所在的内存区的地址为:ds:0
这个内存区的前256个字节中存放的是PSP,dos用来和程序进行通信。
从256字节处向后的空间存放的是程序。
所以我们从ds中可以得到psp的段地址SA,PSP的偏移地址为0,则物理地址为SAx16+0.
因为PSP占256(100H)字节,所以程序的物理地址是:
可用段地址和偏移地址表示为:
SA+10:0
用T命令单步执行程序中的每一条指令,并观察每条指令的执行结果,到了int 21,我们要用P命令执行:
int 21执行后,显示“Program terminated normally”,返回到debug中。
表示程序正常结束
注意:要使用P命令执行int 21
需要注意的是:在DOS中运行程序时,是command将程序加载入内存;
所以程序运行结束后返回到command中,而在这里是debug将程序加载入内存,所以程序运行结束后要返回到debug中。
是用Q命令退出debug,将返回到command中,因为Debug是由command加载运行的。