汇编语言——更灵活的定位内存地址的方法
Posted 想54256
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编语言——更灵活的定位内存地址的方法相关的知识,希望对你有一定的参考价值。
and和or指令
1、and指令
将2进制中的1当做真,2进制中的0当做假
则:只有2个事件都为真的时候才为真,即1&&1==>1,1&&0==>0,0&&0==>0;
用处:假如想把一个数的第7位变成0,让它和01111111B执行与操作就好了
1 mov al,10001101B ; 8位数据 2 3 add al,01111111B 4 5 >> (al)=00001101B
2、or指令
只要2个事件中有1个是真即为真,即1||1==>1,1||0==>1,0||0==>0;
用处:假如想把一个数的第7位变成1,让它和10000000B执行或操作就好了
mov al,01101101B ; 8位数据 or al,10000000B >> (al)=11101101B
ASCII码
大小写转换
由上图可以得知大写字母的ASCII码比小写字母的ASCII码小32(20H),也就是说大写字母和小写只有第5位不同(大写:0,小写:1)
大写 二进制 小写 二进制 A 01000001 a 01100001 B 01000010 b 01100010 C 01000011 c 01100011 D 01000100 d 01100100
示例:将BaSiC全部变成大写,将iNfOrMaTiOn全部变成小写。
1 assume cs:codesg,ds:datasg 2 datasg segment 3 db \'BaSiC\' ; 0~4内存单元 4 db \'iNfOrMaTiOn\' ; 5~15内存单元 5 datasg ends 6 7 codesg segment 8 start: mov ax,datasg 9 mov ds,ax 10 mov bx,0 11 mov cx,5 ; 循环5次 12 13 ; 将BaSiC全部变成大写 14 s:mov al,[bx] ; 获取相应内存单元的值,赋给al低位寄存器 15 add al,11011111B; 将第5位变成0 16 mov [bx],al ; 将修改后的放回之前的内存单元 17 inc bx ; bx自增1 18 loop s 19 20 mov bx,5 21 mov cx,11 22 ; 将iNfOrMaTiOn全部变成小写 23 s0:mov al,[bx] 24 or al,00100000B ; 将第5位变成0 25 mov [bx],al 26 inc bx 27 loop s0 28 29 codesg ends 30 end start
[bx+idata]
我们可以用[bx]的方式来指明一个内存单元, 我们还可以用一种更为灵活的方式来指明内存单元:
[bx+idata]表示一个内存单元,它的偏移地址为(bx)+idata(bx中的数值加上idata)。
示例:使用[bx+idata],将BaSiC全变小写,将MinIX全变大写
1 assume cs:codesg,ds:datasg 2 datasg segment 3 db \'BaSiC\' ; 内存单元0-4 4 db \'MinIX\' ; 内存单元5-9 5 datasg ends 6 7 codesg segment 8 start: mov ax,datasg 9 mov ds,ax 10 11 mov bx,0 12 mov cx,5 13 14 s:mov al,[bx] 15 or al,00100000B ; 或操作,全变成小写 16 mov [bx],al 17 18 mov bl,[bx+5] 19 and al,11011111B ; 与操作,全变成大写 20 mov [bx+5],al 21 inc bx 22 loop s 23 24 mov ax,4c00H 25 int 21H 26 27 codesg ends 28 end start
SI和DI寄存器
si和di寄存器和ds寄存器的作用一样,都是用来表示内存的偏移地址的。只是SI和DI不能够分成两个8 位寄存器来使用。
我们还可以这样使用它们:[bx+si],[bx+di]和[bx+si+idata],[bx+di+idata],其实和[dx+idata]一样
示例:*****
将datasg段中每个单词改为大写字母
我们很容易就会想到以下代码,因为在第2层循环中修改了cx。等它们跳出第二层循环时cx=0,第一层循环会执行cx=cx-1 ==>-1(FFFF),从而进入死循环
1 assume cs:codesg,ds:datasg 2 datasg segment 3 db \'ibm \' ; 16个字节 0-15 4 db \'dec \' ; 16-31 5 db \'dos \' ; 32-47 6 db \'vax \' ; 48-63 7 datasg ends 8 9 codesg segment 10 start: ; 因为要将每行的每个单词改为大写,所以我们需要写两层循环 11 mov ax,datasg 12 mov ds,ax 13 mov bx 14 mov cx,4 15 s:mov cx,3 16 mov so,0 ; 这个要写在外面 17 s0: 18 mov al,[bx+si] 19 add al,11011111B 20 mov [bx+si],al 21 inc si ; 如果是将bx+1的话,就会1,2,3,13,14,15,...这样,所以我们要用si/di寄存器 22 loop s0 23 24 add bx,16 25 loop s 26 27 mov ax,4c00H 28 int 21H 29 30 codesg ends 31 end start
我们可以采用把cx的值放进其他寄存器中,但寄存器是有限的,当程序过大就不够用了
1 assume cs:codesg,ds:datasg 2 datasg segment 3 db \'ibm \' ; 16个字节 0-15 4 db \'dec \' ; 16-31 5 db \'dos \' ; 32-47 6 db \'vax \' ; 48-63 7 datasg ends 8 9 codesg segment 10 start: 11 mov ax,datasg 12 mov ds,ax 13 mov bx 14 mov cx,4 15 s:mov cx,3 16 mov dx,cx ;;;;;; 用其他寄存器保存一下 17 18 s0:mov si,0 19 mov al,[bx+si] 20 add al,11011111B 21 mov [bx+si],al 22 inc si 23 loop s0 24 25 add bx,16 26 mov cx,dx ;;;;; 将cx取出 27 loop s 28 29 mov ax,4c00H 30 int 21H 31 32 codesg ends 33 end start
然后我们可以把他放进内存中,内存是可以随便用的啊,但当循环多的时候,你需要把所以内存位置都记住。这很不方便
1 assume cs:codesg,ds:datasg 2 datasg segment 3 db \'ibm \' ; 16个字节 0-15 4 db \'dec \' ; 16-31 5 db \'dos \' ; 32-47 6 db \'vax \' ; 48-63 7 dw 0 ;;;;; 定义一个字来保存cx的值(64) 8 datasg ends 9 10 codesg segment 11 start: 12 mov ax,datasg 13 mov ds,ax 14 mov bx,0 15 mov cx,4 16 s:mov cx,3 17 mov [64],cx ;;;;;; 放进字单元中保存一下 18 mov si,0 19 s0: 20 mov al,[bx+si] 21 add al,11011111B 22 mov [bx+si],al 23 inc si 24 loop s0 25 26 add bx,16 27 mov cx,[64] ;;;;; 将cx取出 28 loop s 29 30 mov ax,4c00H 31 int 21H 32 33 codesg ends 34 end start
所以我们要使用栈的方式来进行两层循环的嵌套
这样做的好处是:多层循环嵌套的话,每一层往里面push一个值,等它出来的时候pop的值就是那个,我们只需要管理一个栈就好了,不用管其他的。
1 assume cs:codesg,ds:datasg,ss:stacksg 2 datasg segment 3 db \'ibm \' ; 16个字节 0-15 4 db \'dec \' ; 16-31 5 db \'dos \' ; 32-47 6 db \'vax \' ; 48-63 7 datasg ends 8 9 stacksg segment 10 dw 0,0,0,0,0,0,0,0 ;;;;; 定义一个栈段 11 12 codesg segment 13 start: 14 mov ax,datasg 15 mov ds,ax 16 mov ax,stacksg ;;;;; 保存栈段的位置 17 mov ss,ax ;;;;; 赋值给ss 18 mov sp,16 ;;;;; 指向栈顶 19 mov bx,0 20 mov cx,4 21 s:mov cx,3 22 push cx ;;;;;; 入栈 23 mov si,0 24 s0: 25 mov al,[bx+si] 26 add al,11011111B 27 mov [bx+si],al 28 inc si 29 loop s0 30 31 add bx,16 32 pop cx ;;;;; 出栈 33 loop s 34 35 mov ax,4c00H 36 int 21H 37 38 codesg ends 39 end start
以上是关于汇编语言——更灵活的定位内存地址的方法的主要内容,如果未能解决你的问题,请参考以下文章