汇编语言程序设计(三)-基础语法知识

 汇编语言的伪指令
  汇编语言中有3种基本语句:指令语句、伪指令语句和宏指令语句。
  指令语句是上一章介绍的指令,它们经过汇编之后产生可供计算机硬件执行的机器目标代码,所以这种语句又称为执行语句;伪指令语句是一种说明(指示)性语句,仅仅在汇编过程中告诉汇编程序应如何汇编,例如告诉汇编程序已写出的汇编评议程序有几个段,段的名称是什么?是否采用过程?汇编到某处是否需要留出存储空间?应留多大?是否要用到外部变量等。所以,伪指令语句是一种汇编程序在汇编时用来控制汇编过程以及向汇编程序提供汇编相关信息的批示性语句。与指令语句不同,伪指令语句其本身并不直接产生可供计算机硬件执行的机器目标代码,它仅是一种非执行语句。
  宏指令语句用于替代源程序中一段有独立功能的程序,由汇编时产生相应的目标代码。宏指令语句是使用指令语句和伪指令语句,由用户自己定义的新指令。本教材对宏指令语句不作讨论,在这一节里只介绍几种常用的伪指令语句。
  1.数据定义伪指令
  该指令的功能是把数据项或项表的数值存入存储器连续的单元中,并把变量名与存储单元地址联系在一起。在程序中,用户可以用变量名来访问这些数据项。
  数据定义伪指令的格式如下:
    
  其中,变量名是任选项。
  若用DB定义变量,则变量类型为BYTE,汇编时为每个操作数分配一个存储单元;
  若用DW定义变量,则变量类型为WORD,汇编时为每个操作数分配2个存储单元,操作数的低字节在低地址,高字节在高地址;
  若用DD定义变量,则变量类型为DWORD,汇编时为每个操作数分配4个存储单元,操作数的低字节在低地址,高字节在高地址。
  2.符号定义伪指令
  在编制源程序时,程序设计人员常把某些常数、表达式等用一特定符号表示,这样,为编写程序带来许多方便。为此,就要使用符号定义语句,这种语句有以下两种:
  (1)赋值伪指令
  赋值伪指令是为表达赋予一个符号名,其后指令中凡需要用到该表达式的地方均可以用此名字来代替。缩写程序时,通过使用赋值伪指令可以使汇编语言简明易懂,便于程序的调试和修改。赋值伪指令的格式如下:
  符号名 EQU 表达式
  符号名是必需项,赋值伪指令仅在汇编源程序时作为替代符号用,不产生任何目标代码,也不占用存储单元。因此,赋值伪指令左边的符号名没有段、偏移量和类型3个属性。同一符号名不能重复定义。表达式可以是常数表达式、地址表达式、变量名、标号名、过程名、寄存器名或指令名等。如果表达式包含有变量、标号或过程名,则应在EQU语句以前的某处定义过。
  (2)等号伪指令
  语句格式: 符号名=表达式
  这种语句的含义和表达的内容都与赋值语句相同;但是等号语句可以重新定义符号。
  3.类型定义伪指令
  类型定义伪指令的格式如下:
  变量名或标号名 LABEL 类型
  LABEL伪指令为当前存储单元重新定义一个指定类型的变量或标号,该伪指令并不为指定的变量或标号分配存储单元。
  例如:DA-BYTE LABEL BYTE
     DA-WORD DW 20H DUP(0)
  上面第二个语句是定义了20H个字单元,如要对这数组元素中某单元以字节访问它,则可以很方便地直接使用DA-BYTE变量名。DA-BYTE和DA-WORD有相同 段和偏移量属性。同样,也可以有:
  JUMP-FAR LABEL FAR
  JUMP-NEAR:MOV AL,30H
  当从段内某指令来调用这程序段时,可以用标号JUMP-NEAR,如果从另一代码段来调用时,则可用JUMP-FAR标号。
