4.1 一个源程序从写出到执行的过程

image-20211201110414049

4.2 源程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
assume cs: codesg

codesg segment

    mov ax,0123H
    mov bx,0456H
    add ax,bx
    add ax,ax

    mov ax ,4c00H
    int 21H

codesg ends
end

伪指令

在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为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的控制权交还给使它得以运行的程序,我们称这个过程为:程序返回。那么,如何返回呢?应该在程序的末尾添加返回的程序段。

我们回过头来,看一下程序中的两条指令:

1
2
mov ax ,4c00H
int 21H

这两条指令所实现的功能就是程序返回。

image-20211201111613700

DOS 源程序的编辑、编译、连接、执行

编辑

1
C:\>edit

编译

masm

1
C:\masm>masm c:\1;

在后面加分号自动忽略中间文件的生成

连接

link

1
C:\masm>link 1;

执行

1
C:\masm>1

4.8 谁将可执行文件中的程序装载进入内存并使它运行?

image-20211201140731220

(1)在 DOS中直接执行1.exe时,是正在运行的command,将1.exe中的程序加载入内存;

(2)command设置CPU 的CS:IP指向程序的第一条指令(即程序的入口),从而使程序得以运行;

(3)程序运行结束后,返回到command 中,CPU继续运行command。

image-20211201140834972

4.9 程序执行过程的跟踪

为了观察程序的运行过程,可以使用Debug。Debug 可以将程序加载入内存,设置CS:IP指向程序的入口,但 Debug 并不放弃对CPU的控制,这样,我们就可以使用Debug的相关命令来单步执行程序,查看每一条指令的执行结果。

image-20211201141235919

在 DOS系统中.EXE文件中的程序的加载过程

image-20211201141311423

(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中。表示程序正常结束。

image-20211201141803738

使用Q命令退出Debug,将返回到command 中,因为 Debug是由command加载运行的。在 DOS中用“debug 1.exe”运行Debug对1.exe进行跟踪时,程序加载的顺序是:command加载Debug,Debug加载1.exe。返回的顺序是:从 1.exe 中的程序返回到Debug,从Debug返回到command。

==实验==

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
assume cs:codesg
codesg segment
	mov ax,2000H
	mov ss,ax
	mov sp,0
	add sp,10
	pop ax
	pop bx
	push ax
	push bx
	pop ax
	pop bx
	mov ax,4c00H
	int 21H
codesg ends
end

2000:0 - 2000:f 这一行

在执行pop时,红框内容右移

在执行push时,红框内容左移 ==为什么?==

image-20211201145316101