汇编语言 学习笔记 (三)

本贴最后更新于 2569 天前,其中的信息可能已经时过境迁

汇编语言学习笔记

四、汇编语言程序格式

###语句基本格式
汇编语言程序中的语句由 4 项组成,格式如下:

[name] operation operand [;comment]

**名字(name)**项是一个符号。
**操作项(operation)**是一个操作的助记符,它可以是指令、伪操作或宏指令名。
**操作数(operand)**项由一个或多个表达式组成,它提供为执行所要求的操作而需要的信息。
**注释(comment)**项用来说明程序或语句的功能。“;”为识别注释项的开始。“;”也可以从一行的第一个字符开始, 此时整行都是注释,常用来说明下面一段程序的功能。

名字项

名字项可以是:标号或变量
源程序中用下列字符来表示名字:
字母 AZ 数字 09 专用字符 ? . @ _ $
除数字外,所有字符都可以放在源语句的第一个位置
名字中如果用到 . ,则必须是第一个字符
可以用很多字符来说明名字,但只有前面的 31 个字符能被汇编程序所识别

标号

标号在代码段中定义,后面跟着冒号:,它可以作为过程名定义。
标号有 3 种属性:段、偏移及类型
属性定义标号的段起始地址,此值必须在一个段寄存器中,而标号的段则总是在 CS 寄存器中。
偏移属性,标号的偏移地址是从段起始地址到定义标号的位置之间的字节数。
类型属性,用来指出该标号是在本段内引用还是在其他段中引用的。如是在段内引用的,则称为 NEAR,否则为 FAR。

变量

变量在数据段或附加数据段中定义,后面不跟冒号。变量经常在操作数字段出现。它也有段、偏移及类型三种属性。
属性:定义变量的段起始地址,此值必须在一个段寄存器中。
偏移属性:变量的偏移地址是从段的起始地址到定义变量的位置之间的字节数。在当前段内给出变量的偏移值等于当前地址计数器的值。
类型属性:变量的类型属性定义该变量所保留的字节数。如 BYTE(1 个字节长)、WORD(2 个字节长)、DWORD(4 个字节长) 。

注释项

注释项用来说明一段程序、一条或几条指令的功能,它是可有可无的。
但是,对于汇编语言程序来说,注释项的作用是很明显的,它可以使程序容易被读懂,因此汇编语言程序必须写好注释。
注释应该写出本条( 或本段 )指令在程序中的功能和作用,而不应该只写指令的动作。

数据定义及存储器分配伪操作

伪操作的格式是:

[Variable] Mnemonic  Operand , … ,Operand [;Comments] 

**操作数(Operand)**可以是常数,或者是表达式 。
**助记符(Mnemonic)**字段说明所用伪操作的助记符,即伪操作,说明所定义的数据类型。
**变量(Variable)**字段是可选的,它用符号地址表示,其作用与指令语句前的标号相同,但它的后面不跟冒号。如果语句中有变量,则表示第一个字节的偏移地址。
**注释(Comments)**字段用来说明该伪操作的功能,它也是可选的。

Mnemonic(助记符)

DB 伪操作用来定义字节,其后的每个操作数都占有一个字节。
DW 伪操作用来定义字,其后的每个操作数占有一个字(16 位,其低位字节在第一个字节地址中,高位字节在第二个字节地址中)。
DD 伪操作用来定义双字,其后的每个操作数占有两个字(32 位)。

例如
image.png

a. 操作数可以是常数 , 或是表达式
b. 操作数 ? 可以保留存储空间,但不存入数据
c. 操作数还可以使用复制操作符来复制某个(或某些)操作数。其格式为:

repeat-count DUP(operand, … ,operand)

其中 repeat-count 可以是一个表达式,它的值应该是一个正整数,用来指定括号中的操作数的重复次数
d. 可以用 DW 或 DD 伪操作存地址。 DW 把变量或标号的偏移地址存入存储器;DD 把由 16 位段地址和 16 位偏移地址组成的整个地址存入存储器。
e. 用 DD 伪操作存入地址时,第 1 个字为偏移地址,第 2 个字为段地址。
image.png
image.png

###伪操作
####定义属性伪操作 LABEL
LABEL 伪操作来定义属性
其格式为

name  LABEL  type

对于数据项可表示为:

variable-name  LABEL  type

其中类型可以是 BYTE,WORD,DWORD。
对于可执行的代码可表示为:

label-name  LABEL  type

其中类型可以是 NEAR 或 FAR。对于 16 位段,NEAR 为 2 字节,FAR 为 4 字节可。

