and 和 or 指令
1、and 指令:逻辑与指令,按位进行与运算。
mov al , 01100011B and al , 00111011B ; 结果00100011B |
2、or 指令:逻辑或指令,按位进行或运算。
mov al , 01100011B or al , 00111011B ; j结果01111011B |
可以用来将操作对象的相应位设置为 1 ,其他位不变。
计算机中的 ASCII 码
编码规则,文本编辑过程就是按照ASCII码规则进行的编码和解码。当我们按下键盘的一个 a ,这个按键信息被送入计算机,计算机用ASCII码规则对其进行编码,将其转化为61H存储在内存指定空间;文本编辑软件取出内存中的61H,将其送到显卡的显存中;工作在文本模式下的显卡,用ASCII码规则解释显存中的内容,61H被当做字符“a”,显卡驱动显示器,将字符“a”的图像画在屏幕上。
以字符形式给出的数据
在汇编程序中,用‘...’的方式指明数据是以字符的形式给出的,编译器把它们转化为相应的 ascii 。
assume ds:data , cs:code 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” db 'foRK' 相当于“db 66h , 6fh , 52h , 4bh” mov al , 'a' 相当于 "mov al , 61h" |
// 这个程序运行第一条指令指向mov al 'a' ;数据肯定存放在这条指令的上面,就是 076A:0
;定义程序,把字符串的大写改小写,小写改大写 assume cs:codesg , ds:datasg datasg segment db 'BaSic' db 'iNfOrMaTion' datasg ends codedg segment start: mov ax , datasg ;设置 ds 指向 datasg 段 ;这条指令执行的同时,系统就把数据段的空间分配好了 mov ds , ax mov bx , 0 ;设置(bx)=0,ds:bx指向 'BaSic' 的第一个字母 mov cx , 5 s: mov al , [bx] ;取出 'B' 放到 al 中 and al , 11011111B ;转换,因为大写和小写字母只是二进制的第5位不一样;小写字母第5位为1,改成0就变成相应的大写 mov [bx] , al ;转换完成,写回原单元。 inc bx ;偏移一位,指向下一个字母 loop s mov bx , 5 ;设置偏移,指向'iNfOrMaTiOn'的第一个字母 mov cx , 11 ;设置循环次数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)+idata
eg:mov ax , [bx+200] ; 将一个内存单元的内容送入 ax , 这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为 bx 中的数值加上 200,段地址在 ds 中。
mov ax , [200+bx] mov ax , 200[bx] mov ax , [bx].200 ;立即数不在最开头就要前面加一个. |
[bx+idata]的方式进行数组的处理
改写上面那个程序字符大写改小写,小写改大写的程序
assume cs:codesg , ds:datasg
datasg segment
db 'BaSic'
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
mov al , [5+bx]
or al , 00100000B
mov [5+bx] , al ; 第一次5次循环直接可以同时操作两个串,如果两个字符串一样效率更高
inc bx
loop s
mov cx , 6
inc bx
s0: mov al , [5+bx] ; 处理较长的字符串剩下的字符
or al , 00100000B
loop s0
mov ax , 4c00h
int 21h
codesg ends
end start
|
SI 和 DI
SI 和 DI 是8086CPU中和 bx 功能相近的寄存器,SI 和 DI 不能够分成两个 8 位寄存器来使用
SI:源变址寄存器; DI:目的变址寄存器;
mov bx , 0 mov ax , [bx] |
mov si , 0 mov ax , [si] |
mov di mov ax , [di] |
*3组指令效果一样
;用 SI 和 DI 寄存器来实现将字符串 'welcome to masm!' 复制到它后面的数据区 assume cs:codesg , ds:datasg datasg segment db 'welcome to masm!' db '................' datasg ends codesg segment start: mov ax , datasg mov ds , ax mov si , 0 mov di , 16 mov cx , 8 s: mov ax , [si] mov [di] , ax add si , 2 ;si 和 di 不能分成两个8寄存器,所以一次拷贝会拷贝16位2个字节,每次循环+2 add di , 2 loop s mov ax , 4c00h int 21h codesg ends end start |
tips:start后面紧更着冒号
[bx+si] 和 [bx+di]
[bx+si+idata] 和 [bx+di+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
|
;将datasg段中的每个单词改为大写字母 assume cs:codesg , ds:datasg datasg segment db 'ibm ' db 'dec ' db 'dos ' db 'vax ' datasg ends codesg segment start: mov ax , datasg mov ds , ax mov bx , 0 mov cx , 4 s0: mov dx , 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 mov cx , dx ;恢复外层循环cx的值 loop s0 codesg ends end start ; 程序每次修改一行的字符,然后转到下一行,所以用到两个循环,不得不暂存cx的值,但是cpu的寄存器是有限的;如果寄存器不够用,最好的办法是用一个指定的内存地址来暂存数据,ds:[idata];但是最好还是用栈来存放 |
;优化 assume cs:codesg , ds:datasg , ss:stacksg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
stacksg segment ; 用栈段来存放临时数据
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的值
loop s0
codesg ends
end start
|