ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 一、`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` 码 ![](https://box.kancloud.cn/401abc9d9f6f5d0b272693bd18ca8c47_681x1261.png) 那么他们的十六进制对应的二进制有什么联系? ![](https://box.kancloud.cn/31317b57ac7cf1bbee194b503e9f1508_731x286.png) 如果是 小写,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 类似。 以下三组命令实现了同样的功能: ![](https://box.kancloud.cn/60f47ba84c23ddc87e836d650d57f023_478x297.png) 以下三组命令实现了同样的功能: ![](https://box.kancloud.cn/509f10dcf883af8c9d7c314b9ac853ef_423x346.png) 用寄存器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 ~~~ ![](https://box.kancloud.cn/ec3696a0f8063a0fa16aa0a324a8a38a_566x225.png) 完整代码: ~~~ 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 ~~~