前面我们介绍了8086汇编中一些常用的、基本的、重要的概念,现在我们就要把这些东西组装起来。
定义变量
|
|
其中的 var_name
就是一个变量,db
/dw
/dd
是伪指令助记符,用于指定字节/字/双字,表达式可以为一个常量,一个字符串等。
操作数'?'
用于保留储存空间,但不存入数据。
操作数字段还可以利用复制操作符 dup
来复制重复元素。
程序的开始与结束
1. end
伪指令
|
|
end
伪指令标识着整个程序的结束,end
后面的操作数指定程序执行的起始地址。所以,一般主程序模板必须 end
后面指定操作数,然后在操作数放到代码段的开头,如:
2. assume
伪指令
8086存储器是分段的,分了段之后,就必须指明段和段寄存器之间的关系,这由假设语句 assume
实现。
其中,segment_reg
必须是 cs
, ds
, ss
, es
中的一个,segment_name
则是定义的段名。
注意:assume
伪指令只是指定了某个段分配给某个段寄存器,但它并没有将段地址装入段寄存器,所以在代码段中,还要将段地址装入段寄存器。
3. 定义段
|
|
其中,[]
代表是可选的,可以缺省的,但各项顺序不能错,一般不需要我们指定。
4. 定义过程
|
|
在 proc
后面可以指定 near
(默认)—— 在段内被调用,far
—— 可以被段外调用。
在 masm
中,过程含义跟子程序一样,可以通过 call
来调用,过程返回自动调用 ret
。
子程序
子程序跟过程段类似,通过 call
调用,ret
来返回,重点要注意现场保护,参数传递等问题。
简化段
简化段首先要定义程序的存储模型:
存储模型 | 说明 | 适用系统 |
---|---|---|
tiny(微型) | 所有数据和代码都放在一个段内,其访问都为NEAR型,整个程序≤64K,并会产生.COM文件 | MS-DOS |
small(小型) | 所有代码在一个64KB的段内,所有数据在另一个64KB的段内(包括数据段,堆栈段和附加段) | MS-DOS Windows |
medium(中型) | 所有代码>64K时可放在多个代码段中,转移或调用可为FAR型。所有数据限在一个段内,DS可保持不变 | MS-DOS Windows |
compact(紧凑型) | 所有代码限在一个段内,转移或调用可为NEAR型。数据>64K时,可放在多个段中 | MS-DOS Windows |
large(大型) | 允许代码段和数据段都可超过64K,被放置在有多个段内,所以数据和代码都是远访问 | MS-DOS Windows |
huge(巨型) | 单个数据项可以超过64K,其它同large 模型 |
MS-DOS Windows |
说明:small
模型是一般应用程序最常用的一种模型,因为只有一个代码段和一个数据段,所以数据和代码都是近访问的。所以一般将 .model
指定为 small
就可以了。
简化段伪指令:
伪指令 | 功能 | 说明 |
---|---|---|
.code [段名] | 创建一个代码段 | 隐含段名为 @code |
.data | 创建一个数据段 | 隐含段名为 @data |
.stack [大小] | 创建一个堆栈段并指定大小 | 隐含段名为 @stack ,并形成ss 和sp 的初值 |
例:
其他伪操作
1. 基数控制
汇编程序默认的数为十进制数,还可以由以下方式指定基数:
- 二进制: 01001000b
- 八进制: 123q 或 123o
- 十进制: 1234d
- 十六进制: 1234h / 0ffffh (第一个为字母时前面加0)
2. '$'
地址计数器
'$'
保存了当前汇编指令的偏移地址。
常用用途:
计算字符串长度
123456datastr1 db 'hello'len1 db $-str1 ; 5str2 db 'world hahaha'len2 db $-str2 ; 12data ends跳转
1jne $+6 ; 跳转到 jne 指令所在地址 + 6