更灵活的定位内存地址的方法
7.1 and 和 or 指令
(1)and 指令:逻辑与指令,按位进行与运算。
例如指令:
mov al,01100011B
and al, 00111011B
执行后:al=00100011B
通过该指令可将操作对象的相应位设为 0,其他位不变。
(2)or 指令:逻辑或指令,按位进行或运算。
例如指令:
mov al,01100011B
or al,00111011B
执行后:al=01111011B
通过该指令可将操作对象的相应位设为 1,其他位不变。
7.3 以字符形式给出的数据
assume cs:code,ds:data data segment db 'unIX' db 'foRK' data ends code segment start: mov al,'a' mov bl,'b' mov ax,4c00h int 21h code ends end start
上面的源程序中:“db 'unIX'”相当于“db 75H,6EH,49H,58H”,“u”、“n”、“I”、“X”的 ASCII 码分别为75H、6EH、49H、58H;
将上面的程序编译后调试可以查看里面的内容:
现在问题来了,我们数据段中的内容在内存什么位置呢?上图中 DS=0760,CS:IP=0771:0000,也就是说,我们的数据应该位于 0771h-1h=0770h 处(一个段的大小为 16 的倍数,最小为 16 字节),我们查看一下:
我们也可以根据下图理解(正常方法):
CS=DS+10H,
10H是PSP区,用来通信的。
也就是说,DS 为 0760h 的话,那么我们的程序开始的地方应该是 0770h。
2017/10/14更新:我们要注意的是,我们的数据还是在 程序区 开始的一段内存里,而不是 ds 指向的那一段内存。我们可以使用命令 d 0760:0 f 查看 07600 开始的 16 个字节单元的内容,我们会发现并不是我们写入内存的字符串,而当我们用 d 0770:0 f 查看的时候,才有我们写在源程序里面的字符串。
7.5 [bx+idata]
在前面,我们用 [bx] 的方式来指明一个内存单元,还可以用一种更为灵活的方式来指明内存单元:[bx+idata] 表示一个内存单元,它的偏移地址为 (bx)+idata (bx 中的数值加上 idata)。
我们看一下指令 mov ax,[bx+200] 的含义:
将一个内存单元的内容送入 ax,这个内存单元的长度为 2 个字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 200,段地址在 ds 中。
数学化描述为:(ax)=((ds)*16 + (bx) + 200)
该指令也可以写成如下格式(常用):
mov ax,[200+bx]
mov ax,200[bx]
mov ax,[bx].200
7.7 SI 和 DI
si 和 di 是 8086CPU 中和 bx 功能相近的寄存器,si 和 di 不能够分成两个 8 位寄存器来使用。下面的 3 组指令实现了相同的功能。
(1)mov bx,0
mov ax,[bx]
(2)mov si,0
mov ax,[si]
(3)mov di,0
mov ax,[di]
下面的 3 组指令也实现了相同的功能
(1)mov bx,0
mov ax,[bx+123]
(2)mov si,0
mov ax,[si+123]
(3)mov di,0
mov ax,[di+123]
7.8 [bx+si] 和 [bx+di]
在前面,我们用[bx(si 或 di)]和[bx(si 或 di)+idata]的方式来指明一个内存单元,我们还可以用更灵活的方式:[bx+si] 和 [bx+di]。
[bx+si] 和 [bx+di] 的含义相似,我们以[bx+si]为例进行详解。
[bx+si] 表示一个内存单元,它的偏移地址为 (bx)+(si) (即 bx 中的数值加上 si 中的数值)。
指令 mov ax,[bx+si] 的含义如下:
将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 si 中的数值,段地址在 ds 中。
数学化描述为:(ax)=((ds)*16+(bx)+(si))。
该指令也可以写成如下格式(常用):
mov ax,[bx][si]
7.9 [bx+si+idata] 和 [bx+di+idata]
[bx+si+idata] 和 [bx+di+idata] 的含义相似,我们以 [bx+si+idata] 为例进行详解。
[bx+si+idata] 表示一个内存单元,它的偏移地址为 (bx)+(si)+idata(即 bx 中的数值加上 si 中的数值 再加上 idata)。
指令 mov ax,[bx+si+idata] 的含义如下:
将一个内存单元的内容送入 ax,这个内存单元的长度为 2 字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 si 中的数值再加上 idata,段地址在 ds 中。
数学化描述为:(ax)=((ds)*16+(bx)+(si)+idata)
该指令也可以写成如下格式(常用):
mov ax,[bx+200+si]
mov ax,[200+bx+si]
mov ax,200[bx][si]
mvo ax,[bx].200[si]
mov ax,[bx][si].200
7.10 不同的寻址方式的灵活应用
如果我们比较一下前面用到的几种定位内存地址的方法(可称为寻址方式),就可以发现:
(1)[idata] 用一个常量来表示地址,可用于直接定位一个内存单元;
(2)[bx] 用一个变量来表示内存地址,可用于间接定位一个内存单元;
(3)[bx+idata] 用一个变量和一个常量来表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
(4)[bx+si] 用两个变量表示地址;
(5)[bx+si+idata] 用两个变量和一个常量表示地址。
可以看到,从[idata]一直到[bx+si+idata],我们可以用更加灵活的方式来定位一个单元的地址。这使我们可以从更加结构化的角度来看待要处理的数据。