1. 人为定义的代码段:
a. 按照上一节讲过的段的定义,只要是符合规则的内存地址空间的一部分都可以作为段,至于段的含义必须由人给出;
b. 通常编程时会根据人的需要会选择内存地址空间的一些不同空间分别存放程序运行的代码(指令)和程序需要处理的数据,随着程序规模的扩大和逐渐复杂也会产生新的需求,比如定义全局变量以及为函数调用服务的栈等;
c. 因此根据段的定义,程序员会在内存中选择一些段专门用来存放代码(指令),就称为代码段,选择一些段专门用来存放程序需要处理的数据,就称为数据段;
注:在选择段的时候不能让两个段的空间发生重合,一般来说都是在两个段之间空出足够大的空间,以防一个段的长度扩展时越界覆盖另一个段中的内容,而发生不可预计的后果;
2. 定义代码段的方法——段寄存器:
1) 段寄存器就是专门存放段地址(即段基)的寄存器,其后缀为S(Segment,段)的缩写;
2) 将一个段地址存入一个段寄存器的过程就定义了一个段,准确地说是定义了一个段的起始;
3) 段寄存器一共有四个:CS(Code Segment,代码段寄存器)、DS(Data Segment,数据段寄存器)、SS(Stack Segment,栈段寄存器)、ES(Extra Segment,附加段寄存器),这些寄存器都用于存放段基地址;
4) 段寄存器的访问限制:段寄存器就不像通用寄存器那样可以非常随意的访问,比如CS:IP这两个寄存器共同决定下一条指令在内存中存放的位置,这就非常厉害了!对程序来说至关重要,如果知错了程序就会崩溃,因此对于这样的寄存器就不能直接使用MOV等指令随意的修改,其修改就需要很多规则限定,这些规则之后会具体解释;
并且,这些寄存器都具有非常明确的含义,即表示的是代码段还是数据段可以从名字一眼就看出,并且实际使用的时候也是严格按着这个含义使用的(语法和编译器层面上严格规定),这就不像通用寄存器那么随意了,比如虽然AX是存放累加值的,但也可以存放一个段地址或其它含义的数据,即实际的使用方法可以和它名字描述的不一样,因此称为”通用寄存器“;
5) CS:IP组合:IP即Instruction Pointer,指令指针寄存器,即代码段CS对应的偏移指针,和CS配合使用,CS:IP共同指示下一条要执行的指令在内存中的位置;
6) 一般情况下一条指令的执行流程:通过CS:IP的指向从内存中取出下一条执行的指令装入CPU的指令寄存器 ---> 执行指令 ---> IP++(即指向下一条指令了),但也有可能通过JMP等跳转指令重新修改CS:IP而该表下一条指令的位置 ---> 重复第一步(循环);
当然可能某条执行的指令是退出指令,则程序就会退出(或中断)!
7) 只能通过一些特殊的指令(如JMP等)才能对CS:IP进行修改,之后会详述;
4. 对于指令系统和机器来说非常重要的CS:IP:
a. 对于高速强大的CPU来说,没有指令执行那也是巧妇难为无米之炊,而CPU执行的指令就是根据CS:IP来寻找的;
b. 根据指令系统的设计,CPU要执行的指令只会根据CS:IP来寻找,而不会从别的寄存器中寻找,因此CS:IP非常重要,这也就意味着修改CS:IP中的值也必须得非常慎重;
c. 因此如果一段信息被CPU执行过,则该信息所在的内存单元必被CS:IP指向过;
5. 从CS:IP角度来看一条指令的执行过程:
a. CS:IP指向下一条将要执行的指令;
b. CPU根据CS:IP取指令并执行;
c. 将IP加上执行的指令的长度使CS:IP指向下一条指令;
就是如此反复执行指令;
6. 转移指令简介:
a. 8086系统没有提过MOV指令对CS:IP修改的支持,因此使用MOV指令来修改CS:IP是非法的,将导致编译器报错;
b. MOV是传送指令,可以作用于大多数寄存器,而CS:IP是个例外;
c. 转移指令就是那些可以修改CS:IP的值的指令,这里介绍最简单的JMP指令;
d. JMP:即Jamp的缩写,即跳转,因为修改CS:IP的实质就是从当前要执行的指令跳转到另一条指令处;
e. 用法:
i. JMP 直接段地址:直接偏移地址,比如JMP 2AE3:0300
ii. JMP 某一合法寄存器,比如JMP AX,这样只改变IP的值而不改变CS的值,相当于MOV IP, AX
iii. JMP 偏移地址,比如JMP 2301,这样也是只改变IP的地址;