运算符THIS和LABEL伪指令有类似的效果,上面两条LABEL伪指令可分别改为:
  DA-BYTE EQU THIS BYTE
  JUMP-FAR EQU THIS FAR 

  4.段定义伪指令
  我们知道,8086/8088CPU的地址空间是分段结构的。因此,我们在编制任一源程序时,亦必须按段来构造程序。一个程序通常按用途划分成几个逻辑段(至少要定义一个段),如存放数据的段、作堆栈使用的段、存放主程序的段、存放子程序的段等等。那么,如何告诉汇编程序源程序中的哪些内容属于数据段、哪些内容属于代码段呢?这自然是由汇编系统中提供的伪指令来实现。
  段定义伪指令的功能就是把源程序划分为逻辑段,便于汇编程序在相应段名下生成目标码,同时也便于连接程序组合、定位、生成可执行的目标程序。利用段定义伪指令可以定义一个逻辑段的名称和范围,并且指明段的定位类型、组合类型和类别名,其指令格式如下:
  

  在源程序中,每一段都是以SEGMENT伪指令开始,以ENDS伪指令结束。其中:
  (1)段名
  由用户自己选定,通常使用与本段用途相关的名字。如第一数据段DATA1,第二数据段DATA2,堆栈段STACK,代码段CODE……一个段开始与结尾用的段名应一致。
  (2)段参数
  段参数有定位类型、组合类型和类别名,各之间必须用空格分隔。同时,它们必须按给定的顺序排定,它们都是任选项,它们决定了段与段之间联系的形态。
  ①定位类型
  定位类型表示对该段起始边界的要求,可有4种选择:
  ·BYTE 起始地址=×××× ×××× ×××× ×××× ××××,即字节型,表示本段起始单元可以从任一地址开始。
  ·WORD 起始地址=×××× ×××× ×××× ×××× ×××0,即字型,表示本段起始地址可以是任何一个字的边界(偶地址)。
  ·PARA 起始地址=×××× ×××× ×××× ×××× 0000,即节型,表示本段起始地址必须从存储器的某一个节的边界开始(1节等于16个字节)。
  ·PAGE 起始地址=×××× ×××× ×××× 0000 0000,即页型,表示本段起始地址必须从存储器的某一个页的边界开始(1页等于256个字节)。
  对于上述4种定位类型,它们20位边界地址分别可以被1、2、16、256除尽,分别称为以字节、字、节、页为边界。其中,PARA为隐含值,即如果省略"定位类型",则汇编程序按PARA处理。

  ②组合类型
  组合类型指定段与段之间是怎样连接和定位的。它批示连接程序,如何将某段与其他段组合起来的关系。连接程序不但可以将不同模块的同名段进行组合,并可根据组合类型,将各段顺序地或重叠地连接在一起。其中有6种组合类型可供选择:
  ·NONE类型