表达式赋值伪操作 EQU

有时程序中多次出现同一个表达式,可以用赋值伪操作给表达式赋予一个名字。其格式如下:Expression_name EQU Expression
此后,表达式名可以代替该表达式。EQU 的引入提高了程序的可读性,也使其更加易于修改。
表达式可以是任何有效的操作数格式,任何可求出常数值的表达式,任何有效的助记符。

a. 在 EQU 语句的表达式中,如果有变量或标号的表达式,则在该语句前应该先给出它们的定义
b. 与 EQU 相类似的 =伪操作也可以作为赋值伪操作使用。区别是 EQU 伪操作中的表达式名是不允许重复定义的,而 = 伪操作则允许重复定义
image.png

地址计数器与对准伪操作

1. 地址计数器 $

在汇编程序对源程序汇编时,用地址计数器来保存当前正在汇编的指令的偏移地址。
当开始汇编或在每一段开始时,把地址计数器初始化为零,以后在汇编过程中,每处理一条指令,地址计数器就增加一个值,此值为该指令所需要的字节数。
地址计数器的值可用$来表示,汇编语言允许用户直接用$来引用地址计数器的值。

【例】JNE $+6
表示的转向地址是 JNE 指令的首地址加上 6。

当$用在指令中时,它表示本条指令的第一个字节的地址。在这里,$+6 必须是另一条指令的首地址。否则,汇编程序将指示出错信息。
当\$ 用在伪操作的参数字段时(例如 DB 的参数),则和它用在指令中的情况不同,它所表示的是地址计数器的当前值

2. ORG 伪操作

ORG 伪操作用来设置当前地址计数器的值,其格式为

ORG  constant expression

ORG 伪操作可以使下一个字节的地址成为常数表达式的值 n。

操作数项

操作数项由一个或多个表达式组成,多个操作数项之间一般用逗号分开。
对于指令,操作数项一般给出操作数地址,它们可能有一个或两个,或一个也没有。
对于伪操作或宏指令,则给出它们所要求的参数。
操作数项可以是常数、寄存器、标号、变量或由表达式组成。
表达式是常数、寄存器、标号、变量与一些操作符相组合的序列,可以有数字表达式地址表达式两种。
在汇编期间,汇编程序按照一定的优先规则对表达式进行计算后可得到一个数值或一个地址

1. 算数操作符

算术操作符有 +,-,*,/MOD

符号地址 + -常数有意义,*、/、MOD 时意义不明确

2. 逻辑与移位操作符

逻辑操作符有 AND,OR,XORNOT;移位操作符有 SHLSHR
它们都是按位操作的,只能用于数字表达式中。
逻辑操作符要求汇编程序对其前后两个操作数(或表达式)作指定的逻辑操作。
移位操作符的格式是:

expression SHL(或SHR) numshift

汇编程序将 expression 左移或右移 numshift 位,如移位数大于 15,则结果为 0。

3. 关系操作符

它有 **EQ(相等)、NE(不等)、LT(小于)、GT(大于)、LE(小于或等于)、GE(大于或等于)**6 种。
关系操作符的两个操作数必须都是数字,或是同一段内的两个存储器地址。
计算的结果应为逻辑值,结果为真,表示为 0FFFFH;结果为假,表示为 0。

4. 数值回送操作符

它主要有 TYPE,LENGTH,SIZE,OFFSET,SEG 等。这些操作符把一些特征或存储器地址的一部分作为数值回送。

1. TYPE
TYPE  expression

a. 如该表达式是变量,则汇编程序将回送该变量的以字节数表示的类型:DB 为 1,DW 为 2,DD 为 4。
b. 如果表达式是标号,则汇编程序将回送代表该标号类型的数值: NEAR 为-1,FAR 为-2。
c. 如果表达式为常数,则应回送 0。

2. LENGTH
LENGTH  Variable

对于变量中使用 DUP 的情况,汇编程序将回送分配给该变量的单元数,而对于其他情况则送 1。
image.png

只针对通过 DUP 分配的单元

3. SIZE

SIZE Variable:
汇编程序应回送分配给该变量的字节数。此值是 LENGTH 值和 TYPE 值的乘积。

对于上面 2 例:

MOV CX,SIZE FEES	;	等于MOV CX,200
MOV CX,SIZE ARRAY	;	等于MOV CX,2
4. OFFSET
OFFSET  Variable 或 label

汇编程序将回送变量或标号的偏移地址值

