1.1 and 和 or 指令
(1)and指令:逻辑与指令,按位进行与运算 (出现0则为0)
(2)or指令:逻辑或运算,按位进行或运算 (出现1则为1)
1.2 ASCII编码解码
一个文本编辑过程中,就包含着按照 ASCI编码规则进行的编码和解码。在文本编辑过程中,我们按一下键盘的 a 键,就会在屏幕上看到"a"。这是怎样一个过程呢?我们按下键盘的 a 键,这个按键的信息被送入计算机,计算机用 ASCII码的规则对其进行编码,将其转化为 61H 存储在内存的指定空间中;文本编辑软件从内存中取出 61H,将其送到显卡上的显存中;**工作在文本模式下的显卡,用 ASCII码的规则解释显存中的内容,61H 被当作字符"a",显卡驱动显示器,将字符"a"的图像画在屏幕上。**我们可以看到,显卡在处理文本信息的时候,是按照 ASCII码的规则进行的。这也就是说,如果我们要想在显示器上看到"a",就要给显卡提供"a"的 ASCII 码,61H。如何提供?当然是写入显存中。
1.3 以字符形式给出的数据
在汇编程序中,可以用 ’……’ 的方式指明数据是以字符的形式给出的,编译器将把它们转化为相对应的 ASCII码。
注:" db ‘unIX’ "相当于 “db 75H,6EH,49H,58H”,“u”、“n”、“I”、"X"的ASCII 码分别为75H、6EH、49H、58H;
"mov al,‘a’ “相当于"mov al,61H”,"a"的 ASCII码为61H;
用 d 命令查看 data 段,Debug 以十六进制数码和 ASCII 码字符的形式显示出其中的内容,从中,可以看出 data 段中的每个数据所对应的 ASCII字符。
1.4 大小写转换的问题
一个字母,不管它原来是大写还是小写,将它的第5位设置为 0,它就必将变为大写字母; 将它的第5位设置为1,它就必将变为小写字母。在这个方法中,我们不需要在处理前判断字母的大小写。
例:
解:
1.5 [bx+idata]
可以用一种更为灵活的方式来指明内存单元∶
【bx+idata】表示一个内存单元,它的偏移地址为(bx)+idata(bx 中的数值加上idata)。
例:指令mov ax,[bx+200]
数学化描述为∶(ax)=((ds)*16+(bx)+200 )
该指令也可以写成如下格式(常用):
mov ax,[200+bx]
mov ax,200[bx]
mov ax,[bx].200
例题:
(ax) = 00BEH,(bx) = 0600H,(cx) = 0606H
1.6 用[bx+idata]的方式进行数组的处理
[bx+idata] 中的idata可以用来定位不同字符串起始地址,在同一循环中使用 [a+bx] 和 [b+bx] 的方式定位两个字符串的起始偏移地址。
而长度相同的字符(cx相同),在同一循环中,每各遍历一个字符,从起始地址开始的相对地址的变化是相同的(即bx递增相同)
1.7 SI 和 DI
si和 di 是 8086CPU中和 bx 功能相近的寄存器,si和 di 不能够分成两个8位寄存器来使用。
1.8 [bx+si] 和 [bx+di]
注:【bx+si】和【bx+di】的含义相似
【bx+si】表示一个内存单元,它的偏移地址为(bx)+(si)(即 bx 中的数值加上 si 中的数值)。
指令mov ax,【bx+si】的含义如下∶
将一个内存单元的内容送入 ax,这个内存单元的长度为 2字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 si 中的数值,段地址在 ds 中。
数学化的描述为∶(ax)=((ds)*16+(bx)+(si) )
该指令也可以写成如下格式(常用)∶
mov ax,[bx][si]
1.9 [bx+si+idata] 和 [bx+di+idata]
注:【bx+si+idata】和【bx+di+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]
mov ax,[bx].200[si]
mov ax,[bx][si].200
1.10 不同的寻址方式的灵活应用
(1)【idata】用一个常量来表示地址,可用于直接定位一个内存单元;
(2)【bx】用一个变量来表示内存地址,可用于间接定位一个内存单元;
(3)【bx+idata】用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
(4)【bx+si】用两个变量表示地址;
(5)【bx+si+idata】用两个变量和一个常量表示地址。
思考:
程序中经常需要进行数据的暂存,怎样做将更为合理 ?
这些数据可能是寄存器中的,也可能是内存中的。我们可以用寄存器暂存它们,但是这不是一个一般化的解决方案,因为寄存器的数量有限,每个程序中可使用的寄存器都不一样。我们希望寻找一个通用的方案,来解决这种在编程中经常会出现的问题。
显然,我们不能选择寄存器,那么可以使用的就是内存了。可以考虑将需要暂存的数据放到内存单元中,需要使用的时候,再从内存单元中恢复。这样我们就需要开辟一段内存空间。
一般来说,在需要暂存数据的时候,我们都应该使用栈。栈空间在内存中,采用相关的指令,如 push、pop 等,可对其进行特殊的操作。
例:
解:(栈段暂存数据外层循环cx的值,push&pop)
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
stacksg segment ;定义一个段,用来做栈段,容量为16个字节
dw 0,0,0,0,0,0,0,0
stacksg ends
codesg segment
start:mov ax, stacksg
mov ss, ax
mov sp,16
mov ax, datasg
mov ds,ax
mov bx,0
mov cx,4
s0: push cx ;将外层循环的cx值压栈
mov si,0
mov cx, 3 ;cx 设置为内层循环的次数
s: mov al,[bx+si]
and al,11011111b
mov [bx+si], al
inc si
loop s
add bx, 16
pop cx ;从栈顶弹出原 cx的值,恢复 cx
loop s0 ;外层循环的loop 指令将 cx 中的计数值减1
mov ax, 4c00H
int 21H
codesg ends
end start
总结: