and指令:
逻辑与
指令,按位进行与
运算(同真为真)
比如:
mov al, 01100011B and al, 00111011B ;执行后:al=00100011B即都为1才为1
- 1
- 2
- 3
or指令:
逻辑或
指令,按位进行或
运算(同假为假)
比如:
mov al, 01100011B or al, 00111011B ;执行后:al=01111011B 即只要有一个为1就为1
- 1
- 2
- 3
关于ASCII码在内存中的存储:
- 世界上有很多编码方案,有一种方案叫做ASCII编码,是在计算机系统中通常被采用的。简单地说,所谓编码方案,就是一套规则,它约定了用什么样的信息来表示现实对象。比如说,在ASCII编码方案中,用61H表示“a”,62H表示“b”。一种规则需要人们遵守才有意义
- 在文本编辑过程中,我们按一下键盘的a键,就会在屏幕上看到“a”。我们按下键盘的a键,这个按键的信息被送入计算机,计算机用ASCII码的规则对其进行编码,将其转化为61H存储在内存的指定空间中;文本编辑软件从内存中取出61H,将其送到显卡上的显存中;工作在文本模式下的显卡,用ASCII码的规则解释显存中的内容
- 61H被当作字符“a”,显卡驱动显示器将字符“a”的图像画在屏幕上。我们可以看到,显卡在处理文本信息的时候,是按照ASCII码的规则进行的。这也就是说,如果我们要想在显示器上看到“a”,就要给显卡提供“a”的ASCII码,61H。如何提供?当然是写入显存中
比如:
assume cs:code,ds:data data segment db 'unIx' ;相当于“db 75H,6EH,49H,58H” db 'foRK' data ends code segment start: mov al, 'a' ;相当于“mov al, 61H”,“a”的ASCI码为61H; mov b1, 'b' mov ax, 4c00h int 21h code ends end start
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
关于字符在内存中大小写转换的问题:
小写字母的ASCII码值比大写字母的ASCII码值大20H
大写字母ASCII码的第5位为0,小写字母的第5位为1(其他一致),大小写相差32,即2^5。注:这里的位数是从0开始计算的
assume cs:codesg,ds:datasg datasg segment db 'BaSiC' db 'iNfOrMaTion' datasg end codesg segment start: mov ax, datasg mov ds, ax ;设置ds 指向 datasg段 mov bx, 0 ;设置(bx)=0,ds:bx指向’BaSic’的第一个字母 mov cx, 5 ;设置循环次数5,因为’Basic'有5个字母 s: mov al, [bx] ;将ASCII码从ds:bx所指向的单元中取出 and al, 11011111B;将al中的ASCII码的第5位置为0,变为大写字母 mov [bx], al ;将转变后的ASCII码写回原单元 inc bx ;(bx)加1,ds:bx指向下一个字母 loop s mov bx, 5 ;设置(bx)=5,ds:bx指向,iNfOrMaTion'的第一个字母 mov cx, 11 ;设置循环次数11,因为‘iNfOrMaTion'有11个字母 s0: mov al, [bx] or al, 00100000B;将a1中的ASCII码的第5位置为1,变为小写字母 mov [bx], al inc bx loop s0 mov ax, 4c00h int 21h codesg ends
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
[bx+idata]表示一个内存单元, 例如:
mov ax, [bx+200]
,该指令也可以写成如下格式:mov ax, [200+bx] ;将一个内存单元内容送入ax,这个内存单元的长度为2个字节,偏移地址为bx中的数值加上200,段地址在ds中,即(ax)=((ds)*16+(bs)+200) mov ax,[bx+200] ;其他格式 mov ax, 200[bx] ;其他格式 mov ax, [bx].200 ;其他格式 ;案例:用Debug查看内存,结果如下 ;2000:1000H BE 00 06 00 00 00 ... mov ax,2000H mov ds,ax mov bx,1000H mov ax,[bx] ;段地址:(ds)=2000H 偏移地址:(bx)=1000H 则(ax)=00BEH mov cx,[bx+1] ;段地址:(ds)=2000H 偏移地址:(bx+1)=1001H 则(cx)=0600H add cx,[bx+2] ;段地址:(ds)=2000H 偏移地址:(bx+2)=1002H 则(cx)=0606H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
用[bx+idata]的方式进行数组的处理:
assume cs:codesg,ds:datasg datasg segment db 'BaSiC';转为大写 db 'MinIx';转为小写 datasg ends codesg segment start: mov ax, datasg mov ds, ax mov bx, 0 ;初始ds:bx mov cx, 5 s: mov al, 0[bx] and al, 11011111b ;转为大写字母 mov 0[bx], al ;写回 mov al, 5[bx] ;[5 + bx] or al, 00100000b ;转为小写字母 mov 5[bx], al inc bx loop s mov ax, 4c00h int 21h codesg ends end start
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
C语言描述方式:
int main() { char a[] = "BaSic"; char b[] = "MinIX"; int i = 0; do { a[i] = a[i] & 0xDF; b[i] = b[i] | 0x20; i++; } while(i < 5); return 0; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
si和di是8086CPU中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用
assume cs: codesg, ds: datasg datasg segment db 'welcome to masm!' ;用si和di实现将字符串‘welcome to masm!"复制到它后面的数据区中。 db '................' ;db是ding'y datasg ends codesg segment start: mov ax, datasg mov ds, ax mov si, 0 mov cx, 8 s: mov ax, 0[si] ;[0 + si] mov 16[si], ax ;[16 + si] 使用[bx +idata]方式代替di,使程序更简洁 add si, 2 loop s mov ax, 4c00h int 21h codesg ends end start
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
[bx+si]和[bx+di]的含义相似:
- [bx+si]表示一个内存单元,它的偏移地址为(bx)+(si)
- 指令
mov ax, [bx + si]
的含义:将一个内存单元字数据的内容送入ax,段地址在ds中- 该指令也可以写成如下格式:
mov ax, [bx][si]
[bx+si+idata]和[bx+di+idata]:
- [bx+si+idata]表示一个内存单元,它的偏移地址为(bx)+(si)+idata
- 指令
mov ax,[bx+si+idata]
的含义:将一个内存单元字数据的内容送入ax,段地址在ds中不同的寻址方式的灵活应用
[idata]
用一个常量来表示地址,可用于直接定位一个内存单元[bx]
用一个变量来表示内存地址,可用于间接定位一个内存单元[bx+idata]
用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元[bx+si]
用两个变量表示地址[bx+si+idata]
用两个变量和一个常量表示地址;将datasg段中每个单词改为大写字母 assume cs:codesg,ds:datasg,ss:stacksg datasg segment db 'ibm ' ;16 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 ;初始ds:bx ;cx为默认循环计数器,二重循环只有一个计数器,所以外层循环先保存cx值,再恢复,我们采用栈保存 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 ;外层循环的loop指令将cx中的计数值减1 mov ax,4c00H int 21H codesg ends end start 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 ;外层循环的loop指令将cx中的计数值减1 mov ax,4c00H int 21H codesg ends end start
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57