更加灵活的定位内存地址的方法
and
和or
命令
and
指令:逻辑与指令,按位进行与运算
Ex:
mov al,01100011B and al,00111011B
(al) = 00100011B
上第一位为0,下第一为0,0和0做与运算得0
上第三位为1,下第三位为1,1和1做与运算得1
上第四位为1,下第四位为0,1和0做与运算得0
8位全部运算后得到新的数据or
指令:逻辑或指令,按位进行或运算
运算过程与and
指令运算过程类似
以字符形式给出的数据
以'......'
的方式给出的数据是以字符的形式给出的,编译器将它们转化为ASCII码
assume cs:code, ds:data
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
表示定义字节型数据,一个字节占用一个内存单元,偏移量加一
db 'unIX'
相当于db 75H,6EH,49H,58H
,字符与ASCII码相对应
大小写转换的问题
问题:将data中的第一个字符转化为大写,第二个字符转化为小写
分析:
- 小写字母的ASCII码比大写字母的ASCII码大20H,即
小写字母-20H = 大写字母
,大写字母转化为小写字母则相反
但我们尚没有办法使用比较大小相关的指令,所以要另辟蹊径 - 从ASCII码的二进制的形式来看,大写字母与小写字母只有第六位(从右往左)不同
大写字母第六位为0,小写字母第六位为1
即新的方法,只要将一个字母的二进制形式的第六位变为0,它将变成大写,小写同理
使用and
与or
指令可以完成这样的运算
完整程序
assume cs:code,ds:data
data segment
db 'BaSiC'
db 'iNfOrMaTiOn'
data ends'
code segment
start: mov ax,data
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s0: mov al,[bx]
or al,00100000B
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
code ends
end start
[bx+idata]
更加灵活的指明内存单元的方式:[bx+idata]
偏移地址为(bx) + idata
用[bx+idata]的方式进行数组的处理
对于上个问题,两个字符串,一个字符串的起始地址为0,长度为5,另一个字符串的起始地址即为5
可以用[0+bx]
和[5+bx]
来标识两个字符串的第bx个字符
0和5给了两个字符串的起始偏移地址,bx给出了从起始偏移地址开始的相对地址
对上个程序进行简化
mov ax,data
mov ds,ax
mov bx,0
mov cx,5
s: mov al,0[bx] ;[idata+bx]可表示为idata[bx]
and al,11011111b
mov 0[bx],al
mov al,5[bx]
or al,00100000b
mov 5[bx],al
inc bx
loop s
[bx+idata]的方式为高级语言实现数组提供了便利机制
[bx+si+idata]和[bx+di+idata]
SI和DI是8086CPU中和bx功能相近的寄存器
但SI和DI不能够分成两个8位寄存器使用
[bx+si+idata]
表示一个内存单元
它的偏移地址是(bx)+(si)+idata
不同的寻址方式的灵活运用
问题1:将data段中每个单词的头一个字母改成大写字母
assume cs:code,ds:data
data segment
db '1. file ' ;将每个单词定义到一串固定长度的空间内方便地址增加,即换行
db '2. edit '
db '3. search '
db '4. view '
db '5. options '
db '6. help '
data ends
code segment
start:mov ax,data ;将data段地址送入ax中国
mov ds,ax ;经过ax中转,data 段地址被送入ds中
mov bx,0 ;bx即我们即将要访问内存单元要用的偏移地址,初始化为0,此时定位到第一个单词所在的空间
mov cx,6 ;6个单词循环6次
s: mov al,[bx+3] ;bx=0时,bx+3得到3,即偏移量为4,即第一个单词的首字母送入al寄存器中
and al,11011111b ;将第五位变为0即可将字母变为大写
mov [bx+3],al ;将变为大写字母的字符送入字母原来所在的内存单元
add bx,16 ;偏移地址加16即定位到下个单词所在的空间
loop s ;执行下一次循环
code ends
end start
内存单元单元实际上线性顺序排列的,第一个字符占用了16个内存空间即0到15
0到16内第一个单词所在的内存单元为第四个单元即为3,相对于0的偏移量为3
第二个字符在第一个字符的后面,所用的空间即为16到31
而第二个单词所在的位置为19,相对于16的偏移量为3
综上所述,即单词的首字母相对于这个字符的起始地址的偏移量为3
每个字符占用了16个内存单元,所以每个字符的起始地址相差16,即bx迭加16