5. SEG
SEG  Variable 或 label

汇编程序将回送变量或标号的段地址值

5. 属性操作符

主要有 PTR段操作符、SHORT、THIS、HIGH、LOW、HIGHWORD 和 LOWWORD

1. PTR
type  PTR  expression

PTR 用来建立一个符号地址,但它本身并不分配存储器,只是用来给已分配的存储地址赋予另一种属性,使该地址具有另一种类型
格式中的类型字段表示所赋予的新的类型属性,而表达式字段则是被取代类型的符号地址。
image.png

2. 段操作符

段操作符:
用来表示一个标量、变量或地址表达式的段属性。可用段前缀指定某段的地址操作数:

MOV AX,ES:[BX+SI]

可见它是用段寄存器:地址表达式来表示的。此外,也可以用段名:地址表达式或段组名:地址表达式来表示其段属性。

3. SHORT

SHORT 用来修饰 JMP 指令中转向地址的属性,指出转向地址是在下一条指令地址的-128-+127 个字节范围之内。

4. THIS
THIS attribute 或 type

它可以像 PTR 一样建立一个指定类型(BYTE、WORD、DWORD)的或指定距离(NEAR 或 FAR)的地址操作数。
该操作数的段地址和偏移地址与下一个存储单元地址相同
image.png

#####5. HIGH 和 LOW / HIGHWORD 和 LOWWORD

  • HIGH 和 LOW:
    称为字节分离操作符,它接收一个数或地址表达式,HIGH 取其高位字节,LOW 取其低位字节。

  • HIGHWORD 和 LOWWORD:
    称为字分离操作符,它接收一个数或地址表达式,HIGHWORD 取其高位字,LOWWORD 取其低位字。这两个操作符是 MASM6 版支持的。

操作符的优先级别

操作符的优先级别 从高到低排列如下:
(1) 在圆括号中的项,方括号中的项,结构变量(变量,字段),然后是 LENGTH、SIZE 等
(2) 名:(段取代)
(3) PTR,OFFSET,SEG,TYPE ,THIS 及段操作符
(4) HIGH 和 LOW
(5) 乘法和除法:*,/,MOD,SHL,SHR
(6) 加法和减法:+,-
(7) 关系操作:EQ,NE,LT,LE,GT,GE
(8) 逻辑:NOT
(9) 逻辑:AND
(10) 逻辑:OR,XOR
(11) SHORT

汇编源程序结构

段定义伪操作

SEGMENT/ENDS

格式为

segname SEGMENT [align-type] [combine-type] [use-type] ['class']
...
segname ENDS

定位类型 (align-type)
定位类型说明段起始地址边界值的情况 , 可以是:
PARA 指定段的起始地址必须从小段边界开始,即段起始地址的最低的 16 进制数位必须为 0。这样,偏移地址可以从 0 开始,为默认项。
BYTE 该段可以从任何地址开始。这样,起始偏移地址可能不是 0。
WORD 该段必须从字的边界开始,即段起始地址必须为偶数。
DWORD 该段必须从双字的边界开始,即段起始地址的最低十六进制数位必须为 4 的倍数。
PAGE 该段必须从页的边界开始,即段起始地址的最低 8 位必须为 0(该地址能被 256 整除)。

组合类型(combine-type)
组合类型说明程序连接时的段合并方法,可以是:
PRIVATE 该段为私有段,在连接时不与其他模块中的同名段合并,默认值。
PUBLIC 该段连接时可以把不同模块中的同名段相连接而形成一个段,其连接次序由连接命令指定。每一分段都从小段的边界开始,因此各模块的原有段之间可能存在小于 16 个字节的间隙。
COMMON 该段在连接时可以把不同模块中的同名段重叠而形成一个段,由于各同名分段有相同的起始地址,所以会产生覆盖。COMMON 的连接长度是各分段中的最大长度。重叠部分的内容取决于排列在最后一段的内容。
AT expression 使段地址是表达式所计算出来的 16 位值。
MEMORY 与 PUBLIC 同义。
STACK 把不同模块中的同名段组合而形成一个堆栈段,长度为各原有段的总和,各原有段之间并无 PUBLIC 所连接段中的间隙,而且栈顶可自动指向连接后形成的大堆栈段的栈顶。

