20192410罗雪峰汇编程序设计前四章学习笔记
汇编语言学习笔记
第一章 基础知识
1.1汇编语言的一般概念
三类计算机程序语言:机器语言、高级语言、汇编语言
机器语言过于复杂,不方便记忆;
高级语言屏蔽了许多计算机内部的操作细节,更接近自然语言,程序设计简单,但效率比机器语言低。
汇编语言###
为了特定场合兼顾效率和便于记忆阅读,用字母、符号表示机器语言的命令,用十进制或十六进制表示数据的计算机程序语言
汇编语言与机器语言相对应,效率相同
不同类型的计算机有不同的机器指令系统和汇编语言描述
汇编语言与硬件联系密切
1.2学习和使用汇编语言的目的
(1)从根本上认识、理解计算机的工作过程
(2)在计算机系统中,某些功能必须使用汇编语言实现。如:机器自检、系统初始化、实际的输入输出设备的操作
(3)效率高于高级语言(代码长度和运行速度)
1.3进位计数制和相互转换
1.十进制整数转换为二进制数
(1)减权定位
(2)除基取余
2.十进制小数转换为二进制数
(1)减权定位
(2)乘基取整
3.二进制数转换为十进制数
(1)按权相加
(2)逐次乘基相加法
4.二进制小数转换为十进制数
(1)按权相加
(2)逐次除基相加法
5.二进制与八进制和十六进制间的转换
三位二进制对应一位八进制,四位二进制数对应一位十六进制数
1.4带符号数的表示
在计算机中用“0”、“1”来表示正负
用“+”或“-”表示正负的数叫真值
用“0”或“1”表示正负的数叫机器数
一、原码
二进制最高位表示符号,其他位表示数
以8位二进制数原码为例
- 最大数:01111111(+127)
- 最小数:11111111(-127)
0的原码有两种:00000000和10000000(+0和-0)
二、补码
[X]补=M+X (Mod M)
M根据机器数的位数而定
正数补码与原码相同,负数则需要变换
由真值、原码变换为补码
-
真值各位取反,末位加1
-
原码保持符号位不变,其余各位取反,末位加1
补码数的表示范围
同样以8位数为例
- 最大补码为01111111=[+127]补
- 最小补码为10000000=[-128]补
0的补码只有一个,[0]补=00000000,而10000000是[-128]补,11111111=[-1]补
补码的加减运算
-
[X+Y]补 = [X]补+[Y]补
-
[X-Y]补=[X]补-[Y]补=[X]补+[-Y]补
[-Y]补是对[Y]补执行一次求补运算,即将原数连同符号位一起按位取反,末位加1
1.5字符的表示
ASCII码为一字节,低七位表示字符编码,最高位表示奇偶校验
128个ASCII码分为两类
- 非打印ASCII码 33个
- 可打印ASCII码 95个
第二章 IBM-PC微机的功能结构
2.1 IBM-PC微机基本结构
一、微机的一般构成
一般计算机包括五大部件:
运算器、控制器、存储器、输入和输出设备
运算器+控制器=CPU
习惯上将CPU与主存储器合称为主机
二、Intel 8086/8088 CPU的功能结构
CPU执行指令序列就是重复执行:
- 从存储器中取指令
- 执行指令规定的操作
执行方式分为串行和指令流水线方式
-
串行方式
- CPU执行指令时不需要占用系统总线,但此时总线也不工作,导致系统总线空闲时间较多
- 总线从存储器取指令、数据或存数据时,总线占用时间较长,CPU却只需要很短的时间处理从而很长时间处于闲置状态、
-
指令流水线方式
CPU组成结构上要划分为多个单元。8086/8088CPU被划分成两个单元:执行单元(EU)和总线接口单元(BIU)
-
执行单元EU
分析与执行指令
-
总线接口单元BIU
CPU与存储器、I/O的信息传送。具体有取指令、存取数据
EU和BIU一定程度上是并行工作,提高了效率
-
2.2Intel 8086/8088CPU寄存器结构及其用途
一、通用寄存器
-
数据寄存器
AX、BX、CX、DX
用来存放参加运算的操作数或者结果
多数情况下使用这些寄存器需要在指令中明确指示,但是在某些指令中并不需要,即隐含使用
-
指针寄存器
堆栈指针SP和基址指针BP
一般用来存放16位地址,形成20位的物理地址时常被作为偏移量使用
-
变址寄存器
- SI 源变址寄存器
- DI 目的变址寄存器
两者与BP寄存器一样,SI和DI也可以用作通用数据寄存器存放操作数和运算结果。
二、段寄存器
CPU使用存储器时将其划分为若干段,如程序代码段、数据段,每段用一个段寄存器指明段基址
CPU访问存储器时须指明存储单元所属段和偏移量
三、指令指针IP
从存储器取指令时,以段寄存器作为代码段的基址指针,以IP为偏移量。CPU取出一条指令后,IP内容自动修改指向下一条指令。
IP的内容不能被直接访问,但是可通过某些指令的执行而自动修改IP的内容。
四、标志寄存器
用来反映CPU在程序运行时的某些状态
- CF(进位标志位) 最高位
- PF(奇偶标志位) 低八位含1个数
- AF(辅助进位标志位) 低四位向高四位
- ZF(零值标志位)
- SF(符号标志位)
- OF(溢出标志位)
- TF(单步标志位)
- IF(中断允许标志位)
- DF(方向标志位) 规定串操作指令的增减方向
2.3存储器的组织结构
一、存储器的组成
- 由若干存储单元构成
- 每个存储单元存放相同长度的二进制数,且有唯一的地址编号
- 定义一个地址时必须指出字节或字类型属性
二、存储器的段结构
特点:
-
CPU将1MB的存储空间划分成若干段,每段最大长度为64k(CPU内部寄存器长度只有16位)
-
段基址必须是一个小节的首址
存储器规定从0地址开始每16个字节单元称为一个小节,1MB内存可划分为64个小节
-
逻辑段在物理地址中可以是邻接的、间隔的、部分重叠的和完全重叠的
内存中的一个物理存储单元可以映射到一个或多个逻辑段中
-
任一时刻,一个程序只能访问四个当前段中的内容
代码段、数据段、堆栈段和附加段称为当前段,四个段寄存器CS、DS、SS、ES分别保存它们段基址的高16位,称为段基值
三、逻辑地址与物理地址及对应关系
-
物理地址 每个存储单元的物理地址唯一
-
逻辑地址 包括段基值和偏移量
-
逻辑地址转换位物理地址
段基值左移4位,再与偏移量相加
-
逻辑地址的来源
- 允许替代来源也叫做段超越
- 有效地址EA表示指令所采用的寻址方式计算出的段内偏移量
2.4堆栈及其操作方法
堆栈主要用于暂存数据以及在过程调用或处理中断时保存断点信息
一、堆栈的构造
- 专用堆栈存储器
- 软件堆栈
SP始终指向栈顶
先进后出FILO
二、堆栈的组织
SP初始化时指向栈底+2,值为堆栈的长度
数据在堆栈中以字为单位存放,低8位在较低地址单元,高8位在较高地址单元
三、堆栈操作
-
设置堆栈
主要是对SS、SP赋值
-
进栈PUSH
- SP-2
- PUSH
-
出栈POP
- SP指向的内容送往指定的寄存器或存储器
- SP+2
第三章 寻址方式与指令系统
3.1 寻址方式
一条指令通常由两大部分构成:操作码和操作数
提供操作数的方法:
-
立即数操作数——操作数在指令代码中提供
-
寄存器操作数——操作数在CPU的通用寄存器或段寄存器中
-
存储器操作数——操作数在内存的存储单元中
-
I/O端口操作数——操作数在输入/输出接口的寄存器中
寻址方式:寻找操作数的方法
1.立即数寻址
不需另外占用总线周期,执行速度快
立即数只能作为源操作数。
2.寄存器寻址
不需另外占用总线周期,执行速度快
一个存储单元逻辑地址表示形式:段基值:偏移量
偏移量也叫做有效地址EA,是位移量、基址、变址三个地址分量的几种组合
以下是这三个地址分量的不同组合形成的四种寻址方式
3.直接寻址
操作数的有效地址EA只有位移量地址分量。
汇编语言中,直接寻址用符号或常数表示
符号   MOV BX,VAR
常数   MOV AX, DS:[64H]
4.寄存器间接寻址
操作数有效地址EA直接从基址寄存器(BX或BP)或变址寄存器(SI或DI)中获得。
指示存储器所在段的段寄存器可以省略,当指令中使用的是BP寄存器,则隐含表示使用SS段寄存器,其余情况则隐含使用DS段寄存器。
5.基址寻址/变址寻址
操作数的有效地址EA等于基址分量或变址分量加上指令中给出的位移量。
注意:当位移量为常数时,不能加方括号
2、3两种寻址方式中寄存器中的内容是相对于由位移量指定的初始单元。因此也叫**寄存器相对寻址**。
6.基址变址寻址
操作数的有效地址是三个地址分量之和,即EA=基址+变址+位移量
在基址变址寻址方式中,程序运行期间有两个地址分量可以修改。因此它是最灵活的一种寻址方式,可以方便地对二维数组进行访问。
7.串操作寻址方式
设置有专门用于串操作的指令
隐含地使用变址寄存器SI和DI专门指示。
- 寻找源操作数时,隐含使用SI作为地址指针。
- 寻找目的串时,隐含使用DI作为地址指针。
- 串操作完成之后,自动对SI和DI进行修改,使它们指向下一个操作数。
8.I/O端口寻址
在计算机系统,对I/O端口的寻址方式有以下两种方法。
-
存储器编址方法
将IO端口视为存储器的一个单元,对端口的访问就如同访问存储单元一样。访问存储器的指令和各种寻址方式同样适用对I/O端口的访问。
特点:程序设计灵活,但需要占用存储地址空间。
-
IO端口编址方法
I/O端口的地址与存储器地址分开,并使用专门的输入指令和输出指令。
(1)直接端口寻址
在指令中直接给出端口地址,可访问的端口数为0~255个。
(2)寄存器间接端口寻址
把I/O端口的地址先送到DX中。如果访问端口地址值大于255,则必须用I/O端口的间接寻址方式。
3.2 指令系统
一种计算机所能执行的各种类型的指令的集合称为该计算机的指令系统。
Intel8086/8088CPU指令系统的指令可以分为六大类:
- 传送类指令
- 算术运算类指令
- 位操作类指令
- 串操作类指令
- 程序转移类指令
- 处理器控制类指令
从指令的格式划分,一般可以分为三种:
-
双操作数指令:OPR DEST SRC
-
单操作数指令:OPR DEST
-
无操作数指令:OPR
- 指令不需要操作数,如暂停指令HLT。
- 在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如指令PUSHF。
一、传送类指令
-
通用数据传送指令
源操作数传送到目的操作数
对标志寄存器无影响
MOV指令源操作数和目的操作数的长度必须一致。
MOV指令可分为以下几种情况:
-
立即数传送到通用寄存器或存储单元
立即数只能作源操作数,立即数不能传送给段寄存器。
-
寄存器之间的传送,
段寄存器CS只能作源操作数,不能作目的操作数。
-
寄存器与存储单元之间传送
总结:
- 立即数只能作源操作数,立即数不能传送给段寄存器。
- 段寄存器CS只能作源操作数,不能作目的操作数。
- 存储单元之间不能直接传送数据
- MOV指令不影响标志位
-
-
交换指令
指令格式:XCHG DEST,SRC
源操作数和目的操作数内容互换。
交换可以在寄存器之间或寄存器与存储器之间。但不能在存储单元之间进行,寄存器只能使用通用寄存器。
-
标准传送指令
-
取标志寄存器指令
指令格式:LAHF
将标志寄存器低8位送入AH
-
存储标志寄存器指令
指令格式:SAHF
将AH中的7、6、4、2、0位分别送入标志寄存器的SF、ZF、PF、CF,高八位则不受影响
-
标志进栈指令
指令格式:PUSHF
-
标志出栈指令
指令格式:POPF
-
-
地址传送指令(存储单元地址->寄存器)
-
装入有效地址
格式:LEA DEST,SRC
将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中
-
装入地址指针指令
格式:LDS DEST,SRC
LES DEST,SRC
DEST是任一16位通用寄存器。SRC是存储器操作数
作用:把SRC存储单元开始的四字节单元(32位地址指针)送入DEST通用寄存器和段寄存器DS(LDS指令)或ES(LES指令),其中低字单元内容位偏移量送通用寄存器,高字单元内容为段基值送DS或ES
-
二、算术运算类指令
-
加法指令
指令格式:ADD DEST,SRC
DEST不能是立即数
-
带进位加法指令
指令格式:ADC DEST,SRC
-
加1指令
指令格式:INC DEST
不影响CF
-
减法指令
指令格式:SUB DEST,SRC
DEST和SRC不能同时为存储器操作数,立即数只能为源操作数
-
带借位减法
指令格式:SBB DEST,SRC
-
减1指令
指令格式:DEC DEST
-
求负数指令(取补指令)
指令格式:NEG DEST
只有当操作数为0时,CF置0
当操作数为-128或-32768时,OF置1
三、位操作类指令
-
逻辑运算指令
- 逻辑“与”指令 AND DEST,SRC
- 逻辑“或”指令 ORD EST,SRC
- 逻辑“异或”指令 XOR DEST,SRC
- 逻辑“非”指令 NOT DEST
逻辑指令对标志位的影响:
NOT指令对标志无影响。而其余三条指令将根据结果影响SF、ZF和PF,而CF和OF总是置0,AF为不确定。
-
测试指令
指令格式:TEST DEST,SRC
该指令与AND指令相似,但运算结果不送入目的操作数,即目的操作数内容也将保持不变。
-
移位/循环移位指令
这一类指令共有8条,分为3类。
-
算术移位
算术左移 SAL DEST,COUNT 算术右移 SAR DEST,COUNT
-
逻辑移位
逻辑左移SHL DEST,COUNT 逻辑右移 SHR DEST,COUNT
-
循环移位
小循环:
循环左移 ROL DEST,COUNT
循环右移 ROR DEST,COUNT大循环:
带进位循环左移 RCL DEST,COUNT
带进位循环右移 RCR DEST,COUNT
共同点:
1.DEST为操作对象,它可以是字节或字操作数,可以是通用寄存器或存储器操作数。 2.COUNT用来决定移位/循环的位数,即确定移位的次数。 3.在执行移位时,根据指令不同,每移位一次,最高位(左移)或最低位(右移)都要送到进位标志CF。 4.前4条移位指令根据移位结束后修改标志位CF、PF、ZF、SF和OF,而AF不确定。而后4条循环移位指令根据移位结束后的结果仅修改CF和OF。
-
四、处理器控制类指令
-
标志位操作指令
(1)清除进位标志 CLC;置CF为0(2)置1进位标志 STC;置CF为1
(3)进位标志取反 CMC;CF的值取反
(4)清楚方向标志 CLD;置DF为0
(5)置1方向标志 STD;置DF为1
(6)清除中断标志 CLI;置IF为0
(7)置1中断标志 STI;置IF为1
-
与外部事件同步的指令
- HLT;暂停指令
- WAIT;等待指令
- ESC;外部协处理器指令前缀
- LOCK;总线锁定指令
-
空操作指令 NOP
3.3指令编码
汇编指令的编码格式有四种基本格式:
- 双操作数指令编码格式
- 单操作数指令编码格式
- 与AX或AL有关的指令编码格式
- 其它指令编码格式
一、双操作数指令编码格式
对于像MOV、ADD、AND等双操作数指令,操作数可以是以下两种情形:
- 一个操作数在寄存器中,另一操作数在寄存器或存储器中。
- 目的操作数在寄存器或存储器中,源操作数是立即数。
整个指令编码可以包含4个部分:操作特征、寻址特征、位移量、立即数,其中某些部分在一些指令中可以没有
1.操作特征部分
-
OPCODE:操作码字段 表示指令的功能以及两个操作数的来源
-
方向字段d 与第2部分寻址特征一起来决定源操作数和目的操作数的来源。
当源操作数为立即数Imm时,d字段无效,它被并入操作码字段。
-
字\字节字段W
当W=1时,表示两操作数长度为字;当W=0时,表示两操作数长度为字节。
2.寻址特征部分
包括MOD、REG、R/M三个字段,REG确定一个操作数,其余两者确定另一个操作数
- 当d=1时,则目的操作数由REG字段确定,而源操作数由MOD和R/M字段确定。
- 当d=0时,则目的操作数由MOD和R/M字段确定,而源操作数由REG字段确定。
3.位移量部分
- 没有位移量
- 1字节位移量disp8
- 2字节位移量disp16
4.立即数部分
二、单操作数指令编码格式
操作特征、寻址特征、位移量
操作特征部分:
包括OPCODE、V和W三个字段,其中V字段只有移位/循环指令中才有该字段。其它指令中没有该字段。
- V=0时,指令中使用常数1作为移位或循环次数。
- V=1时,指令中使用寄存器CL作移位次数。
三、与AX或AL有关的指令编码格式
用于隐含指定AX/AL作为一个操作数的双操作数指令
第四章 汇编语言程序格式
4.1汇编语言语句种类及其格式
汇编语言的语句可以分为指令语句和伪指令语句
一、指令语句
每一条指令语句在汇编时都要产生一个可供CPU执行的机器目标代码,又叫可执行语句。
指令语句的一般格式为:
1.标号字段
可选字段,后面必须有“:”。标号是一条指令的符号地址,代表了该指令的第一个字节存放地址。
一般放在入口
2.指令助记符字段
必选项,表示这条语句要求CPU完成什么具体操作
有时还可加上前缀实现附加操作
3.操作数字段
一条指令可以有一个操作数、两个操作数或者无操作数。
4.注释字段
可选项,以分号“;”开始。为说明性内容
二、伪指令语句
伪指令语句又叫命令语句。仅仅是告诉汇编程序对其后面的指令语句和伪指令语句的操作数应该如何处理。
一条伪指令语句可以包含四个字段:符号名、伪指令符、操作数、注释
1.符号名字段
可选项。可以是常量名、变量名、过程名、结构名和记录名等等。
一条伪指令语句的符号名可作为其他伪指令或指令语句的操作数,此时其表示一个常量或存储器地址
符号名后面没有冒号“:”,这是与指令语句的重要区别。
2.伪指令符字段
必选项,规定功能。
3.操作数字段
该字段的数量由伪指令符字段来决定。
操作数可以是常数、字符串、常量名、变量名、标号和一些专用符号。
4.注释字段
与指令语句的注释字段相同。
三、标识符
指令语句中的标号和伪指令语句中符号名统称为标识符。
标识符构成规则:
- 字符的个数为1~31个;
- 第一个字符必须是字母、问号、@或下划线“_”这4种字符一;
- 从第二个字符开始,可以是字母、数字、@、“_”或问号“?”;
- 不能使用系统专用的保留字;
4.2汇编语言数据
操作数的基本组成部分。由数值和属性两部分构成。
常用的数据形式:常数、变量、标号
一、常数
汇编期间其值已完全确定,在程序运行过程中,其值不会发生变化。有以下几种形式:
- 二进制数
- 八进制数
- 十进制数
- 十六进制数
- 实数。一般格式为:±整数部分·小数部分E±指数部分
- 字符串常数:用引号(单引号或双引号)括起来的一个或多个字符,这些字符以它的ASCII码值存储在内存。
常数在程序中可以用在以下几种情况:
- 作指令语句的源操作数
- 在指令语句的直接寻址方式、变址(基址)寻址方式或基址变址寻址方式中作位移量。
- 在数据定义伪指令中使用
二、变量
变量用来表示存放数据的存储单元,在程序运行期间可以被改变。
可以认为变量名就是存放数据的存储单元地址
1.变量的定义与预置
给这个存储单元赋与一个符号名,即变量名,同时预置初值。
变量定义一般格式:
其中表达式1、表达式2是给存储单元赋的初值。
变量被定义后,就有了以下三个属性:
- 段属性 表示变量存放在哪一个逻辑段中
- 偏移量属性(OFFSET) 段属性和偏移量构造了逻辑地址
- 类型属性 占用字节数
给变量赋初值的表达式可以使用下面4种形式:
-
数值表达式
-
?表达式 不带引号的问号“?”表示可以预置任意内容。
-
字符串表达式
对于DB伪指令,从左到右,ASCII码地址递增
对于DW伪指令,给两个字符组成的字符串分配两个字节,前一个字符放高地址,后一字符放低地址
对于DD伪指令,只能给两个字符组成的字符串分配4个字节单元。两个字符放在低地址,高地址放0
-
DUP表达式(重复数据操作符)
表达式1是重复的次数,表达式2是重复的内容
可嵌套使用
2.变量的使用
(1)在指令语句中引用
当变量出现在变址(基址)寻址或基址变址寻址的操作数中时表示取用该变量的偏移量。
(2)在伪指令语句中引用
它表示取变量地址的偏移量
三、标号
标号写在一条指令的前面,它就是该指令在内存的存放地址的符号表示,也就是指令地址的别名。
标号主要用在程序中需要改变程序的执行顺序时,用来标记转移的目的地,即作转移指令的操作数。
标号具有三属性:
-
段属性(SEG)
-
偏移量属性(OFFSET)
-
距离属性(也叫类型属性)
NEAR:只能作段内转移
FAR:可以被非本段的转移和调用指令使用
距离属性有两种方法指定:
- 隐含方式 标号在指令语句前面,隐含为NEAR
- 用LABEL伪指令给标号指定距离属性
4.3符号定义语句
在源程序设计中,使用符号定义语句可以将常数或表达式等内容用某个指定的符号来表示。在8086/8088汇编语言中有两种符号定义语句。
一、等值语句
语句格式:符号名 EQU 表达式
功能:用符号名来表示EQU右边的表达式。后面的程序中一旦出现该符号名,汇编程序将把它替换成该表达式。表达式可以是任何形式,常见的有以下几种情况。
- 常数或数值表达式
- 地址表达式
- 变量、寄存器名或指令助记符
同一源程序中,同一符号不能用EQU定义多次
二、等号语句
格式:符号名=表达式
可以对一个符号进行多次定义。 不能为助记符定义别名
等值语句与等号语句都不会为符号分配存储单元。因此所定义的符号没有段、偏移量和类型等属性。
4.4表达式与运算符
任何表达式的值在程序被汇编的过程中进行计算确定,而不是到程序运行时才计算。
一、算术运算符
1.运算符“+”和“-”也可作单目运算符,表示数的正负。
2.使用“+”、“-”、“*”、和“/”运算符时,参加运算的数和运算结果都是整数。
3.“/"运算为取商的整数部分,而“MOD”运算取除法运算的余数。
4.“SHR ”和“SHL”为逻辑移位运算符
移位运算符的操作对象是某一具体的数(常数),在汇编时完成移位操作。而移位指令是对一个寄存器或存储单元内容在程序运行时执行移位操作。
5.下标运算符“[]”具有相加的作用
一般使用格式:表达式1[表达式2]
二、逻辑运算符
- NOT
- AND
- OR
- XOR
都是按位逻辑运算。
三、关系运算符
包括:EQ(等于)、NE(不等于)、LT(小于)、LE(小于等于)、GT(大于)、GE(大于等于)
关系运算符比较的两个表达式必须同为常数或同一逻辑段中的变量。如果是常量的比较,则按无符号数进行比较;如果是变量的比较,则比较它们的偏移量的大小。
四、数值返回运算符
有5个,它们将变量或标号的某些特征值或存储单元地址的一部分提取出来。
1.SEG运算符
取变量或标号所在段的段基值。
2.OFFSET运算符
取变量或标号在段内的偏移量。
3.TYPE运算符
取变量或标号的类型属性,并用数字形式表示。对变量来说就是取它的字节长度。
4.LENGTH运算符
取变量的长度。
5.SIZE运算符
只能作用于变量,SIZE取值等于LENGTH和TYPE两个运算符返回值的乘积。
五、属性修改运算符
这一类运算符用来对变量、标号或存储器操作数的类型属性进行修改或指定。
1.PTR运算符
格式:类型 PTR 地址表达式
将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为“类型”所指的值。
修改是临时的,旨在含有该运算符的语句内有效
2.HIGH/LOW运算符
格式:HIGH 表达式
LOW 表达式
用来将表达式的值分离出高字节和低字节
将常量分离成高8位和低8位;将地址(段基值或偏移量)分离出高字节和低字节。
HIGH/LOW运算符不能用来分离一个变量、寄存器或存储器单元的高字节与低字节。
3、THIS运算符
一般与等值运算符EQU连用,用来定义一个变量或标号的类型属性。所定义的变量或标号的段基值和偏移量与紧跟其后的变量或标号相同。
六、运算符的优先级
- 先执行优先级别高的运算,再算较低级别运算;
- 相同优先级别的操作,按照在表达式中的顺序,从左到右进行;
- 可以用圆括号改变运算的顺序。
4.5程序的段结构
8086/8088按照逻辑段划分管理内存,使用伪指令来定义和使用逻辑段。
一、段定义伪指令
伪指令SEGMENT和ENDS用于定义一个逻辑段。使用时必须配对,分别表示定义的开始与结束。
一般格式:
1.段名
用户自己任意选定的,符合标识符定义规则的一个名称。
2.定位类型
决定段的起始边界,即第一个可存放数据的位置(不是段基址)。
它可以有4种取值。
(1)PAGE:表示该段从一个页面的边界开始
(2)PARA:表示该段从一个小节的边界开始
(3)WORD:表示该段从一个偶数字节地址开始,即段起始单元地址的最后一位二进制数一定是0。
(4)BYTE:表示该段起始单元地址可以是任一地址值。
定位类型为PAGE和PARA时,段起始地址与段基址相同。定位类型为WORD和BYTE时可能不同。
3、组合类型
组合类型说明符用来指定段与段之间的连接关系和定位。它有六种取值选择。
(1)若未指定组合类型,表示本段与其它段无连接关系。在装入内存时,本段有自己的物理段,因此有自己的段基址
(2)PUBLIC:在满足定位类型的前提下,将与该段同名的段邻接在一起,形成一个新的逻辑段,共用一个段基址。段内的所有偏移量调整为相对于新逻辑段的段基址。
(3) COMMON:产生一个覆盖段。在多个模块连接时,把该段与其它也用COMMON说明的同名段置成相同的段基址,这样可达到共享同一存储区。共享存储区的长度由同名段中最大的段确定。
(4)STACK:把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP。
用户程序中应至少有一个段用STACK说明,否则需要用户程序自己初始化SS和SP。
(5)AT表达式:表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值。
(6)MEMORY:表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用MEMIORY说明的段,则只处理第一个用MEMIORY说明的段。其余的被视为COMMON
4.类别名
类别名为某一个段或几个相同类型段设定的类型名称。系统在进行连接处理时,把类别名相同的段存放在相邻的存储区,但段的划分与使用仍按原来的设定。
在定义一个段时,段名是必须有的项,而定位类型、组合类型和类别名三个参数是可选项。各个参数之间用空格分隔。各参数之间的顺序不能改变。
二、段寻址伪指令
段寻址伪指令ASSUME的作用是告诉汇编程序,在处理源程序时,定义的段与哪个寄存器关联。
一般格式:ASSUME 段寄存器:段名,段寄存器名:段名,...
其中段名是用SEGMENT/ENDS伪指令定义的段名。
在一个代码段中可以有几条ASSUME伪指令,对于前面的设置,可以用ASSUME改变原来的设置。
一条ASSUME语句不一定设置全部段寄存器,可以选择其中一个或几个段寄存器。
可以使用关键字NOTHINC将前面的设置删除。
三、段寄存器的装入
段寄存器的初值(段基值)装入需要用程序的方法来实现。四个段寄存器的装入方法略有不同。
-
DS和ES的装入
用数据传送语句来实现对DS和ES的装入。
-
SS的装入
两种方法
- 在段定义伪指令的组合类型项中,使用STACK参数,并在段寻址伪指令ASSUME语句中把该段与SS段寄存器关联。
- 如果在段定义伪指令的组合类型中,未使用STACK参数,或者是在程序中要调换到另一个堆栈,这时,可以使用类似于DS和ES的装入方法。
-
CS的装入
CPU在执行指令之前根据CS和IP的内容来从内存中提取指令,即必须在程序执行之前装入CS和IP的值。因此,CS和IP的初始值就不能用可执行语句来装入。
装入CS和IP一般有下面两种情况。
- 由系统软件按照结束伪指令指定的地址装入初始的CS和IP任何一个源程序都必须以END伪指令来结束。 其格式为:END起始地址
- 在程序运行期间,当执行某些指令时,CPU自动修改CS和IP,使它们指向新的代码段。
4.6过程定义伪指令(PROC/ENDP)
在程序设计过程中,常常将具有一定功能的程序段设计成一个子程序。在MASM宏汇编程序中,用过程(PROCEDURE)来构造子程序。
格式:
过程名 PROC [NEAR/FAR]
...RET...
过程名 ENDP
过程名是子程序的名称,被用作过程调用指令CALL的目的操作数。具有段、偏移量和距离三个属性。而距离属性使用NEAR和FAR来指定,若没有指定,则隐含为NEAR。
4.7当前位置计数器$与定位伪指令ORG(Origin)
汇编程序在汇编源程序时,每遇到一个逻辑段,就要为其设置一个位置计数器,它用来记录该逻辑段中定义的每一个数据或每一条指令在逻辑段中的相对位置。
在源程序中,使用符号$来表示位置计数器的当前值。因此,$被称为当前计数器。它位于不同的位置具有不同的值。
位置计数器$在使用上完全类似变量的使用。
定位伪指令ORG--用来改变位置计数器的值。
格式:ORG 数值表达式
作用:将数值表达式的值赋给当前位置计数器$。ORG语句为其后的数据或指令设置起始偏移量。
4.8标题伪指令TITLE
语句格式:TITLE标题名
作用:给所在程序指定一个标题。
4.9从程序返回操作系统的方法
为了使程序运行结束后,能够正确地返回到操作系统,需要在程序中加上一些必要的语句。一般有以下两种方法。
-
使用程序段前缀PSP (Program Segment Prefix)实现返回
- 将用户程序编制成一个过程,类型为FAR;
- 将PSP的起始逻辑地址压栈,即将INT 20H指令的地址压栈;
- 在用户程序结尾处,使用一条RET指令。执行该指令将使保存在堆栈中的PSP的起始地址弹出到CS和IP中。
-
使用DOS系统功能调用实现返回
执行DOS功能调用4CH,也可以控制用户程序结束,并返回DOS操作系统。
在程序结束时,使用两条指令:
MOV AH,4CH INT 21H
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现