4 内存寻址方式
寻址方式分类
- 直接寻址:
mov ax, [0001] - 寄存器间接寻址:
mov ax, [bx] - 寄存器相对寻址:
mov ax, [bx+idata] - 基址变址寻址:
mov ax, [bx+si] - 相对基址变址寻址:
mov ax, [bx+si+idata] - 立即数寻址:
mov ax, 1 - 寄存器寻址:
mov ax, bx
4.1 处理字符问题
汇编语言中,用'xxxxx'的形式指明数据的字符类型,长度为5(没有'\0')
编译器将字符转化为ASCII码
data segment
db 'HelloWorld'
data ends
大小写转换
大写+20H=小写,所有大写字母第六位=0,所有小写字母第六位=1
20H=0010 0000 B
故大写变小写只需要将第6位变1,其余位不变,若本身就是小写经过上述流程还是小写
故有:任意字母 | 0010 0000 = 小写,|表示按位或
同理,任意字母 ^ 1101 1111 = 大写,^表示按位与
在汇编中的表示
and al, 11011111b
表示将al中的字符转为大写
or al, 00100000b
表示将al中的字符转为小写
4.2 [bx+idata]方式寻址
idata是一个数字类型的常量
mov ax, [bx+200]
表示将内存地址位ds:[bx+200]处的内容存入ax中,以下写法等价
mov ax, [200+bx]
mov ax, 200[bx]
mov ax, [bx].200
这个方式可以用作一维数组,idata为0地址
4.3 si,di寄存器寻址
SI,DI作为变址寄存器,和bx的用法功能相近(唯一区别,bx可以分为两个8为寄存器bh+bl)
SI:source index,源变址寄存器;DI:destination index,目标变址寄存器
mov si, 0
mov di, 16
mov cx, 8
s: mov ax, [si]
mov [di], ax
add si, 2
add di, 2
loop s
这个代码实现了将一个16B的字符串从ds:0000移动到ds:0010,每次移动一个字
用[bx+si]和[bx+di]方式寻址
mov ax, [bx+si]
mov ax, [bx][si]
这两个方式等价,两个都是变量,相当于实现了一个二维数组
4.4 [bx+si+idata]和[bx+di+idata]方式寻址
mov ax, [bx+200+si]
mov ax, [200+bx+si]
mov ax, 200[bx][si]
mov ax, [bx].200[si]
mov ax, [bx][si].200
以上写法等价,只有当idata位于第二/三位时,需要.
结构体
使用[bx+idata+si]定位结构体,[bx]定位结构体基地址,.idata定位某一个数据项,[si]定位这个数据的某一个字节(数组的下标)
多重循环次数储存
由于只有一个cx用于存储循环次数,当存在循环嵌套时,会丢失上一次的次数信息
需要将cx保存下来
- 用其他合法寄存器
- 用固定内存空间
- 用栈
推荐第三种
4.5 BP寄存器
BP,Base Pointer,基指针寄存器,于BX类似,区别是不能当成2*8来用,且默认指向SS:BP
只有BX,BP,SI,DI可以在[]中寻址,且只能一个基地址一个变址,不能[BX+BP]或[SI+DI]
4.6 数据的位置
立即数idata
直接保存在指令中
mov ax, 1
add bx, 2000
寄存器
保存在CPU内部的寄存器,使用时不需要外部的dataBus传递
mov ax, bx
内存
保存在内存中
mov ax, [bx] ;ds:[bx]
mov cx, [bp] ;ss:[bp]
4.7 数据的长度
add/mov指令最多只能使用一个内存地址作为操作数,另一个必须是reg或idata
word
涉及到16b寄存器的操作,都是字型
mov ax, 1
mov ds:[0], ax
当不涉及寄存器时,可以用word ptr显式地指出
mov word ptr ds:[0], 1
add word ptr [bx], 2
byte
涉及到8b寄存器的操作,都是字节型
mov al, 1
add bl, [bp]
同理可用byte ptr显式指出
mov byte ptr ds:[0000], 1
add byte ptr [bx], 2
4.8 DIV和MUL指令
在寄存器中使用DIV
mov ax, 1234
mov dx, 0001
mov bx, 0209
div bx
实现了将(dx*10000H+ax)/bx的商存在ax中,将余数存在dx中
实测div ax会将ax作为除数,结果储存不变
mov al, 12
mov ah, 34
mov bl, 23
div bl
实现了将ax/bl的商保存在al中,将余数保存在ah中
当商超过了ax或al的存储范围,结果溢出,程序自动产生一个中断(表现为指令地址跳跃很大的距离)
在内存单元中使用div
data segmemt
dd 100001h ;定义一个double变量,占4B,ds:[0]-ds:[3]为(01,00,10,00)
dw 100h ;定义一个word变量,占2B,ds:[4]-ds:[5]为(00,01)
dw 0h ;定义一个word变量,占2B,ds:[6]-ds:[7]为(00,00),用于存放结果
data ends
code segment
mov ax, data
mov ds, ax ;这两步将ds指向定义的数据段地址
mov ax, ds:[0] ;由于一个寄存器不足以存放dd,用ax存在后四位,一定是后四位
mov dx, ds:[2] ;用dx存放前四位,一定是前四位
div word ptr ds:[4] ;没有寄存器参与,指明类型,这是除数
mov ds:[6], ax ;将商保存在事先定义的结果空间
mov ax, 4c00h
int 21h
code ends
end
MUL指令
与DIV类似
mul bl ;或任意8b寄存器
表示将al*bl的结果存放在ax中
mul bx ;或任意16b寄存器
表示将ax*bx的结果存放在dx,ax中,dx是高位
mul是无符号数的乘法,imul是有符号数的乘法
4.9 使用DUP设置内存空间
和dd,db,dw等伪指令一起使用,定义数据重复次数,这个是给编译器读的
db 3 dup (0) ;db 0,0,0
db 3 dup (0,1,2) ;db 0,1,2,0,1,2,0,1,2
db 3 dup ('abc','ABC') ;db 'abcABCabcABCabcABC'
dup前面跟的是重复的次数
一个典型用法是开辟一个空的数据空间
stack segment
db 200 dup (0)
stack ends
开辟了一个200B的空栈段
数据定义语句
将操作数存入变量名指定的存储单元,或分配空间

还能在定义时计算,如5*20H=A0H