使用类型(use-type).
使用类型只适用于 386 及其后继机型,它用来说明使用 16 位寻址方式还是 32 位寻址方式
USE16 使用 16 位寻址方式。
USE32 使用 32 位寻址方式。
当使用 16 位寻址方式时,段长不超过 64KB,地址的形式是 16 位段地址和 16 位偏移地址;当使用 32 位寻址方式时,段长可达 4GB, 地址的形式是 16 位段地址和 32 位偏移地址。在实模式下, 使用 USE16。使用类型的默认项是 USE16

类别(‘class’)
类别在引号中给出连接时组成段组的类型名。
类别说明并不能把相同类别的段合并起来,但在连接后形成的装入模块中,可以把它们的位置靠在一起。

ASSUME

ASSUME 伪操作来实现段和段寄存器的关系

例如:

data   segment         ;	定义数据段
       …
data   ends
extra  segment         ;	定义附加段
       …
extra  ends
code   segment         ;	定义代码段
       assume cs:code, ds:data, es:extra
start: mov   ax, data
       mov   ds, ax    ; 段地址 → 段寄存
	   mov   ax, extra
       mov   es, ax    ; 段地址 → 段寄存器
       …
code   ends
       end   start

存储模型与简化段定义伪操作

汇编程序(MASM5.0 与 6.0)除支持前面讨论的完整的段定义伪操作 segment 外,还提供了一种新的较简单的段定义方法。
这种方法不能像 segment 伪操作那样具有较完整的表达能力,但它确实比较简单易用。

MODEL 伪操作

MODEL 伪操作的格式如下

.MODEL memory_model [,model_options]

.MODEL 存储模型 [,语言类型] [,操作系统类型] [,堆栈选项]

memory_model 用来表示存储模型,即用来说明在存储器中是如何安放各个段的,存储模型共有七种。
七种存储模型:
Tiny:所有数据和代码在一个段,都是近访问。
Small:所有数据放在一个 64KB 数据段,所有代码放在另一个 64KB 的代码段,都是近访问。
Medium:代码使用多个段,而数据则合并成一个 64KB 段,数据是近访问,代码则可远访问。
Compact:所有代码都放在一个 64KB 的代码段内,数据则可放在多个段内,代码是近访问,数据则可远访问。
Large:代码和数据都可多个段,都可远访问。
Huge:与 Large 相同,但允许数据段超过 64KB。
Flat:允许使用 32 位偏移量,DOS 下不允许使用,在 OS2 或其他保护模式操作系统下使用。

model options 允许用户指定的三种选项,即语言类型、操作系统类型、堆栈选项。
model options 允许用户指定的三种选项:
语言类型:是指该汇编语言程序作为某一种高级语言程序的过程而为该高级语言程序调用,如 C,BASIC,FORTRAN,PASCAL。
操作系统类型:说明程序运行于哪种操作系统下(OS_DOS 或 OS_OS2),默认是 OS_DOS。
堆栈选项:NEARSTACK 或 FARSTACK。
NEARSTACK 时把堆栈段和数据段组合到一个 DGROUP 段,DS 和 SS 均指向 DGROUP 段,FARSTACK 是指堆栈段和数据段并不合并。
存储模型为 TINY,SMALL,MEDIUM 和 FLAT 时,默认为 NEARSTACK;存储模型为 COMPACT、LARGE 和 HUGE 时,默认项 FARSTACK

与简化段定义有关的预定义符号

汇编程序给出了与简化段定义有关的一组预定义符号,它们可在程序中出现,并由汇编程序识别使用。如在完整的段定义情况下,在程序的一开始,需要用段名装入数据段寄存器。

mov ax,data_seg1
mov ds,ax 

若用简化段定义,则数据段只用.data 来定义,而并未给出段名,此时可用:

mov ax, @data
mov ds, ax 

这里预定义符号**@data**就给出了数据段的段名

程序开始和结束伪操作

END

表示源程序结束的伪操作 END,其格式为

END [label]

其中 label 指示程序开始执行的起始地址。如果多个程序模块相连接,则只有主程序要使用标号,其他子程序模块则只用 END 而不必指定标号。

.STARTUP

.STARTUP 用来定义程序的初始入口点,并且产生设置 DS,SS 和 SP 的代码。如果程序中使用了.STARTUP,则结束程序的 END 伪操作中不必再指定程序的入口点标号。

.EXIT

.EXIT 用来产生退出程序并返回操作系统的代码,格式为:
.EXIT [return-value]
其中 return-value 为返回给操作系统的值。常用 0 作为返回值。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3453 回帖 • 203 关注
  • 笔记

    好记性不如烂笔头。

    308 引用 • 793 回帖 • 1 关注
  • 汇编
    9 引用 • 1 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...