微机原理与接口与接口技术第四章汇编程序设计

4.1 汇编语言的格式

4.1.1 8086汇编语言程序的一个例子

  • 8086汇编的一个语句行是由4个部分组成的,即:
    标号 操作码 操作数 ;注释(或名字)

4.1.2 8086汇编语言源程序的格式

  • 源程序的一般格式位:
NAME1    SEGMENT
   语句
      语句
NAME1 ENDS
NAME2 SEGMENT
  语句
    语句
 NAME2 ENDS
     END<标号>

语句行的构成

4.2.1 标记(Token)

1.IBM宏汇编的字符集

(1)字母

  • 包含大写的英文字母
  • 小写的英文字母
    (2)数字
  • 阿拉伯数字
    (3)特殊字符
  • IBM中宏汇编字符集中可打印字符


2.界符
  • IBM宏汇编字符集中可打印字符


3.常量

(1)数字(整数)常量
①二进制常量

  • 字母B结尾
    ②十进制常量
  • 字母D结尾
    ③八进制常量
  • 以字母Q结尾
    ④十六进制
  • 以字母H结尾

(2)字符串常量

  • 字符串常量是由包含在单引号内的1或2个ASCII码构成的
4.标识符
  • 标识符是由程序员自由建立起来的、有特定意义的字符序列,如例子中的SUM、CYCLE、PORT_VAL等
  • 一个标识符是由最多31个字母、数字及规定的特殊字符(?@_$)等组成的,且不能用数字打头(以免与十六进制数向混淆)
5.保留字
  • 保留字看上去像标识符,但是它们在语言中有特殊的意义,而且不能用它们作为标识符
IBM宏汇编中的保留字


6.注释
  • 为了使汇编语言的源程序更便于阅读和理解,常在源程序中加上注释
  • 注释是在分号(;)后面的任意的字符序列,知道行的结尾
  • 在汇编时,汇编程序对它们并不进行处理
  • 可打印的文件中,注释和源程序一起打印

4.2.2 符号(Symbol)

1. 寄存器
2.变量
  • 所有变量都有三种属性:
    (1)段值(SEGMENT),即变量单元所在段的段地址(段的起始地址)的高16位,低4位始终为0
    (2)偏移量(OFFSET),即变量单元地址与段的起始地址之间的偏移量(16位)
    (3)类型(TYPE),变量有三种类型:字节(Byte)、字(word)和双字(Double Word)
3.标号(Label)
  • 标号是某条指令所存放单元的符号地址,它是转移(条件转移或无条件转移)指令或调用(CALL)指令的目标操作数
  • 标号的类型与变量不同,它的类型是NEAR或是FAR
4.数
  • 汇编源程序中的常数也常以符号的形式出现
5.其他符号

4.2.3 表达式(Expressions)

1.操作数(Operands)
  • 一个操作数或者一个寄存器名,或是一个常量(数字常量或字符串常量),或是一个存储器操作数

(1)常量操作数

  • 具有数字值的操作数是常量或是表示常量的标识符(符号)
  • 例中的常量操作数是100、PORT_VAL
  • 常量操作数的值允许范围是从-65535 ~ +65535

(2)存储器操作数

  • 存储器操作数,通常是标识符
  • 具体地说,可以分为标号(Label)和变量(Variable)两种
变量可以具有以下几种寻址方式:

①直接寻址
②基址寻址
③变址(索引)寻址
④基址变址寻址

2.运算符(Operators)

(1)算术运算符(Arithmetic Operators)

  • 一个是加(+)减、乘、除运算发
  • 另一个算术运算符是MOD

因此对例子中地存储其地址作如下运算:
SUM+2
CYCLE-5
NOT_DONE-GO
是有效地表达式。而
SUM-CYCLE

(2)逻辑运算符

  • 逻辑运算符是按位操作地AND、OR、XOR和NOT
    (3)关系运算符
  • 在IBM宏汇编中有以下关系运算符
    ①相等Equal(EQ)
    ②不等Not Equal(NE)
    ③小于Less Than(LT)
    ④大于Greater Than(GT)
    ⑤小于或等于Less Than or Equal(LE)
    ⑥大于或等于Greater Than or Equal(GE)

MOV BX ,PORT_VAL LT 5
若PORT_VAL地值小于5,关系为真,则会变程序在汇编后产生地语句为:
MOV BX ,OFFFFH
若PORT_VAL的值不小于5,则关系为假,汇编后产生的语句为:
MOV BX,0

(4)分析运算符

  • 把存储器操作数分解为它的组成部分,如它的段值、段内偏移量和类型
    (5)合成运算符
  • 由已存在的存储器操作数生成一个段值和偏移量相同而类型不同的新的存储器操作数

