王爽《汇编语言》(第二版) 学习笔记 (第六章 包含多个段的程序 )

时间:2022-07-01 01:15:59

第六章 包含多个段的程序

本章概述:

1.         在操作系统的环境中,合法地通过操作系统取得的空间都是安全的,因为操作系统不会让一个程序所用的空间和其他程序以及系统自己的空间相冲突。在操作系统允许的情况下,程序可以取得任意容量的空间。

2.         程序取得所需空间的方法有两种,一是在加载程序的时候为程序分配,再就是程序在执行的过程中向系统申请。

3.         若要一个程序在被加载的时候取得所需的空间,则必须要在源程序中做出说明。通过在源程序中定义段来进行内存空间的获取。

4.         大多数有用的程序,都要处理数据,使用栈空间,当然也都必须有指令,为了程序设计上的清晰和方便,我们一般也都定义不同的段来存放它们。

 

一、             在代码段中使用数据

1.         从规范的角度讲,我们是不能自己随便决定哪段空间可以使用的,应该让系统来为我们分配。我们可以在程序中,定义我们希望处理的数据,这些数据就会被编译、连接程序作为程序的一部分写到可执行文件中。当可执行文件中的程序被加载入内存时,这些数据也同时被加载入内存中。与此同时,我们要处理的数据也就自然而然地获得了存储空间。

2.         程序中“dw”的含义是定义字型数据,dw即“define word”,在定义数据的同时也是在开辟内存空间。

3.         程序结构:

assume cs:code

code segment

              :

              数据(dw 0123h0456h…………)

              :

start:

              :

              代码

              :

code ends

end start

4.         end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方。“end 标号”指明程序的入口,被转化为一个入口地址,存储在可执行文件的描述信息中,当程序被加载时,CS:IP将被设置到标号对应的入口地址。

5.         在单任务系统中,可执行文件中的程序执行过程如下 ;

1)        由其他的程序(Debugcommand或其他程序)将可执行文件中的程序加载入内存;

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

3)        程序运行结束后,返回到加载者。

6.         根据什么设置CPUCS:IP指向程序的第一条要执行的指令?也就是说,如何知道哪一条指令是程序的第一条要执行的指令?这一点,是由可执行文件中的描述信息指明的。我们知道可执行文件由描述信息和程序组成,程序来自于源程序中的汇编指令和定义的数据;描述信息则主要是编译、连接程序对源程序中相关伪指令进行处理所得到的信息。用伪指令end 描述了程序的结束和程序的入口。在编译、连接后,由“end start”指明的程序入口,被转化为一个入口地址,存储在可执行文件的描述信息中。当程序被加载入内存之后,加载者从程序的可执行文件的描述信息中读到程序的入口地址,设置CS:IP。这样CPU就从我们希望的地址处开始执行。归根结底,我们若要CPU从何处开始执行程序,只要在源程序中用“end 标号”指明就可以了。

7.         如果没有指明程序的入口地址,将默认从代码段的首地址开始。

二、             在代码段中使用栈

定义数据的同时也是在开辟空间。

三、             将数据、代码、栈放入不同的段

1.         将数据、栈和代码都放到一个段中,有两个问题:

1)        把它们放到一个段中使程序显得混乱。

2)        如果数据、栈和代码需要的空间超过64KB,就不能放在一个段中。

2.         我们用和定义代码段一样的方法来定义多个段,然后在这些段里面定义需要的数据,或通过定义数据来取得栈空间。

3.         定义一个段的方法和定义代码段的方法没有区别,只是对于不同的段,要有不同的段名。

4.         在程序中,段名就相当于一个标号,它代表了段地址。所以指令“mov axdata”的含义就是将名称为“data”的段的段地址送入ax

5.         一个段中的数据的段地址可由段名代表,偏移地址就要看它在段中的位置了。

6.         注意:指令“mov ds data”是错误的,因为8086CPU不允许将一个数值直接送入段寄存器中。程序中对段名的引用,如指令“mov dsdata”中的“data”,将被编译器处理为一个表示段地址的数值。

7.         指令“mov dsdata”是错误的,因为8086CPU不允许将一个数值直接送入段寄存器中。程序中对段名的引用,如指令“mov dsdata”中的“data”,将被编译器处理为一个表示段地址的数值。

8.         在源程序中用伪指令“assume cs:codeds:datass:stack”将csdsss分别和codedatastack段相连。这样做之后,CPU只会将data对应的地址写进cs中,而datastack则需要程序中的代码来完成。

9.         “代码段”、“数据段”、“栈段”完全是我们的安排,CPU并不知道程序中的代码段、数据段、栈段。它仅仅只是按照程序指令来执行。若要CPU按照我们的安排行事,就要用机器指令控制它,源程序中的汇编指令是CPU要执行的内容。

四、             实验5 编写、调试具有多个段的程序