目录
1、普通指令
mov:传送字或字节
add:加法
sub:减法
inc:加1 dec:减1
and:与运算,都为1才为1
or:或运算,都为0才为0
xor:异或运算,多用于加密解密,相同为0不同为1
not:按位取反,单目运算符(只有一个操作数)
SAL:算术左移、SHL:逻辑左移
SAR:算术右移、SHR:逻辑右移
2、JMP指令
3、MOVS指令
4、STOS指令
5、PUSH、POP指令
6、REP指令
7、CALL与RETN指令
1、普通指令
mov:传送字或字节
mov eax,1 -- 将1存入寄存器eax中
lea: 将内存编号存入寄存器
lea左操作数必须是16位或者32位寄存器,右操作数必须是一个内存地址
lea和mov区别在于,mov除了不能从内存到内存,并且左操作数不能是立即数其他都可以
例如:
mov:
lea:
add:加法
add eax,2 -- 将eax中的值加2再放到eax中
sub:减法
sub eax,2 -- 将eax中的值减2再存入eax中
inc:加1 dec:减1
and:与运算,都为1才为1
假设eax=0x1 ebx=0x2
eax:0001 ebx:0010
0001
0010
--------------------
0000 因为上下都为1才为1,所以结果为0
or:或运算,都为0才为0
or eax,ebx
eax=0x1=0001 ebx=0x2=0010
0001
0010
------------------------
0011 上下都为0才为0,所以这里结果为3
xor:异或运算,多用于加密解密,相同为0不同为1
假设eax=0x1=0001 ebx=0x2=0010
0001
0010
----------------------
0011 结果为3
not:按位取反,单目运算符(只有一个操作数)
假设eax=0x1=0001
not eax
0001
1110 结果为14
在这里我使用的是32位的寄存器,所以发生了以下情况
因为我们上面的not eax
eax=0x1=0001 我们是按四位半个字节来看的,但是这里最低操作就是一个字节,所以这里结果是不能等于14的,但是大家知道14是怎么来的就行了
下面我们操作一个字节试试(0x是十六进制前缀)
假设eax=0x11223344 四个字节--两个字
那么后面的0x3344就是ax中的内容,ax是十六位寄存器
ax又可以分为ah(高八位)和al(低八位) (high与low)
ah和al都是一个字节的,这里我们操作al方便观看
假设al=0x1=0000 0001
not al
0000 0001
-----------------------------
1111 1110 结果是FE
SAL:算术左移、SHL:逻辑左移
算术左移和逻辑左移一样都是右边补0: 比如 00101011
算术左移一位:01010110
逻辑左移一位:01010110
对于二进制的数值来说左移n位等于原来的数值乘以2的n次方
比如00011010十进制是26,左移两位后是01101000转成十进制是104恰好是26的4倍。
这种倍数关系只适用于左移后被舍弃的高位不含1的情况,否则会溢出。
这里就不测试了。
SAR:算术右移、SHR:逻辑右移
逻辑右移很简单,只要将二进制数整体右移,左边补0即可
如10101101逻辑右移一位为01010110
算术右移符号位要一起移动,并且在左边补上符号位,也就是如果符号位是1就补1符号位是0就补0
负数的符号位是1、正数的符号位是0
所以算术右移就需要先判断是有符号类型的数值还是无符号类型的
例如:
有符号的情况下:
SAR 10101101,1
结果:01010110
SHR 10101101,1
结果:01010110
有符号的情况下:
SAR 10101101,1
结果:11010110
SHR 10101101,1
结果:01010110
这里就不测试了。
2、JMP指令
JMP指令就是用来修改EIP的值的,我们知道寄存器EIP中存放着下一次将会执行指令的地址,所以我们可以通过JMP指令修改程序下一次执行的内容。
结果如下:
3、MOVS指令
movs通过移动字节数分为movsb、movsd、movsw 分别是byte、dword(双字)、word(字)的缩写。
movs操作到的寄存器就是ESI和EDI
ESI:src 源寄存器
EDI:dst 目标寄存器
movs根据字节大小将源寄存器中的内容对应地址中的内容赋值给目标寄存器中的内容对应地址中的内容
movs byte ptr es:[EDI],byte ptr ds:[ESI] 简称:movsb
movs word ptr es:[EDI],word ptr ds:[ESI] 简称:movsw
movs dword ptr es:[EDI],dword ptr ds:[ESI] 简称:movsd
注意看上面移动的是地址中的值!!!
例如:
我们下面测试中,ESI对应地址中的值始终是0x11223344,EDI对应地址中的值是0
movsb:复制一个字节
执行:
movsw:复制一个字
执行:
movsd:复制双字
执行:
我们可以看到每次操作完esi和edi之后,esi和edi的值都往上加了
这是因为这时候我们的EFL标志寄存器中的DF位是0,如果改成1,那么操作完esi和edi之后,esi和edi中的值就会减,这里就不测试了,知道有这么回事就行。
4、STOS指令
根据字节大小将al/ax/eax中的值存入到[edi]指定的内存单元
STOS BYTE PTR ES:[EDI] 简写为:STOSB
STOS WORD PTR ES:[EDI] 简写为:STOSW
STOS DWORD PTR ES:[EDI] 简写为:STOSD
下面的测试中,我们的eax中始终存放0x11223344:
STOSB:
执行:
STOSW:这里我们修改以下DF位,让EDI被操作之后值减1
执行:
STOSD:
执行:
5、PUSH、POP指令
PUSH是入栈指令,将后方内容压入堆栈中
POP是出栈指令,将后方内容从堆栈中取出
PUSH后面的操作数可以是立即数也可以是寄存器也可以是内存
POP后面的操作数可以是寄存器可以是内存,但不能是立即数,因为数字无法存放内容
例子:
PUSH eax:将eax压入当前堆栈,然后esp栈顶指针-4
执行:
所以一个push将相当于
mov dword ptr ds:[esp-4],eax
sub esp,4
这两个指令
pop ecx
将当前栈顶的内容取出放在ecx里并且栈顶指针+4
如下:
执行:
一个pop就相当于
mov ecx,dword ptr ds:[esp]
add esp,4
6、REP指令
rep指令就是重复执行这个指令多少次,重复的次数次数就是ecx寄存器中的内容
例如:
(这里图片中写错了,ecx中的0x10是16次)
执行:
7、CALL与RETN指令
call指令会跳到对应的地址,并把当前指令下一行的地址压入堆栈
retn会将跳转到当前对战中的地址
call:
注意:这里执行必须F7,至于为什么请观看我另一篇文章《Fake F8》
执行:
一个call相当于:
JMP 401230
mov dword ptr ds:[esp-4],401217
sub esp,4
这三个指令
retn:
执行:
一个retn相当于
jmp dword ptr ds:[esp]
add esp,4
也可以理解为:
pop eax
JMP eax
关于RETN后面加参数的方法可以观看我的另一篇文章《堆栈平衡、外平栈与内平栈》文章来源:https://www.toymoban.com/news/detail-782285.html
总结:以上便是整篇文章的全部内容,整理的这里都是一些常用的汇编指令,并不是所有的,另外当前我也在学习中,还有一些原因导致这篇文章是我赶时间做出来的,如果有错误,希望大佬指正,非常感谢!文章来源地址https://www.toymoban.com/news/detail-782285.html
到了这里,关于【汇编】32位汇编常用的指令的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!