表示该段与其他段在逻辑上不发生连接关系,这是隐含的组合类型,若省略"组合类型"项,即为NONE。
  ·PUBLIC类型
  表连接时,应把不同模块中属于该类型的同名同类别的段相继顺序地连成一个逻辑运算时装入同一物理段中,使用同一段基址。连接顺序与LINK时用户所提供的各模块的顺序一致,应当注意,各模块中属于PUBLIC类型的同名同类别的各段的总长度不能超64KB。
  ·STACK类型
  与PUBLIC类型同样处理,只是组合后的该段用作堆栈。当段定义中指明了STACK类型后,说明堆栈已经确定,系统自动对段寄存器SS初始化在这个连续段的首址,并初始化堆栈指针SP。用户程序中至少有一个段用STACK类型说明,否则需要用户程序自己初始化SS和SP。
  ·COMMON类型
  表明连接时,应将不同模块中属于该类型的同名同类别的各段连接成一段,它们共用一个基地址,且互相覆盖(重叠地放在一起),连接后,段的长度取决于最长的COMMON段的长度,这样可以使不同模块的变量或标号使用同一存储区域,便于模块间的通信。
  ·AT表达式类型
  表示本段可定位在表达式所指示的节边界上。如"AT 0930H",那么本段从绝对地址09300H开始。但是,它不能用来指定代码段。
  ·MEMORY类型
  表明连接时应把本段装在被连接的其他所有段的最后(高地址端),若有几个段都指出了MEMORY纵使类型,则汇编程序认为所遇的第1个为MEMORY组合类型,其他段认为是COMMON类型。
  ③类别名
  类别名必须用单引号括起来。类别名是由用户任选字符串组成,以表示该段的类别。在连接时,连接程序将各个程序模块中具有同样类别名的逻辑段集中在一起,形成一个统一的物理段。典型的类别名有"STACK"、"CODE"、"DATA1"、"DATA2"……
  一个典型程序的段结构如下:
  STACK SEGMENT PARA STACK 'STACK';堆栈段,定位类型为节起点,组
                    合为公用堆栈段,类别名为SATCK。
  语句
  …
  语句
  STACK ENDS
  DATA SEGMENT PARA 'DATA';数据段,定位类型为节起点,不与其他段组
                合,类别名为DATA。
  语句
  …
  语句
  DATA ENDS
  CODE SEGMENT PARA MEMORY;代码段,定位类型为节起点,本段地址位于
                高地址端。
  语句
  …
  语句
  CODE ENDS       
  5.设置起始地址伪指令
  ORG伪指令用来指出其后的程序段或数据块存放的起始地址的偏移量。其指令格式为: ORG 表达式
  汇编程序把语句中表达式之值作为起始地址,连续存放程序和数据,直到出现一个新的ORG指令。若省略ORG,则从本段起始地址开始连续存放。
  6.汇编结束伪指令
  标志着整个源程序的结束,它使汇编程序停止汇编操作。其指令格式为:
  END 表达式(标号)
  其中,表达式与源程序中的第一条可执行指令语句的标号相同。它提供了代码段寄存器CS与指令指示器IP的数值,作为程序执行时第一条要执行的指令的地址。
  伪指令END必须是汇编语言源程序中的最后一条语句,而且每一个源程序只能有一条END伪指令。如果出现一第以上的END伪指令,则在第一条伪指令END以后的语句是无效的。
  7.段寄存器设定伪指令
  段寄存器设定伪指令ASSUME,一般出现在代码段中,它用来告诉汇编程序由SEGMENT/ENDS伪指令定义的段和段寄存器的对应关系,即设定已定义段各自属于哪个段寄存器。其指令格式为:
  ASSUME 段寄存器名:段名[,段寄存器名:段名]
  段寄存器名是CS、DS、SS或ES,段名必须是由SEGMENT/ENDS定义过的段名。
  应当注意:使用ASSUME伪指令,仅仅告诉汇编程序,关于段寄存器与定义段之间的对应关系。但它并不意味着汇编后这些段地址已装入了相应的段寄存器中,这些段地址的真正装入,仍需要用程序来送入,且这4个段寄存器的关入略有不同。
  8.过程定义伪指令
  在程序设计中,我们常常把具有一定功能的程序段设计成一个子程序。汇编程序用"过程"(PROCEDURE)来构造子程序。过程定义伪指令格式如下:

  
  一个过程是以PROC伪指令开始,以ENDP伪指令结束。
  其中,过程名不能省略,且过程的开始(PROC)和结束(ENDP)应使用同一过程名。它就是这个子程序的程序名,也是过程调用指令CALL的目标操作数。它类同一个标号的作用,仍有3个属性――段、偏移量和距离类型。过程的距离类型可选择NEAR和FAR。在定义过程时,如没有选择距离类型,则隐含为NEAR。"过程"应在一个逻辑段内。
  过程和段可以相互嵌套,即过程可以完全地包含某个段,而段也可以完全地包含某个过程,但它们不能交叉覆盖,即过程可以完全地某个段,而段也可以完全地包含某个过程,但它们不能交叉覆盖,例如,以下的序列是合法的:
  每一个过程一定含有返回指令RET,它可以在过程中的任何位置,不一定放在一个过程的最后。如果一个过程有多个出口,它可能有多个返回指令;但是,一个过程执行的最后一第指令必定是返回指令RET。
  9.程序开始伪指令
  在程序的开始可以用NAME或TITLE伪指令,用来为程序取名。
  (1)程序开始语句格式:NAME程序名
  程序名是由用户任意选定的,如果源程序中缺少该语句,将用源文件名作为程序名。
  (2)标题语句格式:TITLE文本
  该伪指令用于给程序指定一个标题,以便在列表文件中每一页的第一行都会显示这个标题。它的文本可以是用户任意选用的名字或字符串,但是字符个数不得超过60个。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值