【x86汇编】第五章:程序设计其它方法技术

字符串操作

串操作指令简介

主机与外设之间的交互,大多采用字符串的形式,为了方便地实现字符串操作,简化程序设计,80x86提供了字符串操作指令

字符串操作指令共有5条:

  • 传送指令 MOVS
  • 搜索指令 SCAS
  • 比较指令 CMPS
  • 读取指令 LODS
  • 存储指令 STOS

以上指令可使用的重复前缀如下:

  • REP,无条件重复CX寄存器指定的次数
  • REPE/REPZ,在CX≠0 && ZF=1时重复
  • REPNE/REPNZ,在CX≠0 && ZF=0时重复

所有的字符串操作指令,使用相同的寄存器,标志位和符号

  • 源串指示器:DS:SI/ESI
  • 目的串指示器:ES:DI/EDI
  • 重复次数计数器:CX/ECX
  • SCAS指令的搜索值在:AL/AX/EAX中
  • LODS指令的目的地址为:AL/AX/EAX
  • STOS指令的源地址为:AL/AX/EAX
  • 传送方向:
    1. DF = 0 自动增量
    2. DF = 1 自动减量
  • _SB:不带操作数的字节串操作指令
  • _SW:不带操作数的字串操作指令
  • _SD:不带操作数的双字串操作指令

串操作指令

传送指令

MOVS OPD, OPS
MOVSB:字节传送
MOVSW:字传送
MOVSD:双字传送

功能:

  • DS:[SI] / [ESI] --> ES:[DI] / [EDI]
  • 自动修改指针,指向下一个位置

比较指令

CMPS OPD, OPS
CMPSB:字节比较
CMPSW:字比较
CMPSD:双字比较

功能:

  • DS:[SI] / [ESI] – ES:[DI] / [EDI]
  • 根据相减的结果,置标志位,源串与目的串内容不变
  • 自动修改指针,指向下一个位置
  • 后面一般跟转移指令
  • 串比较指令,是源操作数减去目的操作数

搜索指令

SCAS OPD
SCASB:字节搜索
SCASW:字搜索
SCASD:双字搜索

功能:

  • 字节操作:(AL) – (ES:[DI] / [EDI])

  • 字 操 作:(AX) – (ES:[DI] / [EDI])

  • 双字操作:(EAX) – (ES:[DI] / [EDI])

  • 根据相减的结果置标志位,但不保存结果

  • 自动修改指针,指向下一个位置

  • 主要用来在字符串中搜索某个值

从源串中取数指令

LODS OPD
LODSB:字节串中取数
LODSW:字串中取数
LODSD:双字串中取数

功能:

  • 字节操作:(DS:[DI] / [EDI]) -> (AL)

  • 字 操 作:(DS:[DI] / [EDI]) -> (AX)

  • 双字操作:(DS:[DI] / [EDI]) -> (EAX)

  • 将字符串存储区的某个数据,送到累加寄存器中

  • 自动修改指针,指向下一个位置

往目的串中存数指令

STOS OPD
STOSB:往字节串中存数
STOSW:往字串中存数
STOSD:往双字串中存数

功能:

  • 字节操作: (AL) -> (DS:[DI] / [EDI])

  • 字 操 作:(AX) -> (DS:[DI] / [EDI])

  • 双字操作:(EAX) -> (DS:[DI] / [EDI])

  • 将累加寄存器中的值,送到目的串

  • 自动修改指针,指向下一个位置

宏功能程序设计

  • 子程序的调用,需要额外的时间和空间花销
  • 当重复部分较短时,一般设计成宏指令
  • 宏汇编语言提供:宏指令的定义调用、重复汇编、条件汇编
  • 宏指令使用三步骤:宏定义、宏调用、宏拓展

宏定义

宏定义使用伪指令 MACROENDM 实现
定义格式

宏指令名 MACRO 形参
            宏体
            ENDM
  • 宏指令名,类似于函数名
  • 形参可以出现在宏体任何地方,形参以逗号隔开
  • 宏体是要重复的部分,包括一系列机器指令和伪指令
  • ENDM和MACRO成对出现
  • 宏指令一定要放在被调用之前

宏调用

宏指令完成定义后,可以在源程序中调用

调用格式:宏指令名 实际参数

宏拓展

  • 宏汇编程序在汇编期间,先扫描宏定义,将宏名字、形参、宏体填入宏定义表中
  • 遇到宏调用时,实参替换形参

宏定义于宏调用中的参数

带间隔符的实参

有时,实参是一串带间隔符(空格、逗号)的字符串,为了不至于混淆,用尖括号 <> 将它们括起来,尖括号中的内容代表实参

例如用宏指令定义申请堆栈空间:

STACK0 <500 DUP(0)>

