# 一、`and`和`or`指令
按位与、或:
`and`:与,1 and 1: 1,其他的为 0
`or`: 或,0 or 0 : 0,其他的为 1
~~~
and al, 1010100B
or al, 00101011B
~~~
# 二、ASCII码
ASCII,美国信息交换标准代码,主要用于显示现代英语和其他西欧语言.
# 三、以字符形式给出的数据
db: 定义字节型数据
dw:定义字型数据
~~~
db 75H, 6EH, 49H,58H
; 相当于
db 'unIX'
~~~
# 四、大小写转换的问题
改变的是它的 `ASCII` 码

那么他们的十六进制对应的二进制有什么联系?

如果是 小写,asscii减 `20H`就可以得到对应的大写。
使用 `and` 和 `or`来做判断:
~~~
assume cs:code, ds:data
data segment
db 'SaSiC'
db 'iDiIDssiDww'
data ends
code segment
start: mov ax, data
mov ds, ax ; 设置ds指向data段
mov bx, 0 ; 设置 (bx)=0,ds:bx指向“SaSiC”的第一个字母
mov cx, 0 ;设置循环5次, 因为“SaSiC”有5个字母
s: mov a1, [bx] ; 将ASCII从ds:bx所指向的单元中取出来
add al, 110111111b ; 将al从ASCII中的第s个位置为0,变为大写字母
mov [bx], a1 ; 将转转变后的ASCII放回原来的单元
inc bx ; (bx)自增,ds:bx指向下一个字母
loop s
mov bx, 5 ; 设置bx为5,为什么是5,由于“SaSiC”有5个字母,所以 ds:bx指向“iDiIDssiDww”的第一个字母
mov cx, 11 ; 设置循环次数
s0: mov al, [bx]
or al, 00100000b ; 将al从ASCII中的第s个位置为0,变为小写字母
mov [bx], al
inc bx
loop s0
mov ax, 4c00H
int 21H
code ends
end start
~~~
# 五、`[bx idata]`
`[bx idata]`表示一个内存单元,它的偏移地址为:(bx)+idata,即为bx中的数值+idata
查看`mov ax, [bx+200]`的含义:
将一个内存单元的内容送入 ax 中,这个内存单元的长度为 2 字节(字单元),偏移地址为:bx中的值+200所对应的段地址ds中。
转换成数学描述: (ax) = ((ds)*16+(bx)+200)。
`mov ax, [bx+200]`还有以下写法:
+ `mov ax, [200+bx]`
+ `mov ax, 200[bx]`
+ `mov ax, [bx].200`
# 六、用`[bx idata]`的方式进行数组的处理
就`将字母转换成大小写`可以修改成:
~~~
assume cs:code, ds:data
data segment
db 'SaSiC'
db 'i39878678On'
data ends
code segment
start: mov ax, data
mov ds, ax ; 设置ds指向data段
mov bx, 0 ; 设置 (bx)=0,ds:bx指向“SaSiC”的第一个字母
mov cx, 0 ;设置循环5次, 因为“SaSiC”有5个字母
s: mov a1, [bx] ; 将ASCII从ds:bx所指向的单元中取出来
add al, 110111111b ; 将al从ASCII中的第s个位置为0,变为大写字母
mov [bx], a1 ; 将转转变后的ASCII放回原来的单元
mov al, [5+bx] ; 定位到第二个字符串的第一个字符
or al, 0010000b
mov [5+bx], al
inc bx ; (bx)自增,ds:bx指向下一个字母
loop s
mov ax, 4c00H
int 21H
code ends
end start
~~~
# 七、`SI`和`DI`
这两个寄存**不能分为两个 8 位的寄存器**来使用。
他们的功能与 bx 类似。
以下三组命令实现了同样的功能:

以下三组命令实现了同样的功能:

