往期:
[汇编语言笔记篇]二:数据的表示
目录
数据寻址
前论
指令及其操作数
寻址方式
数据寻址的主要方式
立即数寻址
立即数寻址程序
寄存器寻址
寄存器寻址程序
存储器寻址
存储器的逻辑地址
存储器的直接寻址
存储器直接寻址程序
存储器的寄储器间接寻址
存储器的寄存器间接寻址程序-字符串的复制
存储器的寄存器相对寻址
存储器的寄存器相对寻址程序
指令由两部分:操作码和操作数
通过地址访问数据或指令
通过地址查找数据(操作数)
一条指令执行后,确定执行下一条指令的位置
总结:
立即数寻址:数据在指令代码中,用常量表达
寄存器寻址:数据在寄存器中,用寄存器名表示
存储器寻址:数据在主存中,用存储器地址代表
I/O寻址:数据在外设(I/O设备)中,用I/O地址代表
符号:
imm 立即数
i8 8位立即数
i16 16位立即数
i32 32位立即数
首先我们来看一条指令的构成情况
; eg0208.asm in Windows Console
include io32.inc
.data
const = 64
bvar byte 87h,49h
dvar dword 12345678h,12
.code
start:
mov al,12H
mov ah,'d'
labl: mov bx,-1
mov ecx,const
mov edx,const*4/type dvar
mov esi,offset bvar
mov edi,labl
mov bvar,01001100b
mov dvar+4,12h
call disprd
exit 0
end start
分析:
符号:
reg 通用寄存器
r8 8位寄存器
r16 16位寄存器
r32 32位寄存器
例:
; eg0209.asm in Windows Console
include io32.inc
.data
.code
start:
mov al,ah
mov bx,ax
mov ebx,eax
mov dx,ds
mov es,dx
mov al 12
mov bx 12
mov bvar, cl
mov wvar, dx
mov dvar, edx
mov edi,si
exit 0
end start
符号:
mem 存储器操作数
m8 8位存储器单元
m16 16位存储器单元
m32 32位存储器单元
段寄存器指示段基地址
读取指令:代码段CS
堆栈操作:堆栈段SS
读写数据:默认在数据段DS
使用段超越指令前缀(段寄存器名+冒号)
CS: DS: SS: ES: FS: GS:
段寄存器的默认和超越
偏移地址有各种存储器寻址方式计算
这被称为有效地址EA
32位有效地址的组成
例如:
EBX+ESI*4+80h
16位有效地址组成
例如:
BX+SI+80h
有效地址只有位移量部分,直接包含在指令代码中
用变量名(或加中括号)表示偏移地址
形式:
- 变量名
- 变量名 ± n
- [变量名] 变量名[n]
存储器直接寻址示意图:
通过这张图我们可以直观的感受到存储器直接寻址的过程
; eg0210.asm in Windows Console
include io32.inc
.data
bvar byte 87h,49h
dvar dword 12345678h,12
.code
start:
mov cl,bvar
mov edx,dvar
mov bvar+1,dh
mov word ptr dvar+2,dx
mov dvar,87654321h
mov dvar+4,dvar
exit 0
end start
分析:
有效地址存放在寄存器中
寄存器内容 = 偏移地址 = 有效地址
用中括号括起来寄存器表达
注:寄存器间接寻址的数据由另一个操作数的寄存器或变量类型决定
mov [EBX], 100 ;错误 数据类型不明确
解决方法,显示说明即可:
mov word ptr [EBX], 100
; eg0211.asm in Windows Console
include io32.inc
.data
srcmsg byte 'Try your best, why not.'
dstmsg byte sizeof srcmsg dup(?)
.code
start:
mov ecx,lengthof srcmsg ;ECX=字符串字符个数
mov esi,offset srcmsg ;ESI=源字符串首地址
mov edi,offset dstmsg ;EDI=目的字符串首地址
again: mov al,[esi] ;取源串一个字符送AL
mov [edi],al ;将AL传送给目的串
add esi,1 ;源串指针加1,指向下一个字符
add edi,1 ;目的串指针加1,指向下一个字符
loop again ;字符个数ECX减1,不为0,则转到AGAIN标号处执行
mov eax,offset dstmsg ;显示目的字符串内容
call dispmsg
exit 0
end start
分析
srcmsg byte 'Try your best, why not.'
dstmsg byte sizeof srcmsg dup(?)
mov ecx,lengthof srcmsg ;ECX=字符串字符个数
mov esi,offset srcmsg ;ESI=源字符串首地址
mov edi,offset dstmsg ;EDI=目的字符串首地址
mov al,[esi] ;取源串一个字符送AL
mov [edi],al ;将AL传送给目的串
add esi,1 ;源串指针加1,指向下一个字符
add edi,1 ;目的串指针加1,指向下一个字符
again: mov al,[esi] ;取源串一个字符送AL
...
loop again ;字符个数ECX减1,不为0,则转到AGAIN标号处执行
运行结果:
有效地址是寄存器内容与位移量之和
寄存器要用中括号括起
表达形式:
- [ebx+4] 4[ebx] [4][ebx]
- [ebp-08h] [-8h][ebp]
- count[esi] [esi+count] [count][esoi] ;count变量所在的偏移地址用作位移量
相对寻址的位移量一般没有类型,需要依靠另一个操作数确定
如果位移量用变量名表达,则具有变量的类型
注:地址的加减是以主存字节单元为单位
; eg0212.asm in Windows Console
include io32.inc
.data
srcmsg byte 'Try your best, why not.'
dstmsg byte sizeof srcmsg dup(?)
.code
start:
mov ecx,lengthof srcmsg ;ECX=字符串字符个数
mov ebx,0 ;EBX指向首个字符
again: mov al,srcmsg[ebx] ;取源串一个字符送AL
mov dstmsg[ebx],al ;将AL传送给目的串
add ebx,1 ;加1,指向下一个字符
loop again ;字符个数ECX减1,不为0,则转到AGAIN标号处执行
mov eax,offset dstmsg ;显示目的字符串内容
call dispmsg
exit 0
end start
分析
1、
2、寄存器指向字符位置
3、字符传送
4、指向下一个字符
5、逐个传送
运行结果