数字实参

  • 有时希望用符号做实参,希望传进去的是符号的值,而不是符号本身,可以符号的前面加 %
  • 特殊宏操作符%用来将其后的表达式转换为对应的值
  • % 后面的符号,一定是直接用EQU或者=赋值的符号常量,或者汇编时能确定值的表达式,而不能是变量和寄存器名

宏参数的连接

  • 在宏定义中,有些形参需要夹在字符串中,为了将这种形参标识出来,需要在这样的形参前面加符号 &
  • 如果形参后面还跟有字符串,则还应在形参后面加符号 &
  • 宏汇编程序识别后,将符号连成一个完整的字符串

宏体中的变量与标号

  • 宏体中经常需要定义一些变量和标号,如果进行了多次宏拓展,则会出现变量或标号重复定义的错误
  • 为解决这个问题,提供了伪指令LOCAL

LOCAL 形参

功能:

  • 在宏拓展时,宏汇编程序自动为其后的形参顺序生成特殊符号,并用这些特殊符号取代宏体中的形参,从而避免了符号重复定义的错误
  • LOCAL语句只能作为宏体的第一条语句,它后面的形参即为本宏定义中所定义的变量和标号

重复汇编

  • 有时源程序中,会连续重复完全相同,或者几乎完全相同的一组语句
  • 这时采用重复汇编方式比把他们定义成宏指令更能简化程序设计

给定次数

REPT    表达式
           重复块
            ENDM

功能:让宏汇编程序将重复块连续地汇编“表达式”所指定的次数

不定次数

次数由实参的个数确定,根据实参形式的不同,选择IRP和IRPC

IRP 形参, <实参1,实参2...,实参n>
    重复块
    ENDM
  • 让宏汇编程序将重复块重复汇编由实参个数所确定的次数,并在每次重复时,依次用相应位置的实参代替形参
  • 实参必须用尖括号括起来,并且各实参之间用逗号隔开
IRPC 形参,字符串
    重复块
    ENDM
  • 将重复块重复汇编,重复的次数由字符串中的个数决定,并在每次重复时,依次用相应位置的字符代替形参
  • 字符串不带引号

条件汇编

  • 条件汇编是指,允许宏汇编程序根据条件,决定某一段程序是否参加汇编
  • 使用条件汇编伪指令时,条件表达式各项的值必须在第一遍扫描中求得,否则表达式不正确

使用格式:

IF ... 条件表达式
        条件汇编块1
ELSE
        条件汇编块2
ENDIF
正条件 反条件 表达式的形式 检测条件
IF IFE 数值表达式 表达式值不为0(为0)为真
IF1 IF2 第一次/第二次扫描
IFDEF IFNDEF 符号 符号已被(未被)定义或被(未被)说明为外部符号为真
IFB IFNB <参数> 该参数对应的实参存在(不存在)为真
IFIDN IFDIF <参数1>, <参数2> 字符串参数1与字符串参数2相等(不相等)为真

宏库的使用

宏库的建立

  • 对于经常使用的宏定义,用户可以将他们集中在一起,建成宏库供用户随时调用
  • 宏库为文本文件,文件名任意指定
  • 利用TYPE命令可以查看文本的内容

宏库的使用

  • 程序中需要调用宏库时,首先将宏库加入到自己的源文件中,然后按照宏库中各宏定义的规定调用即可
  • 伪指令 INCLUDE 用于将宏库加入源文件一起进行汇编

INCLUDE 文本文件名

功能:将文件内容加入汇编,全部汇编完后,再汇编后面的内容

条件汇编与宏定义的使用

  • 条件汇编伪指令常与宏定义一起使用
  • 可以使用条件汇编,使宏库只在第一遍扫描时添加,这样加快第二次扫描,避免列出长长的汇编列表清单
  • 对于宏库中用不上的宏指令,可以使用伪指令PURGE取消
IF1
    INCLUDE MACRO.LIB
ENDIF
    PURGE WRITE

宏指令与子程序的比较

  • 处理的时间不同:宏指令是在汇编期间,由宏汇编程序处理的;而子程序调用是在目标程序执行期间,由CPU直接执行的
  • 处理的方式不同:宏指令必须先定义后使用,宏调用用宏体置换宏指令名,实参置换形参,而子程序的调用不发生这种代码和参数的置换,而是CPU将控制方向由主程序转向子程序
  • 目标程序的长度不同:由于每次宏调用都要进行宏拓展,因而使用宏指令不会缩短目标程序,而子程序通过CALL指令调用,无论执行多少次,目标代码只出现一次,因此,目标程序短,占用空间小
  • 执行速度不同:执行子程序需要使用堆栈保护和恢复现场,因而执行速度慢,而宏指令不存在这些问题
  • 参数传递方式不同:宏调用可实现参数的代换,参数形式不受限制,而子程序参数一般是地址或者操作数

