本篇介绍在汇编中使用多个段编写代码以及更多的寻址方式。
栈的使用
利用栈将程序中定义的数据逆序存放,代码如下:
assume cs:codesg |
将数据、代码、栈放入不同的段
上面的程序稍加修改,改为下面的,则可将数据、代码、栈放入不同的段,代码如下:
assume cs:codesg,ds:data,ss:stack |
从程序中看出,定义多个段和前面的定义代码一样,都是用 assume 的方法。
指令 mov ax,stack 的意义是将 stack 段的段地址放入 ax,然后 mov ss,ax 表示把 stack 段的段地址放入 ss 中,这样我们就正确的设置栈段的段地址。同理 mov ax,data 和 mov ds:ax 表示一样的意思,是将代码段的段地址放入 ds 中。
and 和 or 指令
and 表示按位与指令,or 表示逻辑或指令,进行按位或运算。
例如指令
mov al,01110000B
and al,00010000B
执行后 al 中的内容为 00010000B
再例如指令
mov al,00000000B
or al,11111110B
执行后 al 中的内容为 11111110B
更灵活的寻址方式
前面介绍过用 [idata] 的方式进行寻址,当然也可以用 [bx] 的方式寻址,同样也可以用 [bx + idata] 的方式寻址,它表示的意义为 [bx + idata] 表示一个内存单元,它的偏移地址为 bx 中的值加上 idata 的值,段地址在 ds 中。例如指令 mov ax,[bx + 200] ,它表示将一个内存单元中的内容送入 ax 中,这个内存单元的偏移地址为 bx 中的内容加上 200,段地址在 ds 中。该指令还可以用以下的形式表示:
- mov ax,[200 + bx]
- mov ax, 200[bx]
- mov ax, [bx].200
SI 和 DI 是 8086CPU 中和 bx 功能相近的寄存器,但是它们不能够用作两个 8 为寄存器来使用。当然也能够用 [bx + si] 或者 [bx + di] 的方式来寻址,同样的也可以用 [bx + si + idata] 或者 [bx + di + idata] 的方式来寻址。指令 mov ax,[bx + si + 200] 的含义为:它表示一个内存单元中的内容送入 ax 中,这个内存单元的偏移地址为 bx 加 si 加 200 ,段地址在 ds 中。该指令也可以用以下常用的形式表示:
- mov ax,[dx + 200 + si]
- mov ax,[200 + dx + si]
- mov ax,200[bx][si]
- mov ax,[bx].200[si]
- mov ax,[bx][si].200
目前为止,已经学到了很多种寻址的方法,总结如下:
- [idata] 用一个常量定位一个内存单元
- [bx] 用一个变量定位一个内存单元
- [bx + idata] 用一个变量和常量定位一个内存单元
- [bx + si] 或 [bx + di] 用两个变量来定位一个内存单元
- [bx + si + idata] 或 [bx + di + idata] 用两个变量和一个常量来定位一个内存单元
实战:用 si 和 di 实现将字符串 ‘welcome to masm!’ 复制到它后面的数据区中,代码如下
assume cs:codesg,ds:datasg |
代码执行后,从下图可以看出复制成功了。

在 8086CPU 中只有 bx、si、di、bp 这四个寄存器能用 […] 的方式寻址。当然也可以是这组合形式,比如:bx 和 si,bx 和 di,bp 和 si,bp 和 di,而 bx 和 bp 或者 si 和 di 却是错误的。
寻址方式总结
通过前面的学习,现将 8086CPU 的寻址方式做以下总结:
寻址方式 | 名称 | |
---|---|---|
[idata] | 直接寻址 | |
[bx],[bp],[si],[di] | 寄存器间接寻址 | |
[bx+idata],[bp+idata],[si+idata],[di+idata] | 寄存器相对寻址 | |
[bx+si],[bx+di],[bp+si],[bp+di] | 基址变址寻址 | |
[bx+si+idata],[bx+di+idata],[bp+si+idata],[bp+di+idata] | 相对基址变址寻址 |
总结
通过本次学习,我们知道了怎么在汇编中运用多个段来编写程序,了解了 and 指令和 or 指令的用法,总结了 8086CPU 的寻址方式,收获颇丰,继续努力!