内存寻址方式
内存寻址
目录
内存寻址
可用于内存寻址的寄存器有且仅有:
bx、bp、si、di
即、仅有上述寄存器可放在 [] 中
bx、bp的使用和区别:
- bx 默认使用 ds段
- bp 默认使用 ss段
- 也可显示指定段的方式 更改段地址
处理字符
大小写转换
A: 65 41H 0100 0001
a: 97 61H 0110 0001
大小写之间相差 32,即 2H, 在2进制中,有一位不同
则, 大写转小写:
0100 0001
0010 0000 or
0110 0001
小写转大写:
0110 0001
1101 1111 and
0100 0001
寻址
形式 | 名称 | 特点 | 意义 | 示例 |
---|---|---|---|---|
[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] |
寻址方式 | 含义 | 名称 | 常用格式举例 |
---|---|---|---|
[idata] | EA=idata;SA=(ds) | 直接寻址 | [idata] |
[bx] | EA=(bx);SA=(ds) | ||
[si] | EA=(si);SA=(ds) | 寄存器间接寻址 | [bx] |
[di] | EA=(di);SA=(ds) | ||
[bp] | EA=(bp);SA=(ss) | ||
[bx+idata] | EA=(bx)+idata;SA=(ds) | 用于结构体:[bx].idata | |
[si+idata] | EA=(si)+idata;SA=(ds) | 寄存器相对寻址 | 用于数组:idata[si],idata[di] |
[di+idata] | EA=(di)+idata;SA=(ds) | ||
[bp+idata] | EA=(bp)+idata;SA=(ss) | 用于二维数组:[bx][idata] | |
[bx+si] | EA=(bx)+(si);SA=(ds) | ||
[bx+di] | EA=(bx)+(di);SA=(ds) | 用于二维数组:[bx][si] | |
[bp+si] | EA=(bp)+(si);SA=(ss) | 基址变址寻址 | |
[bp+di] | EA=(bp)+(di);SA=(ss) | ||
[bx+si+idata] | EA=(bx)+(si)+idata; SA=(ds) | 用于表格(结构)中的数组项: [bx].idata[si] | |
[bx+di+idata] | EA=(bx)+(di)+idata; SA=(ds) | 相对基址变址 | 用于二维数组: |
[bp+si+idata] | EA=(bp)+(si)+idata; SA=(ss) | 寻址 | idata[bx][si] |
[bp+di+idata] | EA=(bp)+(di)+idata; SA=(ss) |
[bx + idata] 方式寻址
mov ax,[bx+200]
含义:
- 将一个内存单元的内容 传输给 ax
- 内存单元的长度为 2字节(字单元)
- 段地址在ds中
- 数学化的描述: (ax)=((ds) * 16 + 200 + (bx))
其它写法:
- mov ax, [200+bx]
- mov ax, 200[bx]
- mov ax, [bx].200
si 和 di 变址寄存器
作为 源操作单元 和 目标操作单元 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
assume cs:codesg, ds:datasg
datasg segment
db 'hello world!'
db '............'
datasg ends
codesg segment
start: mov ax,datasg
mov ds,ax
mov si,0
mov di,12
mov cx,6
s: mov ax,[si]
mov [di],ax
add di,2
add si,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
[bx + si] 和 [bx + di]方式 指定地址
本身 表示一个内存单元
指令 mov ax, [bx+si]
含义
- 存入一个内存单元的内容 到 ax
- 内存单元大小为 2字节 (字单元)
- 偏移地址为 bx 和 si 中的数值相加
其它写法:
mov ax,[bx][si]
[bx + si + idata] 和 [bx + di + idata]方式 指定地址
含义、指令含义 同上
指令mov ax, [bx+si+idata]
的其它写法:
mov ax,[bx+200+si]
mov ax,200[bx][si]
mov ax,[bx].200[si]
mov ax,[bx][si].200
多重循环的寻址方式
思路:进入循环时 保存 cx 的值,循环前 恢复 cx 的值
- 使用额外的寄存器 — 强烈不推荐
- 用固定的内存空间 — 不推荐
- 用栈 — 推荐
指令处理数据的长度
- 字操作 word
- 使用寄存器, ax、bx
- 每个寄存器操作长度为 1一个字
- 字节操作 byte
- 使用寄存器 al、ah、bl、bh等
- 操作长度为 1 byte
- 指明操作
- 无寄存器参与运算的情况
- mov word ptr ds:[0],1 字操作
- inc byte ptr [bx] 字节操作
imul
有符号数的乘法
mul
存储原理:被乘数(8位) $\times$ 乘数(8位) = 积(16位)
格式:
- 默认被乘数 8位:al, 16位:ax
- 寄存器乘数
- 8位乘数
mul bl
- 16位乘数
mul bx
- 8位乘数
- 内存单元地址乘数
- 16位乘数
div word ptr [0]
- 8位乘数
div byte ptr [0]
- 16位乘数
8位乘法 | 16位乘法 | |
---|---|---|
被乘数 | AL | AX |
乘数 | 8位内存或寄存器 | 16位内存或寄存器 |
积 | AX | DX(high) + AX(low) |
idiv
有符号数的除法
div
存储原理:被除数(16位) $\div$ 除数(8位) = 商(8位)
格式:
- 默认被除数 16位 (对应8位除数):ax, 32位 (对应16位除数):dx + ax
- 寄存器除数
- 8位除数
div bl
- 16位除数
div bx
- 8位除数
- 内存单元地址除数
- 16位除数
div word ptr [0]
- 8位除数
div byte ptr [0]
- 16位除数
被除数 | AX | DX和AX |
---|---|---|
除数 | 8位内存或寄存器 | 16位内存或寄存器 |
商 | AL | AX |
余数 | AH | DX |
- 被除数16位 ax — 除数8位 bl 或 byte ptr
- 商 al 余 ah
- 被除数32位 dx+ax — 除数 bx 或
- 商 ax 余 dx
- 被除数 dx 存高位、ax存低位
示例:
示例指令 | 被除数 | 除数 | 商 | 余数 |
---|---|---|---|---|
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 | (dx)*10000H+(ax) | (bx) | (ax) | (dx) |
div word ptr es:[0] | (dx)*10000H+(ax) | (es)*16+0 | (ax) | (dx) |
div word ptr [bx+si+8] | (dx)*10000H+(ax) | (es)*16+(bx)+(si)+8 | (ax) | (dx) |
dup 重复数据设置内存
作用: 进行内存数据的批量设置
指令 | 功能 | 相当于 |
---|---|---|
db 3 dup(0) | 定义了3个字节,它们的值都是0 | db 0,0,0 |
db 3 dup(0,1,2) | 定义了9个字节,由0、1、2重复3次构成 | db 0,1,2,0,1,2,0,1,2 |
db 3 dup(‘abc’,’ABC’) | 定义了18个字节,构成’abcABCabcABCabcABC’ | db ‘abcABCabcABCabcABC’ |
dup的使用格式
- db 重复的次数 dup (重复的字节型数据)
- dw 重复的次数 dup (重复的字型数据)
- dd 重复的次数 dup (重复的双字数
其它指令和注意事项
数据段存储
DS 与 CS 的隔了 10H程序段前缀
例如: DS=075A, 数据则存放在076A:0, 即076A0H中
前面的100H中存放PSP(Program Segment Prefix, 即程序段前缀),是一个存储在内存中特定位置的数据结构,DOS 操作系统会在每次加载并执行一个程序时为其分配这个前缀区域。
PSP的介绍
PSP 结构和内存布局:
PSP 是 DOS 为每个加载的可执行程序(如 .COM 文件)创建的数据结构,大小正好是 100H 字节。在这个区域存放了程序执行的控制信息,例如传递给程序的命令行参数,环境变量,文件句柄等等。 因此,当程序被加载时,实际上程序代码从 PSP 之后的 100H 开始。这是一个普遍的规则
字符串存入
1
2
3
4
5
assume cs:codesg, ds:datasg
datasg segment
db 'BaSiC'
db 'MinIx'
datasg ends