4.2.4 语句(Statements)

  • 一个汇编语言的源程序是由一条条语句组成的,语句就是对需要计算机完成的动作的说明

  • 源程序中的语句可分为两类:指令语句和指示性语句

  • 指令语句,汇编程序把它们翻译成机器代码,这些代码命令8086执行某些操作。如MOV、ADD、JMP等

  • 对于指示性语句(伪指令),汇编程序并不把它们翻译成机器代码,实际上也不可能翻译成机器代码,只是用来指示、引导汇编程序在汇编时做一些操作,如定义符号、分配存储单元、初始化存储器等,所以伪指令本身不占用存储单元

  • 例如:
    MY_PLACE DB ?
    指令语句的格式:
    标号:助记符 参数,...,参数 ;注释
    指示性语句的格式为:
    名字 命令 参数,...,参数 ;注释

4.3 指示性语句

4.3.1 符号定义语句

1.等值语句EQU

NAME EQU EXPRESSION

  • EQU语句给符号定义一个值,或定义为别的符号名,甚至可定义为一条可执行的指令等
  • 一些例子如下:


2.等号(Equal Sign) =语句
  • 能对符号进行再定义
    EMP = 6
    EMP = 7
    EMP = EMP + 1
3.解除语句PURGE

PURGE 符号1,符号2,...,符号n

  • 已经用EQU命令定义的符号,若以后不再用了,就可以用PURGE语句接触
    例如:


4.3.2 数据定义语句

  • 数据定义语句,为一个数据项分配存储单元,用一个符号名与这个存储单元相联系,且为这个数据提供一个人选的初始值

  • 与该项相联系的符号名称为变量

  • 例子:


  • 例如:THING DB 25
    不仅使THING这个符号与一个字节的存储单元相联系,而且在汇编时会把25放入THING相联系的存储单元中
    所以THING是一个字节变量,它的初始值为25

  • BIGGER_THING DW 4142H
    在汇编时就会把41H与42H分别放至与BIGGER_THING相联系的两个连续的字节单元中(一个字中),而且42H放在地址低的字节,41H放在地址高的字节
    所以,若BIGGER_THING是一个字变量,则它的初始值为4142H

  • 语句:BIGGEST_THING DD 12345678H
    它定义了一个双字变量,且给了初始值


  • 一个存储单元的类型如下:
    (1)数据字节
    SUM DB ? ;定义一个字节
    (2)数据字(两个连续的字节)
    BIGGER DW ?; 定义一个字

(3)数据双字(四个连续的字节)
BIGGER DD ? ;定义一个双字
(4)Near指令单元
CYCLE : CMP SUM,100
(5)Far指令单元

  • 若在一个程序中,对它的数据段有如下定义:



    其中的每一个存储单元都有一些属性(或组成成分)
    分析运算符SEG,返回的是一个存储单元的段地址(即它所在段的起始地址)OFFSET运算符返回的是每一个存储单元地址的段内偏移量,即它与段地址之间的偏差。故:
    SEG BUFFER1
    SEG BUFFER2
    SEG BUFFER3
    都是相同的,它们返回的地址都是DATA_TABLES的地址
    所以,若要对数据段寄存器初始化,则可采用指令:
    MOV AX,SEG BUFFER1
    MOV DS,AX

    OFFSET BUFFER1
    OFFSET BUFFER2
    OFFSET BUFFER3
    是各不相同的,若要向这些缓冲区填入新的数据,可以采用一些地址指针,则可以用以下指令来初始化地址指针:
    MOV BX ,OFFSET BUFFER1
    MOV SI,OFFSET BUFFER2
    MOV DI,OFFSET BUFFER3
    以后,就可以用这些指针来间接寻址这些缓冲区

存储器地址操作数的类型值

4.3.3 段定义语句

  • 段定义的主要命令有①SEGMENT,②ENDS,③ASSUME,④ORG

  • SEGMENT和ENDS语句把汇编语言源程序分成段

  • 这些段就相应于存储器段,在这些存储器段中,存放相应段的目标码

  • 如何使用SEGMENT、ENDS和ASSUME命令,以定义代码段、堆栈段、数据段和附加段



    image.png




    (1)不要搭接,段中的第一个可用字节是在16字节界限上
    MY_SEG SEGMENT
    .
    .
    .
    MY_SEG ENDS
    这是一种正常情况
    (2)允许搭接,但第一个可用字节必须在字的界限上
    MY_SEG SEGMENT WORD
    .
    .
    .
    MY_SEG ENDS
    (3)段开始在指定的16个字节界值上,但第一个可用字节在指定的偏移位置上
    MY_SEG SEGMENT AT 1A2BH ; 段地址为1A2BH
    ORG 0003H ;段内从偏移量0003H开始
    MY_SEG ENDS

