内存寻址方式
处理字符问题
处理字符问题
汇编程序中,用单引号将字符括起来,编译器在编译过程中将字符转换为对应的ascii码值
ASCII表

解决大小写转换问题
转换原理
1)对比大写A与小写a的ascii码值的二进制形式(其他字符同下述对比过程)
A:0 1 0 0 0 0 0 1
a:0 1 1 0 0 0 0 1
2)经多组对比发现,大写字符与小写字符的区别在于第六位二进制,如果为1,那么该字符为小写,反之为大写
3)因此如果进行大小写转换,可利用 or 和 and 操作符进行操作
如:A变为a
0 1 0 0 0 0 0 1
or 0 0 1 0 0 0 0 0
---------------------
0 1 1 0 0 0 0 1
4)小写变成大写:a变为A
0 1 1 0 0 0 0 1
and1 1 1 0 1 1 1 1 1
---------------------
0 1 0 0 0 0 0 1
汇编实现代码如下
assume cs:code,ds:data
data segment
db 'asdfgh' ;将小写变为大写
db 'ZXCVBN' ;将大写变为小写
data ends
code segment
start:
mov ax,data
mov ds,ax ;初始化数据段的位置
mov ax,0 ;存放临时数据
mov bx,0 ;将偏移量初始化为0
mov cx,6 ;循环六次
l:
mov al,ds:[bx] ;取出数据段数据
and al,11011111b ;进行与运算
mov ds:[bx],al ;将运算结果存入刚刚取出该数据的空间
inc bx ;bx自行加一,向后偏移
loop l
mov cx,6 ;循环六次
ll:
mov al,ds:[bx] ;取出数据段数据
or al,00100000b ;进行或运算
mov ds:[bx],al ;将运算结果存入刚刚取出该数据的空间
inc bx ;bx自行加一,向后偏移
loop ll
mov ax,4c00H
int 21H
code ends
end start

