【mov指令】
mov指令用于读写寄存器和内存地址空间,有两个地址码,分别指定写入地址与读取地址,寻址方式有3种:立即寻址、寄存器寻址、内存寻址。
(资料图)
● 立即寻址
也称为立即数寻址,写入的数据存储在地址码中,示例:mov ax,99,将99写入ax寄存器,其中99直接存储在地址码中。
立即数可以使用多种进制方式指定,如下:
99,默认为10进制
10B,添加B后缀,表示2进制
67Q,添加Q后缀,表示8进制
0CH,添加H后缀,表示16进制,若第一个数字为字母则需要额外添加前缀0
0xC,添加0x前缀,表示16进制,某些编译器不支持此方式
● 寄存器寻址
要操作的数据存储在寄存器中,示例:mov ax,bx,将bx中的数据写入ax。
● 内存寻址
要操作的数据在内存中,地址码指定数据的偏移地址,段地址默认存储在ds寄存器中,可以在内存与寄存器之间读写数据,也可以将一个立即数写入到内存,但是不能在两个内存地址之间读写数据。
★ 直接内存寻址
直接内存寻址使用一个立即数指定偏移地址,要操作的内存地址不能改变。
示例:
mov ax,[0x404020] ;将0x404020地址处的数据写入ax寄存器,使用ds作为段地址寄存器。
在寄存器与内存之间读写时,处理器默认要读写的数据长度与寄存器长度相同,处理器通过寄存器的长度确定要读写多少个内存单元。
将一个立即数写入内存时,需要在地址码中指定数据的长度,处理器通过操作数类型码确定要写入几个内存单元。
指定数据长度关键词如下:
byte,1字节
word,2字节
dword,4字节
fword,6字节
qword,8字节
示例:
mov byte[0x404020],9 ;将9写入地址0x404020处,占1个存储单元
mov word[0x404020],9 ;占用2个存储单元
以上为nasm编译器语法,masm编译器需要额外添加ptr关键词:byte ptr。
★ 间接内存寻址
地址码中指定一个寄存器,使用寄存器中的数据作为偏移地址,寄存器中的数据也称为指针,意为它指向另一个数据,需要读写其他内存地址时,读写数据指令无需修改,只需要修改指针的值即可。
示例:
mov ax,[bx] ;[]符号内指定一个寄存器,读取寄存器中的数据作为偏移地址
mov ax,[rcx] ;在x86-64中,第二个地址码只能使用32位、64位寄存器
偏移地址也可以使用多个数据组合的方式指定:
mov eax, [rbx+2] ;寄存器+立即数
mov eax, [rbx+rsi] ;寄存器+寄存器
mov eax, [rbx+rsi+2] ;寄存器+寄存器+立即数,两个寄存器长度必须相同
mov eax, [rbx*4+2] ;寄存器×立即数+立即数
mov eax, [rbx*4+rcx] ;寄存器×立即数+寄存器
● 字节序
对于长度超过一字节的数据,需要使用多个存储单元存储,不同处理器对数据字节的排序方式不同,x86处理器规定数据的低位存储在低地址中,高位存储在高地址中,比如 12345678H 需要占用4个存储单元,拆分为 12H、34H、56H、78H 四个字节,78H是低位,放在低地址中,12H放在高地址中,这种排序方式称为小端序,反之则称为大端序。
【读写并运算】
lea指令的原意为将一个指针写入一个寄存器,功能与mov类似,但是lea不能使用内存寻址,只能使用寄存器寻址、立即数寻址。
lea rax,[0x4] ;将一个立即数写入rax,数据放在[]符号内,但这并非表示内存寻址
lea rax,[rbx] ;将rbx中的数据写入rax,在x86-64中不能使用32位以下寄存器
lea的上述功能与mov指令重合,这并非lea的全部使用方式,lea支持读取数据的同时对数据进行运算,比如:lea rax,[rbp+4],rbp中的数据+4写入rax,等同于如下指令的组合:
mov rax, rbp
add rax, 4
lea支持以下数据运算方式:
lea rax, [rbx+2]
lea rax, [rbx+rcx]
lea rax, [rbx+rcx+2]
lea rax, [rbx*4+2]
lea rax, [rcx+rbx*4]
【读写并扩展】
● movzx
movzx指令用于将一个无符号数扩展长度并写入指定寄存器,扩展的长度由写入寄存器的长度决定,具体行为是将扩展后的高位全部使用0填充,需要扩展的数据可以使用寄存器寻址、内存寻址,若使用内存寻址则需要指定数据长度。
movzx ax, al ;al扩展为ax,ax高位全部设置为0
movzx eax, al
movzx eax, ax
movzx eax, bx
movzx rax, byte[0x404020]
movzx不能用于将32位寄存器数据扩展为64位长度,比如 movzx rax,eax 这样是错误的,因为写入eax时rax的高位会清0,无需扩展,直接使用即可,但是写入ax时eax的高位不会清0,这是x86-64与x86的一个区别。
● movsx
movsx指令用于读取并扩展一个有符号数的长度,具体行为是将扩展长度数据的符号位写入扩展后高位的每一位,若是正数,则高位全部使用0填充,若是负数,则高位全部使用1填充,其中最高位的1表示符号位,其余高位的1表示负数补码,将扩展高位全部设置为1即可满足两个补数相加产生进位的规则。
movsx ax, al ;ax的高8位为al的符号位,若al为负数,则ax的高8位全部为1
movsx eax, al
movsx eax, bx
movsx rax, ebx
movsx rax, byte[0x404020]
【数据扩展指令】
数据扩展指令用于将ax系列寄存器中的有符号数扩展长度。
★ cbw
将al寄存器中的8位有符号数扩展为16位,使用ax寄存器存储,al存储低位,ah存储高位,具体行为是将al寄存器中的符号位写入ah的每一位,若al为负数则ah存储负数补码的高8位。
★ cwde
将ax中的16位有符号数扩展为32位,使用eax存储。
★ cdqe
将eax中的32位有符号数扩展为64位,使用rax存储。
★ cwd
将ax中的16位有符号数扩展为32位,使用dx+ax存储,dx存储高位,ax存储低位。
★ cdq
将eax中的32位有符号数扩展为64位,使用edx+eax存储,edx存储高位,eax存储低位。
★ cqo
将rax中的64位有符号数扩展为128位,使用rdx+rax存储,rdx存储高位,rax存储低位。
【数据交换】
xchg指令用于将两个地址码中的数据进行交换,可以使用寄存器寻址、内存寻址,但是不能使用两个内存地址,这一点与mov相同。
xchg ax,bx
xchg ax,[0x404020]
【读写IO地址空间】
● in - 读
in al,0x60 ;读取0x60地址中的数据写入al,只能使用al、ax、eax接收数据,分别表示读取1字节、2字节、4字节
in eax,dx ;可以使用间接寻址,但是只能使用dx寄存器存储IO地址
● out - 写
out 0x60,al
out dx,al
Copyright 2015-2022 东方晨报网 版权所有 备案号:沪ICP备2020036824号-8 联系邮箱:562 66 29@qq.com