完整段定义的伪操作
8086/8088在管理内存时,需要按照逻辑段进行划分,不同的逻辑段可以用来存放不同目的的数据。在程序中使用四个段寄存器CS,DS,ES和SS来访问它们。
段定义伪指令
一般格式:
1 | 段名 SEGMENT [定位类型] [组合类型] [‘类别名'] |
定位类型
定位类型用于决定段的起始边界,即第一个可存放数据的位置(不是段基址)
PAGE
表示该段从一个页面的边界开始
由于一个页面为256个字节,并且页面编号从0开始,因此,PAGE定位类型的段起始地址的最后8位二进制数一定为0,即以00H结尾的地址。
PARA
表示该段从一个小节的边界开始
如果用户未选定位类型,则缺省为PARA。
WORD
表示该段从一个偶数字节地址开始,即段起始单元地址的最后一位二进制数一定是0。
BYTE
表示该段起始单元地址可以是任一地址值。
注意:定位类型为PAGE和PARA时,段起始地址与段基址相同。定位类型为WORD和BYTE时,段起始地址与段基址可能不同。
组合类型
用来指定段与段之间的连接关系和定位
NONE
若未指定组合类型,表示本段与其它段无连接关系。在装入内存时,本段有自己的物理段,因此有自己的段基址。
PUBLIC
在满足定位类型的前提下,将不同模块的同名段邻接在一起,形成一个新的逻辑段,共用一个段基址。段内的所有偏移量调整为相对于新逻辑段段基址的偏移量
COMMON
产生一个覆盖段。在多个模块连接时,把该段与其它也用COMMON说明的同名段置成相同的段基址,这样就达到了共享同一存储区。共享存储区的长度由同名段中最大的段确定。
STACK
把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP。
用户程序中应至少有一个段用STACK说明,否则需要用户程序自己初始化SS和SP。
AT表达式
表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值。
MEMORY
表示本段在存储器中应定位在所有其它段这之后的最高地址上。如果有多个用MEMORY说明的段,则只处理第一个用MEMORY说明的段。其余的被视为COMMON
类别名
类别名为某一个段或几个相同类型段设定的类型名称。系统在进行连接处理时,把类别名相同的段存放在相邻的存储区,但段的划分与使用仍按原来的设定。
在定义一个段时,段名是必须有的项,而定位类型、组合类型和类别名三个参数是可选项。各个参数之间用空格分隔。各参数之间的顺序不能改变。
举例:
1 | STACK1 SEGMENT PARA STACK 'STACK0' |
段寻址伪指令
段寻址伪指令ASSUME的作用是告诉汇编程序,在处理源程序时,定义的段与哪个寄存器关联。并不设置各个段寄存器的具体内容,段寄存器的值是在程序运行时设定的。
问题:这个怎么在emu8086中看?
注:可以使用关键字NOTHING将前面的设置删除。
ASSUME ES:NOTHING ;删除前面对ES与某个定义段的关联 ASSUME NOTHING ;删除全部4个段寄存器的设置
段寄存器的装入
DS和ES的装入
没有声明就无法装入
为了改正上述程序中的错误,可以在变量DBYTE2前加一个段前缀说明即可。即: MOV ES:DBYTE2[2], AL
初步小结:貌似既需要用ASSMUE指定段分配到哪个段寄存器里面,也要将段的首地址分配到段寄存器里面?
SS的装入
法一:
1. 组合类型使用STACK参数
2. ASSUME语句与SS关联
3. 栈顶指针SP初始化为最大值(根据声明的堆栈段大小决定)
举例:
法二
类似前面数据段装入,需要额外定义一个变量top
堆栈操作都是按字操作
当前位置计数器$与定位伪指令ORG(Origin)
当前位置计数器$
$表示当前指针地址
定位伪指令ORG
格式
ORG 数值表达式
作用
将数值表达式的值赋给当前位置计数器。ORG相当于移动当前位置指针。赋给它的值必须是正值
举例:
1 | DATA1 SEGMENT |
从程序返回操作系统的方法
使用DOS系统功能调用实现返回
1 | MOV AH,4CH |
程序基本结构
1 | 【例3-11】求字存储单元中两个数之差,结果存入下一个相邻的字单元中。 |
一个段的名字就是一个段的标号,就是这个段的首地址。是个常亮
取变量,变量名字出现在指令中,表示取变量中内容
DOS 功能子程序调用
带显示的键盘输入(1号功能)
将字符的ASCII码送入AL寄存器,并在屏幕上显示该字符
1 | MOV AH,01H |
不带显示的键盘输入(8号功能)
除了不显示字符其他和1号功能一样
1 | MOV AH,8 |
字符显示(2号功能)
打印单个字符
1 | MOV DL, 'A' |
打印单个字符还好,什么叫数字转ASCII码值?还有2位数需要转字符串循环输出
数字转ASCII码方法:数字+‘0’即可
字符串输入(0AH号功能)
缓冲区第一个字节是可输入的最大字符数+1
第二个字节是系统在调用该功能时,自动填入的本次调用时实际输入的字符个数,实际应用时初始化时常设置为0
从第三个字节开始存放输入字符的ASCII码,当用户输入回车键时,结束输入,并将回车键的ASCII码(0DH)作为最后一个字符送入缓冲区。但它不计入实际输入字符个数
参考代码
1 | DATA SEGMENT |
字符串显示(9号功能)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20DATA SEGMENT
CHAR_BUF DB 'This is a test', 0AH, 0DH, '$'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
START:
MOV AX, DATA
MOV DS, AX
MOV DX, OFFSET CHAR_BUF
MOV AH, 9H
INT 21H
; 退出程序
MOV AH, 4CH ; 功能号:退出程序
INT 21H ; 调用 DOS 中断 21H
CODE ENDS
END START
解释:
- 0AH表示换行,将光标移到下一行开头。
- 0DH表示回车,将光标移到当前行开头。