伪操作是汇编程序对源程序进行汇编时处理的操作,(不像机器指令那样是程序运行期间由计算机来执行的)完成处理器选择、存储模式定义、数据定义、存储器分配、指示程序开始结束等功能。 硬指令——使 CPU 产生动作、并在程序运行期间由计算机执行的语句。 伪指令( Directive )——不产生 CPU 动作、在程序执行前由汇编程序处理的说明性语句。例如,数据说明、变量定义等等。 伪指令与具体的处理器类型无关,但与汇编程序的版本有关。 汇编语言语句实例 MOV CX,0 ; 传送指令,具有 2 个操作数 DELAY: NOP ; 空操作指令,没有操作数,带有标号 LOOP DELAY; 循环指令,标号 DELAY 说明转移位置 BUFFER DB 1,2,3,4,5,6,7 ;数据定义伪指令,在主存中开辟 7 个连续的字节单元,初值依次为 1 ~ 7 , BUFFER 表示首地址
1. 完整的段定义伪操作 存储器的物理地址是由段地址和偏移地址组合而成的,汇编程序在把源程序转换为目标程序时,必须确定标号和变量的偏移地址,并且需要把有关信息通过目标模块传送给连接程序,以便连接程序把不同的段和模块连接在一起,形成一个可执行程序。为此需要用段定义伪操作,格式如下: 段名 SEGMENT [ 定位 ] [ 组合 ] [ 使用 ] [' 类别 ' ] ... ; 对数据段 , 附加段和堆栈段 , 一般是存储单元的定 ... ; 义 , 分配等伪操作,对代码段则是指令及伪操作. 段名 ENDS 完整段定义由 SEGMENT 和 ENDS 这一对伪指令实现, SEGMENT 伪指令定义一个逻辑段的开始, ENDS 伪指令表示一个段的结束 段定义指令后的 4 个关键字用于确定段的各种属性,堆栈段要采用 stack 组合类型,代码段应具有‘ code '类别,其他为可选属性参数 如果不指定,则采用默认参数;但如果指定,注意要按照上列次序。
(1) 定位类型:指定逻辑段在主存储器中的边界,可为: BYTE 该段可以从任何地址开始,这样偏移地址可能不是 0 WORD 该段必须从字的边界开始,即段起始地址必须为偶数 DWORD 该段必须从双字的边界开始,即段起始地址的最低两个十六进制数位 须为 4 的倍数 PARA 该段的起始地址必须从小段边界开始,即段起始地址的最低 16 进制数必须为 0 PAGE 该段必须从页的边界开始,即段的起始地址的最低两个十六进制数位必须为 0 简化段定义伪指令的代码和数据段默认采用 WORD 定位,堆栈段默认采用 PARA 定位 完整段定义伪指令的默认定位属性是 PARA ,其低 4 位已经是 0 ,所以默认情况下数据段的偏移地址从 0 开始
(2) 组合类型说明程序连接时的段合并方法,即指定多个逻辑段之间的关系,可为: PRIVATE 本段为私有段,与其他段没有逻辑关系,在连接时不与其他段合并,每段都有自己的段地址。这是完整段定义伪指令默认的段组合方式 PUBLIC 连接程序把本段与所有同名同类型的其他段相邻地连接在一起,然后为所有这些段指定一个共同的段地址,也就是合成一个物理段。这是简化段定义伪指令默认的段组合 STACK 本段是堆栈的一部分,连接程序将所有 STACK 段按照与 PUBLIC 段的同样方式进行合并。这是堆栈段必须具有的段组合
(3)使用类型是支持 32 位段而设置的属性,用来说明使用 16 位寻址方式还是 32 位寻址方式 对于 16 位 x86 CPU 来说,它默认是 16 位段,即 USE16 而对于汇编 32 位 x86 CPU 指令时,它默认采用 32 位段,即 USE32 ;但可以使用 USE16 指定标准的 16 位段 编写运行于实地址方式( 8086 工作方式)的汇编语言程序,必须采用 16 位段 (4) 类别在引号中给出连接时组成段组的类型名。当连接程序组织段时,并不能把相同类别的段合并起来,但可将所有的同类别段相邻分配 段类别可以是任意名称,但必须位于单引号中 大多数 MASM 程序使用 'code' 、 'data' 和 'stack '来分别指名代码段、数据段和堆栈段,以保持所有代码和数据的连续 此外,必须明确段与段寄存器的关系,可用 ASSUME 伪操作来实现。格式: ASSUME 段寄存器:段名 [, 段寄存器名:段名 , ...] 作用 : 通知 MASM 用指定的段寄存器来寻址对应的逻辑段,即建立段寄存器与段的缺省关系,在明确了程序中各段与段寄存器之间的关系后,汇编程序会根据数据所在的逻辑段,在需要时自动插入段超越前缀。这是 ASSUME 伪指令的主要功能。 ASSUME 伪指令并不为段寄存器设定初值,所以在代码段中还必须把段地址装入相应的段寄存器中。例如:定义数据段段名为 DATA ,则需使用 MOV 指令对 DS 段寄存器进行赋值。 MOV AX, DATA MOV DS, AX 如果程序中有堆栈段,也需要把地址装入 SS 中 代码段不需要这样做,代码段的这一操作是在程序初始化时完成的。 例:完整的段定义伪操作 data_1 segment … data_1 ends data_2 segment … data_2 ends code segment assume cs:code,ds:data_1,es:data_2 start: mov ax,data_1 mov ds,ax mov ax,data_2 mov es,ax … code ends end start
2. 存储模型与简化段定义伪操作
(1)MODEL 伪操作 格式: .MODEL memory_model[,model options] 用来表明存储模型,即用来说明在存储器中是如何安放各个段的. 存储模型 memory model 决定一个程序的规模,确定进行子程序调用、指令转移和数据访问的缺省属性 MASM 有 7 种不同的存储模式: ① TINY ② SMALL ③ COMPACT ④ MEDIUM ⑤ LARGE ⑥ HUGE ⑦ FLAT 微型模型是 MASM 6.0 才引入的,用于创建 COM 类型程序。用微型模型编写汇编语言程序时,所有的段地址寄存器都被设置为同一值,这意味着代码段、数据段、堆栈段都在同一个段内,不大于 64KB ;访问操作数或指令都只需要使用 16 位偏移地址。一般用于小程序。 S mall 小型模型是最常用的一种模型。在小型模型下,一个程序至多只能有一个代码段和一个数据段,每段不大于 64KB ,这里的数据段指数据段、堆栈段和附加段的总和,它们共用同一个段基址,总长度不超过 64KB ;访问操作数或指令都只需要使用 16 位偏移地址;代码和数据都是近访问的,小模型下程序的最大长度为 128KB C ompact 紧凑模型适合于数据量大但代码量小的程序。在该模型下,代码段被限制在一个不大于 64KB 的段内;而数据段则可以有多个,超过 64KB 。 代码是近访问的,而数据则可为远访问的。M edium 中型模型是与紧凑模型互补的模型,适合于数据量小但代码量大的程序。中型模式的代码段可以超过 64KB ,有多个;但数据段只能有一个不大于 64KB 的段。数据是近访问,而代码可远访问。 L arge 大型模式允许的代码段和数据段都有多个,都可以超过 64KB ;但全部的静态数据(不能改变的数据)仍限制在 64K 字节内 . 数据和代码都可以远访问。 H uge 巨型模型与大型模型基本相同,只是静态数据不再被限制在 64K 字节之内 F lat 平展模型用于创建一个 32 位的程序,它只能运行在 32 位 x86 CPU 上。 DOS 下不能使用 FLAT 模型,而编写 32 位 Windows 9.x 或 Windows-NT 的程序时,必须采用 FLAT 模型。 DOS 下编程可选择前六种模型,一般可以选用 SMALL 模型, TINY 模式产生 COM 程序,其他模型产生 EXE 程序, FLAT 模型只能用于 32 位程序。 Model options 允许用户指定三种选项:高级语言接口、操作系统和堆栈距离。 高级语言接口选项是指该汇编语言程序作为某一种高级语言程序的过程而为该高级语言程序调用时,应该用C等来说明。 操作系统选项是要说明程序运行于哪个操作系统之下,可用 OS_DOS 或 OS_OS2 来说明,默认是 OS_DOS 。 堆栈距离选项可用 NEARSTACK 或 FARSTACK 来说明,基中 NEARSTACK 是指堆栈段和数据段组合到一个 DGROUP 段中,而 FARSTACK 是指堆栈段和数据段并不合并。 例如: .MODEL SMALL,C .MODEL LARGE,OS_DOS
|