作者:bakari 时间:2012.4.21
1、 操作数类型
Imm立即操作数
Reg寄存器操作数
Mem内存操作数
2、 操作数寻址方式
立即数寻址
寄存器数寻址
存储器寻址
3、 数据传送类指令
(重点介绍)mov、xchg、push、pop、lea
(除标志寄存器指令外,其余均不影响标志位)
1.1、 通用数据传送指令
1)、Mov传送指令
两个操作数的尺寸必须是一致的(但movzx和movsx例外)
两个操作数不能同时为内存操作数(内存数据不能直接传送)
指令规则 目的操作数不能为CS、EIP和IP(会覆盖原来其指向的数)
立即数不能直接送段寄存器(不允许:mov DS ,Data)
两个段寄存器之间不能直接传送数据
(其余指令与此类似)
MOVSX:符号扩展
MOVZX:零扩展
8位或16位扩展为32位,两个操作数的尺寸不一致,目的操作数是寄存器
补充:内存内偏移地址的应用 见一段代码:
.data
var1 BYTE 10h
.code
Mov al , var1
方括号:[ ]:可用符号地址代替数值地址(var1是一个符号地址)
.data
Var1 BYTE 10h,20h,30h
.code
Mov al , [var1+2] ;=mov al , var1+2 ;al=30h
2)、交换指令XCHG :
----------------------------见一段指令----------------------
.code
Mov ax,var1
Xchg ax,var2
Mov var2,ax
1.2、 堆栈操作指令(移动地址遵循低对低,高对高的原则)
1)、进栈指令:push指令 ESP指定栈顶的偏移地址
ESP逐渐减少(记忆:把堆栈想象成一个倒扣的桶,栈底是高地址,进栈数据增多ESP下移)
Push指令只表达源操作数,目的操作数在栈顶,由ESP确定。
---------------------见一段代码---------------------
;进栈指令
Push eax ;等同于如下两条指令
Sub esp,4 ;减法指令
Mov [esp],eax ;传送指令
2)出栈指令:pop指令
ESP逐渐增多
源操作数在栈顶由ESP确定,pop指令只表达目的操作数,刚好与push指令相反
----------------------用法见一段指令-----------------
;出栈指令
Pop eax ;等同于如下两条指令
Mov eax , [esp] ;传送指令
Add esp , 4 ;加法指令
-----------------------综合:见一段堆栈操作程序-----------------------
.data
Ten = 10
Dvar DEORD 67762000h , 12345678h
.data
Mov eax , dvar+4 ;eax=12345678h
Push eax ;将eax里的内容压入堆栈
Push DWORD ptr ten ;将立即数以双字量压入堆栈
Push dvar ;将变量的第一个数据压入堆栈
Pop eax ;将栈顶数据弹出到eax
Pop dvar+4 ;栈顶数据弹出到DVAR+4的位置
Mov ebx , dvar+4 ;ebx=0000000AH
Pop ecx ;栈顶数据弹出到ecx
应用堆栈的几点注意以及应用
1、 注意:
-------------由于堆栈的栈顶和内容随着程序的执行不断变化,所以编程时应该注意进栈和出栈的数据要成对,要保持堆栈平衡。
--------------避免16和32为两种传送单位的混用。
2、 应用
-------------堆栈指令、子程序调用指令CALL、子程序反回RET指令、中断调用INT指令、中断返回IRET等指令都会使用堆栈,修改ESP值。
-------------用来存放数据,以便随时恢复它们,使用pop指令时明确栈顶的数据。
-------------可以以随机的方式读取其中的数据,EBP就是以这个目的而设计(见一段代码)
Mov ebp , esp
Mov eax , [ebp+8]
Mov [ebp] , eax
------------利用堆栈实现主程序与子程序间的传递参数
------------还常用于子程序的寄存器保护和恢复,进行快速的现场保护和恢复。
1.3、 其他传送指令
1)、地址传送指令:lEA
-----------------------LEA 的一点重点-----------------------------
-LEA与offset的区别
LEA:CPU的指令,后面课跟标号、常量和表达式
Offset:伪指令,后面只能跟标号和常量
------------见一段代码
Buffer dp 100 dup ( 0 ) ;开辟100个连续字节的的初始化为零的空间
;dp 与WORD,BYTE形式类似
;buffer 类似数组名,指向的是数组的首地址
.code
Lea ebx , buffer ;(送首地址)
Mov ebx , offset buffer ;(送地址)
Mov ebx , buffer ;(送第一个数 零)
Lea ebx , [buffer+50] ;(送地51个地址)
Mov enx ,offset [buffer+50] ;ERROR!(buffer+50已经是地址,offset有送地址,乱套了!)
一般来说:注意:
mov reg , offset XXX 比 Lea reg , XX 的指令长度少一个字节,快一个时钟,但lea更灵活