[bx + idata] 方式寻址
含义
1)[bx + idata]表示一个内存单元,它的偏移地址为(bx) + idata(bx中的数值加上idata)
2)mov ax,[bx + 200] 的含义
1)将一个内存单元送入ax
2)这个内存单元的长度为2字节(字单元),存放一个字
3)内存单元的段地址在ds中,偏移地址为200加上bx的数值
4)数学化描述:ax = ((ds)* 16 + 200 + bx)
上述寻址方式的常见写法
1)mov ax,[200 + bx]
2)mov ax,200[bx]
3)mov ax,[bx].200
更改大小写转换代码(前提:同长度字符串)
.....
mov bx,0 ;将偏移量初始化为0
mov cx,6 ;循环六次
l:
mov al,ds:[bx] ;取出数据段数据
and al,11011111b ;进行与运算
mov ds:[bx],al ;将运算结果存入刚刚取出该数据的空间
mov al,ds:[bx + 6] ;取出数据段数据
or al,00100000b ;进行或运算
mov ds:[bx],al ;将运算结果存入刚刚取出该数据的空间
inc bx ;bx自行加一,向后偏移
loop l
.....
SI与DI寄存器(变址寄存器)
BX:通用寄存器,在计算机存储地址时,常作为基址寄存器使用
SI:source index,源变址寄存器
DI:destination index,目标变址寄存器
三种寄存器可实现相同的功能
mov bx,0
mov ax,[bx + 常量]
mov si,0
mov ax,[si + 常量]
mov di,0
mov ax,[di + 常量]
用寄存器SI和DI实现将字符串'welcome to masm!'复制到它后面的数据区中。
assume cs:code,ds:data
data segment
db 'welcome to masm!'
db '................'
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
[si + bx] 与 [di + bx] 寻址方式
下述汇编代码
mov ax,2000H
mov ds,ax
mov bx,1000H
mov si,0
mov ax,[bx + si]
inc si
mov cx,[bx + di]
inc si
mov di,si
mov ax,[bx + di]
对内存的寻址方式
| 形式 | 名称 | 特点 | 意义 | 示例 |
|---|---|---|---|---|
| [idata] | 直接寻址 | 用一个常量/立即数表示地址 | 用于直接定位一个内存单元 | mov ax,[200] |
| [bx] | 寄存器间接寻址 | 用一个变量来表示内存地址 | 用于间接定位一个内存单元 | mov bx,0 mov ax,[bx] |
| [bx + idata] | 寄存器相对寻址 | 用一个变量和常量表示地址 | 可在一个起始地址的基础上用变量间接定位一个内存单元 | mov bx,4 mov ax,[bx + 200] |
| [bx + si] | 基址变址寻址 | 用两个变量表示地址 | mov ax,[bx + si] | |
| [bx + si + idata] | 相对基址,变址寻址 | 用两个变量和一个常量表示地址 | mov ax,[bx + si + 200] |
如果汇编程序中出现了需要双重循环的情况,解决办法如下:
1)利用寄存器保存循环时需要的循环次数
.....
mov cx,4 ;外层循环需要循环四次
waiceng:
mov bx,cx ;将cx中的剩余循环次数放置到bx
mov cx,3 ;内层循环需要循环三次
neiceng:
.....
loop neiceng
mov cx,bx ;将剩余的循环次数放置到cx中进行递减一
loop waiceng
.....
但是该方式必须占用一个寄存器当做存储空间,但是寄存器只有14个(8086CPU),因此占一个寄存器进行存储临时值不现实。
2)用固定的内存空间保存数据
.....
mov cx,4 ;外层循环需要循环四次
waiceng:
mov ds:[40H],cx ;将cx中的剩余循环次数放置到指定内存空间
mov cx,3 ;内层循环需要循环三次
neiceng:
.....
loop neiceng
mov cx,ds:[40H] ;将剩余的循环次数放置到cx中进行递减一
loop waiceng
.....
但是这种情况造成的情况就是,占用的空间位置是固定的,如果该空间被其他程序所占用,那么如果对该空间数值进行更改,可能会造成无法预见的错误。
3)利用栈解决存储
.....
mov cx,4 ;外层循环需要循环四次
waiceng:
push cx ;将cx中的剩余循环次数放置到bx
mov cx,3 ;内层循环需要循环三次
neiceng:
.....
loop neiceng
pop cx ;将剩余的循环次数放置到cx中进行递减一
loop waiceng
.....
该情况较为完美的解决了临时数据的存储
用于寻址的寄存器
寻址寄存器
BX:通用寄存器,在计算机存储地址时,常作为基址寄存器使用
SI:source index,源变址寄存器
DI:destination index,目标变址寄存器
BP:指针寄存器
在[ ]中只能存在上述四种寻址寄存器,而类似 mov cx,[ax] 的指令操作是错误的
四种寄存器可产生的 合法 组合
1)bx + di
2)bx + si
3)bp + di
4)bp + si
bp与bx区别
1)bx默认指向ds段
2)bp默认指向ss段
| 汇编指令 | 数学含义 |
|---|---|
| mov ax,[bp] | ax = ((ss) * 16 + (bp)) |
| mov ax,ds:[bp] | ax = ((ds) * 16 + (bp)) |
| mov ax,es:[bp] | ax = ((es) * 16 + (bp)) |
| mov ax,[bx] | ax = ((ds) * 16 + (bx)) |
| mov ax,ss:[bx] | ax = ((ss) * 16 + (bx)) |
| mov ax,[bp + idata] | ax = ((ss) * 16 + (bp) + idata) |
| mov ax,[bp + si] | ax = ((ss) * 16 + (bx) + (si)) |
| mov ax,[bp + si + idata] | ax = ((ss) * 16 + (bp) + (si) + idata) |
数据在哪里?有多长?
汇编语言中数据位置的表达
1)立即数(idata)
对于直接包含在机器指令中的数据,被称为立即数,数据包含在指令中
2)寄存器
指令要处理的数据在寄存器中,在汇编指令中给出响应的寄存器名称
3)内存:段地址(SA)和偏移地址(EA)
指令要处理的数据在内存中,有SA:EA确定内存单元
汇编语言中指令要处理的数据有多长(8086CPU)
1)字word操作:十六位寄存器,十六位操作
2)字节byte操作:八位的字节操作
在没有寄存器参与的内存单元访问指令中,用word ptr与byte ptr进行标明所要访问的内存房源长度是很必要的,否则cpu无法得知所要访问的单元时字单元还是字节单元。
mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
div指令实现除法
div是除法指令,使用div做除法时
1)被除数:默认放在AX或DX和AX中
2)除数:八位或十六位,在寄存器或内存单元中
3)结果
div指令格式
1)div 寄存器
2)div 内存单元
| 被除数 | AX | DX和AX |
|---|---|---|
| 除数 | 八位内存或寄存器 | 十六位内存或寄存器 |
| 商 | AL | AX |
| 余数 | AH | DX |
dup设置内存空间
功能:dup和db、dw、dd等数据定义伪指令配合使用,用来进行数据的重复。
示例:
| 指令 | 功能 | 等同 |
|---|---|---|
| db 3 dup (0) | 定义了三个字节,值全为0 | db 0,0,0 |
| db 2 dup (0,1,2) | 定义了九个字节,由0、1、2重复三次构成 | db 0,1,2,0,1,2,0,1,2 |
| db 3 dup ('abc','ABC') | 定义了十八个字节,由'abcABC'循环三组构成 | db 'abcABCabcABCabcABC' |
dup使用格式
1)db 重复的次数 dup(重复的字节型数据)
2)dw 重复的次数 dup(重复的字型数据)
3)dd 重复的次数 dup(重复的双字型数据)
实例应用
定义一个200个字节的栈段
db 200 dup (0)
应用于汇编程序
assume cs:code,ds:data
data segment
db 3 dup (0)
db 3 dup (0,1,2)
db 80 dup (0)
db 3 dup ('abc','ABC')
data ends
code segment
mov ax,data
mov ds,ax
mov ax,4c00H
int 21H
code ends

浙公网安备 33010602011771号