目录
5.5、[bx+si+idata]和[bx+di+idata]
5.1、处理字符串问题
1、规定
汇编中用‘……’的方式指明数据是以字符的形式给出的,编译器将把他们转化为相应的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,4c20h
int 21h
code ends
end start
2、大小写转换
逻辑与指令:and dest,src
逻辑或运算:or dest,src
大写转小写:add al,11011111b
小写转大写:or al,00100000b
例如:将BaSic转为全部大写,iNfOrMaTion转小写。
assume cs:code,ds:data
data segment
db 'BaSiC'
db 'iNfOrMaTiOn'
data ends
code segment
start:mov ax,data
mov ds,ax
mov bx,0
mov cx,5
s:mov al,[bx]
and al,11011111b
mov [bx],al
inc bx
loop s
;BaSic
mov bx,5
mov cx,11
s0:mov al,[bx]
or al,00100000b
mov [bx],al
inc bx
loop s0
;iNfOrMaTiOn
mov ax,4c20h
int 21h
code ends
end start
5.2、[bx+idata]方式寻址
1、含义
[bx+idata]表示一个内存单元,它的偏移地址为(bx)+idata
指令mov ax,[bx+200]的含义
将1个长度为2字节的内存单元的内容送入ax
该内存单元的段地址在ds中,偏移地址为200加上bx中的数值。
即:(ax)=((ds)*16+200+(bx))
2、应用
例如:将下列字符串分别改为大写和小写
assume cs:code,ds:data
data segment
db 'StaDIum'
db 'cHicKen'
data ends
code segment
start:mov ax,data
mov ds,ax
mov ax,0
mov bx,0
mov cx,7
s:mov al,[bx]
and al,11011111b
mov [bx],al
mov al,[bx+7]
or al,00100000b
mov [bx+7],al
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
5.3、SI和DI寄存器
1、变址寄存器
SI和DI是8086CPU中和BX功能相近的寄存器,执行与地址有关的操作。
BX:通用寄存器,在计算地址时,常用作基址寄存器用。
SI:源变址寄存器
DI:目标变址寄存器
与bx的区别
SI和DI是纯粹的16位寄存器,
不能分成两个8位寄存器来使用。
2、应用
例如:用寄存器SI和DI实现将字符串"welcome to masm!"复制到它后面的数据区中
源数据起始地址:datasg:0,用ds:si指向要复制的原始字符串
目标数据起始地址:detasg:16,用ds:di指向目的空间
assume cs:code,ds:data
data segment
db'welcome to masm!'
db'0000000000000000'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov di,16
mov cx,8
s:mov ax,[si]
mov [di],ax
add si,2
add di,2
loop s
mov ax,4c00h
int 21h
code ends
end start
5.4、[bx+si]和[bx+di]
1、基址变址寻址方法
[bx+si]表示一个内存单元,偏移地址位(bx)+(si),其中(bx)为基址,(si)为变址。该寻址方式称为基址变址寻址方式。
例如:内存中有数据,2000:1000 BE 00 06 00 00 00 .. .. ..
程序执行后, ax、bx、cx中的内容
(ax)=6h (bx)=1000h (cx)=600h
mov ax,2000H
mov ds,ax
mov bx,1000H
mov si,0
mov ax,[bx+si]
;(ax)=00BEh
inc si
mov cx,[bx+si]
;(cx)=0600h
inc si
;(si)=2
mov di,si
mov ax,[bx+di]
;(ax)=0006h
5.5、[bx+si+idata]和[bx+di+idata]
1、应用
[bx+si+idata]表示一个内存单元
例如:程序中数据:2000:1000 BE 00 06 00 6A 22 00 00
执行程序后,ax,bx,cx中的内容?
mov ax,2000h
mov ds,ax
mov bx,1000h
mov si,0
mov ax,[bx+2+si]
;(ax)=0006h
inc si
mov cx,[bx+2+si]
;(cx)=6a00h
inc si
mov di,si
mov ax,[bx+2+di]
;(ax)=226ah
5.6、不同的寻址方式的灵活运用
1、对内存的寻址方式
2、案例1:灵活应用不同的寻址方式
问题:编程将detasg段中的每个单词的头字母改为大写字母
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,4c00h
int 21h
codesg ends
end start
分析及程序执行结果如下:
根据datasg中的数据的存储结构,采用[bx+idata]方式
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | 1 | . | f | i | l | e | ||||||||||
10 | 2 | . | e | d | i | t | ||||||||||
20 | 3 | . | s | e | a | r | c | h | ||||||||
30 | 4 | . | v | i | e | w | ||||||||||
40 | 5 | . | o | p | t | i | o | n | s | |||||||
50 | 6 | . | h | e | l | p |
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+2]
and al,11011111b
mov [bx+2],al
add bx,16
loop s
mov ax,4c00h
int 21h
codesg ends
end start
3、案例2:灵活应用不同的寻址方式
问题:编程将datasg段中的每个单词改为大写字母。
assume cs:code,ds:data,ss:stack
data segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
data ends
分析及代码执行结果如下:
根据数据在内存中的存储结构,采用[bx+si]方式
二重循环问题的处理——用栈保存数据
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
00 | i | b | m | |||||||||||||
10 | d | e | c | |||||||||||||
20 | d | o | s | |||||||||||||
30 | v | a | x |
assume cs:code,ds:data,ss:stack
data segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
data ends
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,16
mov bx,0
mov cx,4
s:push cx
;将外层循环的cx值压栈
mov cx,3
;设置内层循环次数
mov si,0
s1:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s1
add bx,16
pop cx
;从栈顶弹出外层循环的cx值
loop s
mov ax,4c00h
int 21h
code ends
end start
5.7、寻址方式总结
1、内存的寻址方式(全)
5.8、用于内存寻址的寄存器
1、有哪些寄存器?
BX(base):基址寄存器,常用于地址索引,默认指ds段
BP(base pointer):栈基址指针寄存器,bp默认指ss段
SI(Source Index):源变址寄存器,可用来存放相对于DS段之源变址指针
DI(Destination Index):目的变址寄存器,可用来存放相对于ES 段之目的变址指针。
2、用法
(1)只有bx、bp、si、di可以用在[...]对内存单元寻址。
(2)bx以外的通用寄存器、段寄存器不可以用在[...]中。
(3)dx、bp不能一起用,[bx+bp]格式错误;si、di不能一起用,[si+di]格式错误。
(4)具体含义
5.9、关于数据的两个基本问题
1、处理的数据在什么地方?
1、立即数(idata) | 2、寄存器 | 3、内存:段地址:偏移地址(SA:EA) |
---|---|---|
对于直接包含在机器指令中的数据,称为立即数,数据包含在指令中。 | 指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名。
| 指令要处理的数据在内存中,由SA:EA确定内存单元。 |
2、要处理的数据有多长?
1、字word操作 | 2、字节byte操作 | 3、用word ptr或byte ptr声明 |
---|---|---|
ax、bx | al、bl | mov word ptr ds:[0],1 inc word ptr [bx] mov word ptr ds:[0],1 inc word ptr [bx] |
注释:在没有寄存器参与的内存单元访问指令中,用word ptr或byte ptr显性地指明所访问的内存单元的长度是很必要的,否则,CPU无法得知所要访问的是字单元,还是字节单元。 |
5.10、用div指令实现除法
1、div指令
div是除法指令,使用div作除法的时候
被除数:(默认)放在AX(8位除法)或DX和AX(16位除法)中
除数:8位或16位,在寄存器或内存单元中
div指令格式
div 寄存器
div 内存单元
被除数 | AX | DX和AX | |
除数 | 8位内存或寄存器 | 16位内存或寄存器 | |
结果 | 商 | AL | AX |
余数 | AH | DX |
示例指令 | 被除数 | 除数 | 商 | 余数 |
---|---|---|---|---|
div bl | (ax) | (bl) | (al) | (ah) |
div byte ptr ds:[0] | (ax) | ((ds)*16+0) | (al) | (ah) |
div byte ptr [bx+si+8] | (ax) | ((ds)*16+(bx)+(si)+8) | (al) | (ah) |
div bx | ((ds)*10000H+(ax)) | (bx) | (ax) | (dx) |
div word ptr es:[0] | ((ds)*10000H+(ax)) | ((es)*16+0) | (ax) | (dx) |
div word ptr [bx+si+8] | ((ds)*10000H+(ax)) | ((ds)*16+(bx)+(si)+8) | (ax) | (dx) |
切记提前在默认的寄存器中设置号被除数,且默认寄存器不作别的用处。 |
2、div指令示例
(1)编程:利用除法指令计算100001/100。
分析:100001D=186A1H,使用16位除法;dx与ax联合存放被除数186A1H,bx存放除数100D=64H。
mov dx,1
mov ax,86a1
mov bx,64
div bx
(2)编程:利用除法指令计算1001/100
分析:1001D=3E9H,进行8位除法,存入AX中;BX存放除数100D=64H。
mov ax,3E9
mov bl,64
div bl
3、在内存单元中实施除法
(1)双字型数据的定义
data segment
db 1 ;定义1个字节数据01h,在data:0处,占1个字节空间
dw 1 ;定义1个字数据0001h,在data:1处,占2个字节空间
dd 1 ;定义1个双字数据0000 0001h,在data:3处,占4个字节,或2个字空间
data ends
(2)例如
用div计算data段中的第1个数据除以第2个数据后的结果,商存放在第3个数据的存储单元中。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ds | 10 | 00 | 01 | 00 | 00 | 10 | 00 | |||||||||
100001 | 100 | 0 |
assume cs:code,ds:data
data segment
dd 100001
dw 100
dw 0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,ds:[0]
mov ds,ds:[2]
div word ptr ds:[4]
mov ds:[6],ax
mov ax,4c00h
int 21h
code ends
end start
5.11、用dup设置内存空间
1、dup功能和用法
(1)功能:dup和db、dw、dd等数据定义伪指令配合使用,用来进行数据的重复。
注释:duplicate复制
(2)示例
(3)dup的使用格式
db重复的次数dup(重复的字节型数据)
dw重复的次数dup(重复的字型数据)
dd重复的次数dup(重复的双字型数据)
2、dup用途
示例1:定义1个容量位200个字节的栈空间。
stack segment
db 200 dup(0)
stack ends
示例2:
assume cs:code,ds:data
data segment
db 7 dup(0)
db 3 dup(0,1,2)
db 64 dup(0)
db 3 dup('abcd','ABCD')
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,4c00h
int 21h
code ends
end start