在之前的文章中,我们用[0],[bx]的方法定位内存单元的地址,我们现在将用一些具体问题来复习一些更灵活的定位地址内存的方法和相关的编程方法。
and和or指令:
(1)and指令,逻辑与指令,按位进行与运算
例如指令:
mov al,01100011B
and al,001110011B
执行后:al = 00100011B
通过该指令可将操作对象的相应位设为0,其他位不变。
例如:
将al的第6位设置0的指令是:
and al,10111111B
将al的第0位设置0的指令时:
and al,11111110B
(2)or指令:逻辑或指令,按位进行或运算
例如指令:
mov al,01100011B
or al,00111011B
执行后:al = 01111011B
通过该指令可以将操作对象相应位设为1,其他位不变
例如:
将al的第6位设为1的指令是:
or al,01000000B
以字符形式给出的数据:
我们可以在汇编程序中,用'......'的方式指明数据是以字符的形式给出的编译器会将它们转化为相应的ASCII码。例如:
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
大小写转换问题:
考虑这样一个问题,在codesg中编写代码,将datasg中的第一个字符串转化为大写,第二个字符串转化为小写。
在ASCII码中,小写字母的ASCII码值大写字母大20H。除此之外,将字母的ASCII码值转换成二进制可以发现,一个字母,无论是大写还是小写,将他的第5位置为0,它就变成大写字母,将它置为1,它就变成小写字母。根据上面学到的and和or指令,我们可以写出以下程序:
assume cs:codesg,ds:datasg
datasg segment
db 'unIX'
db 'iNfOrMaTiOn'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s0: mov al,[bx]
or al,00100000B
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
[bx + idata]:
在前面,我们用[bx]的方式来指明一个内存单元,还可以用一种更为灵活的方式来指明内存单元,它的偏移地址为(bx)+ idata
所以上面程序中的codesg可以改写为:
assume cs:codesg,ds:datasg
datasg segment
db 'BaSiC'
db 'MinIX'
data ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
mov al,[5+bx]
or al,00100000B
mov [5+bx],al
inc bx
loop s
codesg ends
end start
SI和DI:
si和di是8086CPU中和bx功能相近的寄存器,si和di不能分为两个8位寄存器来使用。
下面3组指令实现了相同的功能:
mov bx,0
mov ax,[bx]
mov si,0
mov ax,[si]
mov di,0
mov ax,[di]
下面三组指令也实现了相同的功能:
mov bx,0
mov ax,[bx+123]
mov si,0
mov ax,[si+123]
mov di,0
mov ax,[di+123]
[bx+si]和[bx+di]
我们还可以用更灵活的方式:[bx+si]和[bx+di]
例如:
mov ax,[bx+si]
也可以写作:
mov ax,[bx][si]
我们也可以用[bx+si+idata]和[bx+di+idata]来确定内存地址