用寄存器SI和DI实现将字符串‘welcome to masm!’复制到它后面的数据区中。
~~~
assume cs:codesg,ds:datasg
datasg segment
db ‘welcome to masm!’
db ‘…………….’
~~~
~~~
assume cs:code, ds:data
data segment
db "welcome to masm!"
dd "........"
data ends
code segment
start: mov ax, data
mov ds, ax
mov si, 0 ; 原地址从 0 开始
mov di, 16 ; 长度为16字节,所以目标地址从16字节开始
mov cx, 8 ; si和di都是16位的寄存器, 而"welcome to masm!"共 16 字节,一次复制 2 个字节,则需复制 8 次
s: mov ax, [si]
mov [di], ax
add si, 2 ; 每次复制 2 位
add di, 2
loop s
mov ax, 4c00H
int 21H
code ends
end start
~~~
程序中使用`ds:si`指向了要复制的源字符串,`ds:di`指向复制的目的空间。
使用数组的方式,来解决问题:
~~~
assume cs:code, ds:data
data segment
db "welcome to masm!"
dd "........"
data ends
code segment
start: mov ax, data
mov ds, ax
mov si, 0
mov cx, 8 ; 循环 8 次
s: mov ax, 0[si] ; 读取 [0+si]的值
mov 16[si], ax ; 目标地址从 [16+si]开始
add si, 2
loop s
mov ax, 4c00H
int 21H
code ends
end start
~~~
# 八、`[bx si]`和`[bx di]`
`[bx si]`表示一个内存单元,他的偏移地址为: (bx)+(si)。
**我们看下指令mov ax,[bx+si]的含义:**
将一个内存单元的内容送入ax,这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为:bx中的数值加上si中的数值,段地址在ds中。
指令mov ax,[bx+si]的数学化的描述为:(ax)=( (ds)*16+(bx)+(si) )
该指令也可以写成如下格式(常用):`mov ax,[bx][si]`
# 九、`[bx si idata]`和`[bx di idata]`
`[bx+si+idata]`表示一个内存单元,它的偏移地址为`(bx)+(si)+idata`。(即bx中的数值加上si中的数值再加上idata)
数学化的描述为: ` (ax)=( (ds)*16+(bx)+(si)+idata )`
**指令 mov ax,[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
# 十、不同的寻址方式的灵活应用
寻址方式:定位内存地址的方法。
几种寻址方式:
+ `[idata]`用常量表示地址,直接定位一个内存单元
+ `[bx]`用变量表示地址,间接定位一个内存单元
+ `[bx+idata]`用变量+常量的方式,在一个起始地址的基础上用变量**间接**定位一个内存单元
+ `[bx+si/di]` 用两个变量表示地址
+ `[bx+si+di]`用两个变量和一个常量表示地址
## 将datasg段中每个单词的头一个字母改为大写字母
~~~
assume cs:codesg,ds:datasg
datasg segment
db '1. file '
db '2. edit '
db '3. search '
db '4. view '
db '5. options '
db '6. help '
datasg ends
codesg segment
start:……
codesg ends
end start
~~~
完整代码:
~~~
assume cs:codesg,ds:datasg
datasg segment
db '1. file '
db '2. edit '
db '3. search '
db '4. view '
db '5. options '
db '6. help '
datasg ends
codesg segment
start: mov ax, datasg
mov ds, ax
mov bx, 0
mov cx, 6
S: mov al, [bx+3] ; 单位是字节,所以是al
and al, 110011111b
mov [bx+3], al
add bx , 16
loop s
mov 4c00H
int 12H
codesg ends
end start
~~~
## 将datasg段中每个单词改为大写字母(循环嵌套)
~~~
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
codesg segment
start:
……
codesg ends
end start
~~~

完整代码:
~~~
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec ' ; 共 16 字节
db 'dos '
db 'vax '
datasg ends
codesg segment
start: mov ax, datasg
mov ds, ax
mov bx, 0 ; 定位行
mov cx, 4
s: mov si, 0 ; 定位列
mov cx, 3 ; 内层循环执行次数
s0: mov al, [bx+si] ; 对 每一行 的数据进行处理
and al, 1101111b
mov [bx+si], al
inc si
loop s0 ; 此时的 cx 为 0
add bx, 16 ; 指到下一行
loop s ; 下面再-1,就变成了FFFFH
mov ax, 4c00H
int 21H
codesg ends
end start
~~~
以上的程序有bug,原因:在内存循环执行完成后,`cx=0`
我们应该在指向内存循环之前,需将外层的cx保存起来,执行完了之后再恢复。
修改后的程序:
~~~
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec ' ; 共 16 字节
db 'dos '
db 'vax '
datasg ends
codesg segment
start: mov ax, datasg
mov ds, ax
mov bx, 0 ; 定位行
mov cx, 4
s: mov dx, cx ; 用dx存放外层cx的值 --------
mov si, 0 ; 定位列
mov cx, 3 ; 内层循环执行次数
s0: mov al, [bx+si] ; 对 每一行 的数据进行处理
and al, 1101111b
mov [bx+si], al
inc si
loop s0
add bx, 16 ; 指到下一行
mov cx, dx ; 在外层循环恢复cx的值 --------
loop s
mov ax, 4c00H
int 21H
codesg ends
end start
~~~
**另外一种解决办法**
~~~
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec ' ; 共 16 字节
db 'dos '
db 'vax '
dw 0 ; 用于存放 cx的值 ------
datasg ends
codesg segment
start:mov ax, datasg
mov ds, ax
mov bx, 0 ; 定位行
mov cx, 4
s: mov ds:[40H], cx ;将cx存入 dw 定义的内存单元 -------
mov si, 0 ; 定位列
mov cx, 3 ; 内层循环执行次数
s0: mov al, [bx+si] ; 对 每一行 的数据进行处理
and al, 1101111b
mov [bx+si], al
inc si
loop s0
add bx, 16 ; 指到下一行
mov cx, ds:[40H] ; 在外层循环恢复cx的值 --------
loop s
mov ax, 4c00H
int 21H
codesg ends
end start
~~~
# 将datasg段中每个单词的前四个字母改为大写字母
~~~
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
db '1. display......'
db '2. brows........'
db '3. replace......'
db '4. modify.......'
datasg ends
codesg segment
start:
……
codesg ends
end start
~~~
编程:
~~~
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
db '1. display......'
db '2. brows........'
db '3. replace......'
db '4. modify.......'
datasg 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
s: push cx ; -----------------
mov si, 0
mov cx, 4
s0: mov al, [bx+3+si]
mov al, 11011111b
mov [bx+3+si], al
inc si
loop s0
add bx, 16
pop cx ; -----------------
loop s
mov ax, 4c00H
int 21H
codesg ends
end start
~~~
