4.1 一个源程序从写出到执行的过程
4.2 源程序
|
|
伪指令
在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行。而伪指令没有对应的机器指令,最终不被CPU所执行。伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。
程序中出现了3种伪指令
(1)segment和ends
segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须要用到的一对伪指
segment和ends的功能是定义一个段segment说明一个段开始,ends说明一个段结束。一个段必须有一个名称来标识
(2)end
end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。所以,在我们写程序的时候,如果程序写完了,要在结尾处加上伪指令end。否则,编译器在编译程序时,无法知道程序在何处结束。
(3) assume
这条伪指令的含义为“假设”。它假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联。通过 assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相联系。
比如,在程序中,用codesg segment … codesg ends定义了一个名为codseg的段,在这个段中存放代码,所以这个段是一个代码段。在程序的开头,用assume cs:codesg 将用作代码段的段codesg和CPU中的段寄存器cs联系起来。
注意,以后可以将源程序文件中的所有内容称为源程序,将源程序中最终由计算机执行、处理的指令或数据,称为程序。
程序返回
一个程序P2在可执行文件中,则必须有一个正在运行的程序P1,将P2从可执行文件中加载入内存后,将CPU的控制权交给P2,P2才能得以运行。P2开始运行后,P1暂停运行。而当P2运行完毕后,应该将CPU的控制权交还给使它得以运行的程序P1,此后,P1继续运行。
现在,我们知道,一个程序结束后,将 CPU的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回。那么,如何返回呢?应该在程序的末尾添加返回的程序段。
我们回过头来,看一下程序中的两条指令:
|
|
这两条指令所实现的功能就是程序返回。
DOS 源程序的编辑、编译、连接、执行
编辑
|
|
编译
masm
|
|
在后面加分号自动忽略中间文件的生成
连接
link
|
|
执行
|
|
4.8 谁将可执行文件中的程序装载进入内存并使它运行?
(1)在 DOS中直接执行1.exe时,是正在运行的command,将1.exe中的程序加载入内存;
(2)command设置CPU 的CS:IP指向程序的第一条指令(即程序的入口),从而使程序得以运行;
(3)程序运行结束后,返回到command 中,CPU继续运行command。
4.9 程序执行过程的跟踪
为了观察程序的运行过程,可以使用Debug。Debug 可以将程序加载入内存,设置CS:IP指向程序的入口,但 Debug 并不放弃对CPU的控制,这样,我们就可以使用Debug的相关命令来单步执行程序,查看每一条指令的执行结果。
在 DOS系统中.EXE文件中的程序的加载过程
(1)程序加载后,ds中存放着程序所在内存区的段地址,这个内存区的偏移地址为0,则程序所在的内存区的地址为ds:0;
(2)这个内存区的前256个字节中存放的是PSP,DOS用来和程序进行通信。从256字节处向后的空间存放的是程序。
所以,从ds中可以得到PSP的段地址SA,PSP的偏移地址为0,则物理地址为SA×16+0。
因为PSP占256(100H)字节,所以程序的物理地址是:SA×16+0+256=SA×16+16×16+0=(SA+16)×16+0
可用段地址和偏移地址表示为:SA+10H:0。
图4.19中DS 的值,DS=129E,则PSP的地址为129E:0,程序的地址为12AE:0(即129E+10:0)。
==到了int 21,要用P命令执行==
int 21执行后,显示出“Program terminated normally”,返回到 Debug中。表示程序正常结束。
使用Q命令退出Debug,将返回到command 中,因为 Debug是由command加载运行的。在 DOS中用“debug 1.exe”运行Debug对1.exe进行跟踪时,程序加载的顺序是:command加载Debug,Debug加载1.exe。返回的顺序是:从 1.exe 中的程序返回到Debug,从Debug返回到command。
==实验==
|
|
2000:0 - 2000:f 这一行
在执行pop时,红框内容右移
在执行push时,红框内容左移 ==为什么?==