伪指令ORG的一般格式为:
ORG <表达式>

此语句指定了段内在它以后的程序或数据块存放的起始地址,也即以语句中的表达式的值作为起始地址,连续存放,除非遇到一个新的ORG语句

4.3.4 过程定义语句

过程定义语句的格式:
PROCEDURE_NAME PROC [NEAR]

PROCEDURE_NAME PROC FAR
RET
PROCEDURE _NAME ENDP

  • 例子



4.3.5 结束语句

START:
END START

4.4 指令语句

4.4.1 指令助记符

1.NOP(No Operation)
  • 使汇编产生一字节指令,使寄存器AX的内容自行交换
2.保留空格(Place Holder)
  • NIL是使汇编程序不产生任何指令的唯一的指令助记符

4.4.2 指令前缀

  • IBM宏汇编中允许作为前缀的助记符:
    LOCK
    REP(Repeat)
    REPE (当相等时重复)
    REPNE (当不相等时重复)
    REPZ (当标志ZF=1时重复)
    PEPNZ (当标志ZF=0时重复)

具有前缀的指令语句例子
CYCLE: LOCK DEC COUNT

4.4.3 操作数寻址方式

1.立即

MOV AX,15 ;15是一个立即数

2.寄存器

MOV AX,15 ;15是一个寄存器操作数

3.直接

SUM DB ?
MOV SUM,15 ;SUM是一个直接存储操作数

4.通过基址寄存器间接

MOV AX,[BX]
MOV AX,[BP]

5.通过变址寄存器间接

MOV AX,[SI]
MOV AX,[DI]

6.通过基址寄存器加变址寄存器间接

MOV AX,[BX][SI]
MOV AX,[BX][DI]
MOV AX,[BP][SI]
MOV AX,[BP][DI]

7.通过基址或变址寄存器加位移量间接

MANY_BYTES DB 100 DUP (?)
.
.
.
MOV AX,MANY_BYTES[BX]
MOV AX,MANY_BYTES[BP]
MOV AX,MANY_BYTES[SI]
MOV AX,MANY_BYTES[DI]

8.通过基址寄存器加变址寄存器加位移量间接存储器

MANY_BYTES DB 100 DUP (?)
.
.
.
MOV AX,MANY_BYTES[BX][SI]
MOV AX,MANY_BYTES[BX][DI]
MOV AX,MANY_BYTES[BP][SI]
MOV AX,MANY_BYTES[BP][DI]

4.4.4 串操作指令

ALPHA DB ?
BETA DB ?
MOV SI,OFFSET ALPHA
MOV DI,OFFSET BETA
MOV BETA,ALPHA

  • 一个完整的汇编语言源程序应该由可执行命令组成的指令性语句和由对符号定义、分配存储单元、分段等组成的指示性语句构成的。而且,一个完整的程序至少应该包含三种段:由源程序组成的代码段。堆栈操作所需要的堆栈段和存放数据的数据段

该例子是把两个分别由未组合的BCD码(一个字节为一位BCD数)的串相加;由于8086中允许两个未组合的十进制数相加,只要经过适当的调整就可以得到正确的结果。所以,在程序中把第一个串的一位BCD数取至AL中,与第二个串的相应位相加,经过AAA调整,再把结果存至存储器中。程序中的前面部分是为了设置段,先设置数据段,用DB伪指令定义两个数据串,用COUNT表示数据的长度。接着是定义堆栈段,为堆栈留下了100个单元的空间(实际上当然由需要来定),然后是当以代码段,从标号GO开始就是可执行指令部分。







4.5 汇编语言程序设计及举例

4.5.1 算术运算程序设计(直线运行程序)

  • 例 两个32位无符号数乘法程序

4.5.2 分支程序设计

4.5.3 循环程序设计

1.用计数器控制循环

例题:在一串给定个数的数中寻找最大值(或最小值),放至指定的存储单元。每个数用16位表示

2.多重循环

4.5.4 字符串处理程序

1.确定字符串的长度

例题:从头搜索字符串的结束标志,统计搜索的字符个数

2.加偶校验到ASCII字符
  • 例题:若有一个ASCII字符串,它的起始地址放在单元STRING内,要求从串中取出每一个字符,检查其中包含的“1”的个数,若已为偶数,则它的最高有效位置“0”;否则,最高有数位置“1”,然后送回

4.5.5 码转换程序设计

1.十六进制到ASCII的转换

例4-5 若有一个二进制数码串,要把每一个字节中的二进制转换位两位十六进制数的ASCII,高4位的ASCII放在第hi高的单元。串中的第一个字节为串的长度(小于128)