模块化程序设计

  • 在汇编语言中,一个以 END 语句为结束标志的源程序,称为一个代码块
  • 它经过汇编源程序汇编后,生成一个目标文件,也称为目标模块
  • 连接程序将多个目标模块连接在一起时,需要两个信息,一是模块间通信方式,二是段之间的组合方式
  • 通信方式是指:一个模块可访问另外模块中所定义的标号、变量、符号常量的方式
  • 组合方式是指:多个模块以什么方式组合在一起

组合方式

定位方式

定位方式是对该段起始地址所提出的要求,即告诉连接程序,在各个段装配在一起时,前一段放完后,后面一个段将从一个什么样的起始边界开始存放

定位方式有4种选择:

  • PARA:节:表示该段要从能被16整除的地址开始存放,即最低4位必须为0
  • WORD:字:表示该段要从偶数地址开始存放,即最低1位必须为0
  • BYTE:字节:表示对该段存放的首地址不作要求,任何地址处都可以开始存放
  • PAGE:页:该段要从能被256整除的地址开始存放,即最低8位必须为0

其中PARA为默认方式,不指定时为此方式

组合方式

组合方式的作用是向连接程序提供本段同其他段的组合关系,可以选择以下几种关系

  • 不选择:表示本段与其他段逻辑上不发生关联
  • PUBLIC:表示应将本段与其他模块中的同名、同 ‘类别’ 段按模块连接的顺序相邻的连接在一起,组成一个物理段,该段大小不能超过64KB
  • STACK:与PUBLIC功能相同,但该方式仅对堆栈段
  • COMMON:表示本段和同名、同 ‘类别’ 的其他段应该具有相同的段首址,即将本段与这些段相覆盖,覆盖长度取决于最长的COMMON段
  • AT表达式:表示将本段装在根据表达式计算出的段地址上,但AT方式不能包含代码和初始化数据,不能用于用户代码段,仅用于访问系统数据,表示已在内存中的数据和数据地址
  • MEMORY:表示将本段定位在所有连接在一起的段之上(最高地址上),如果几个段都选择MEMORY组合方式而又同时连接在一起,那么只有宏汇编程序遇到的第一段处理为MEMORY,其它作为COMMON段

类别

  • 段的 ‘类别’ 是用单括号括起来的字符串来表示的
  • 连接时,‘类别’ 相同的所有段,按先后顺序存放在连续的存储区,且每段都有自己的起始地址

通信方式

公共符号与外部符号

  • 公共符号:不仅可被定义自己的模块访问,还可以供其它模块访问的符号,用PUBLIC说明
  • 外部符号:在该模块内部访问,而不在该模块内定义的符号,用EXTERN说明

PUBLIC 符号

  • 用来说明其后的符号是公共符号,可以被其它模块所引用
  • 这些符号必须是在本模块中定义的符号常量、标号、变量,各名字之间用逗号隔开,一个模块中的同一个名字仅可被PUBLIC说明一次
  • 一般放在程序的开头

EXTERN 符号:类型

  • 用来说明本模块中需要引用的、由其他模块所定义的符号
  • 这些符号必须在所定义的模块中声明为PUBLIC
  • 类型为:ABS(符号常量)、BYTE、WORD、DWORD、NEAR、FAR

连接程序的功能

连接程序可以将若干个目标模块连接在一起,连接程序主要有以下功能:

  • 将指定的若干个目标模块和子程序库中的子程序模块连接在一起,解决各模块中段的组合、定位问题,确定目标模块中浮动地址及公共符号的引用问题,生成一个可再定位的装入模块,即能够执行的文件(.EXE)
  • 产生一个地址分配文件(.MAP)

源程序综合举例

模块程序设计中的注意事项

模块划分

  • 如果一个程序段被很多模块公用,则他应该该是一个独立的模块
  • 如果若干程序段处理的数据是公用的,则这些程序段应该放在一个模块
  • 若两个程序段的利用率差别很大,则应该分属于两个模块
  • 一个模块不能太大,也不能太小,过大则通用性差,过小则时间和空间浪费
  • 力求使模块具有通用性,通用性越强模块的利用率越高
  • 各模块在功能、逻辑上相互独立,避免使用转移语句在模块间转来转去
  • 各模块之间接口简单,尽量减少公共符号的个数,尽量不公用数据存储单元,在结构或编排上有联系的数据应该放在一个模块中,以免相互影响
  • 每个模块的结构应该尽量设计成单入口、单出口的形式

程序文件命名

  • 标识出程序设计者
  • 标识出模块功能
  • 标识出模块之间的连接关系

标号的定义

  • 模块出处
  • 功能名称
  • 分支代号

变量和缓冲区的定义

  • 缓冲器或变量标志:用B为缓冲器名开头,用V为变量名开头,用S为字符串开头
  • 第二个字母可表示定义的类型

模块注释

为方便子模块的调用,在子模块前面应该有详细的说明,包括:

  • 子模块的功能
  • 入口参数
  • 出口参数
  • 所用到的主要变量

猜你喜欢

转载自blog.csdn.net/whitefish520/article/details/105612187