——《编程语言》 王爽 著
1. 多段程序
我们现在知道内存可以数据段,代码段,栈空间;那么当我们在一个程序中同时包含数据和代码时,从内存角度来看,我们应该怎么解决这个问题呢?
- 在一个段中存放数据、代码、栈;
- 将数据、代码、栈放入不同的段中。
1.1 在代码段中使用程序
先看下列程序:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0defh,ofedh,0cbah,0987h
start: mov bx,0
mov bx,0
mov cx,0
s: add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
需要说明的几个问题:
1 dw的含义是define word,在这里,使用dw定义了8个字型数据;
2 end 后面的 start表明了程序的入口。end除了通知编译器程序在这里结束外,还可以通知编译器程序的入口在什么地方;
3 通过这种方法生成的数据,这8个数据存在于代码段的最开始,所以偏移地址为0,然后依次递增,8个字型数据存在于代码段的偏移0,2,4,6,8,A,C,E处。
1.2 在代码段中使用栈
程序的大概思路为先"dw"8个字型空间留给要用的数据,然后"dw"8个字型空的空间留做栈空间用。
假如我们设计将cs:10~cs:2F用做栈空间,那么需要在初始化设置时将cs段地址赋予ss中(中间经过ax寄存器做桥梁),然后将sp指向30h。
1.3 将数据、代码、栈放入不同的段
将数据、代码、栈都放在一起存在两个缺点:
- 把它们放到一个段中使程序显得混乱;
- 如果需要的空间超过64kb,既不能放在一个段中(8086模式中一个段的容量不能超过64kb)。
程序大概格式如下:
assume cs:code,ds:data,ss:stack
data segment
...
data ends
stack segment
...
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,20h ;指向栈顶
mov ax,data
mov ds,ax ;指向data段
...
code ends
end start
这个代码一共定义了三段空间,通过名称“data”等来传递段地址,即在进行空间的定义的时候,在物理上就将三个空间分开,然后调用其相应的段地址即可。
此处再进行强调依次,在对段地址寄存器进行操作的时候,不能直接对其赋值,而应通过ax等寄存器作为桥梁。
2. 更灵活的内存定位
基础知识点:
- and和or指令的用法;
- 通过db ‘(字母)’的形式将对应的ASCII码值提取出来,db的意思是define byte;
- 字母的大小写转换问题,仔细研究一下ASCII表中大小写字母的区别,差值固定;
- [bx + idata] 的意思是 [(bx)+ idata](意义:为高级语言实现数组提供了便利机制);
- 提供了SI,DI两个16位寄存器,但是这两个寄存器并不能拆分成两个8位寄存器,功能和BX相近;
结论:
- [idata]用一个常量来表示地址,可用于直接定位一个内存单元;
- [bx]用一个变量来表示内存地址,可用于间接定位一个内存单元;
- [bx+idata]用一个变量和常量表示地址,可在一个其实地址的基础上用变量简洁的定位一个内存单元;
- [bx+si]用两个变量表示地址;
- [bx+si+idata]用两个变量和一个常量表示地址。