2.从二进制到ASCII串的转换
  • 例4-6 把在内存变量NUMBER中的16位二进制数,每一位转换为相应的ASCII,存入串变量STRING中

4.5.6 有关I/O的DOS功能调用

1.在CRT上连续输出0 ~ 9

4.5.7 宏汇编与条件汇编

1.宏命令的用途

(1)在汇编语言的源程序中,若有的程序段要多次使用,为了使在源程序中不重复书写这个程序段,可以一条宏指令来代替。由宏汇编程序在汇编时产生所需要的代码

MOV CL,4
SAL AL,CL

若要多次使用,就可以用一条宏指令代替:
SHFT MACRO
MOV CL,4
SAL AL,CL
ENDM

(2)宏定义不但能使源程序书写简洁,而且由于宏指令具有接受参量的能力,所以功能就更灵活

SHFT MACRO X,Y
MOV CL,X
SAL Y,CL
ENDM

(3)形式参量不只可以出现在操作数部分,也可以出现在操作码部分。如:
SHFT MACRO X,Y,Z
MOV CL,X
S&Z Y,CL
ENDM

若有以下调用:
SHFT 4,AL,AL
SHIFT 6,BX,AR
SHIFT 8,SI,HR
在汇编时,分别产生以下指令的目标代码
MOV CL,4
SAL AL,CL
MOV CL,6
SAR CL,6
SAR BX,CL
MOV CL,8
SHR SI,CL

2.IBM宏汇编中主要宏操作伪指令

(1)MACRO

宏定义名 MRRCO <形式参量表>

(2)PURGE
PURGE 宏定义名 [,......]

(3)LOCAL

  • 例题在AL中有一位十六进制数码要转换为ASCII,则可以用以下宏定义:
    CHANGE MACRO
    CMP AL,10
    JL ADD_0
    ADD AL,'A'-'0'-10
    ADD_0 ADD AL,'0'
    ENDM

上面的CHANGE宏定义在下有多次调用的情况,应定义为:
CHANGE MACRO
LOCAL ADD_0
CMP AL,10
JL ADD_0
ADD AL,'A'-'0'-10
ADD_0 ADD AL,'0'
ENDM

(4)REPT
REPT <表达式>
ENDM

  • 这个伪指令可以重复执行在它的指令体部分所包含的语句。重复执行的次数,由表达式的值所决定

例4-7 把数字0 ~ 9的ASCII填入表TABLE。CHAR = ‘0’


例题4-8 建立一个地址表,其中每个字的内容是下一个字的地址(用作地址指针),而最后一个字的内容是第一个字的地址


(5)IRP
IRP 形式参量(参数表)
ENDM


(6)IRPC
IRPC 形式参量,字符串(或<字符串>)
ENDM

3.宏定义嵌套
4.宏指令与子程序的区别

(1)宏指令是为了简化源程序的书写,在汇编时,汇编程序处理宏指令,还把宏定义体插入到宏调用处。所以,宏指令并没有简化目标程序。有多少次宏调用,在目标程序中仍需要有同样多次的目标代码插入。所以,宏指令不能节省目标程序所占的内存单元
(2)若一个源程序中多次调用一个程序段,则可用子程序,也可以用宏指令来简化源程序。用子程序的办法,汇编后产生的目标代码少,也即目标程序占用的内存少,节约了内存空间。但是,子程序在执行时,每调用一次都要先保护断点,通常在程序中还要保护现场;在返回时先要恢复现场,然后恢复断点(返回)
这些操作都额外增加了时间,因而执行时间长,速度慢指令恰好相反,它的目标程序长,占用的内存的那元多;但是执行时不需要保护断点,也不需要保护现场以及恢复、返回等这些额外的操作,因而执行时间短、速度快

5.条件汇编
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容

  • 这学期有了汇编课,但个人感觉这部分难度还是有一些的,所以写了这篇简书当做自己对于知识的复习,同时也是希望能够再次加...
    kl_w阅读 6,642评论 0 7
  • 1.地址总线,数据总线,控制总线在哪里,它们有什么作用?答:它们都是cpu连接外部组件的线路。地址总线:地址总线A...
    MagicalGuy阅读 1,456评论 0 1
  • 计算机通过执行指令序列来使机器得以工作,所以对于每一系列的计算机都有指定的一组指令集供计算机使用,这组指令...
    未来科技工作室阅读 7,994评论 1 10
  • # 常见汇编代码 # 1. 编写程序:比较AX,BX,CX中带符号数的大小,将最大的数放在AX中 code...
    喝豆腐脑加糖阅读 2,610评论 0 0
  • 汇编总结 汇编的发展史 机械语言 由0和1组成的机器指令(如:0101 0001 1101 0110) 汇编语言(...
    iChuck阅读 1,306评论 1 8