汇编学习记录1

来源:互联网 发布:mssql存储过程 游标 编辑:程序博客网 时间:2024/06/05 10:56

1.寄存器介绍
寄存器是CPU内部的用于运行中暂存数据的存储单元。 在PC用的16位CPU  8086、8088中,寄存器的名字分别是AX(累加器),BX(基址寄存器),CX(计数寄存器),DX(数据寄存器),SP(堆栈指针),BP(基址指针),SI(源变址寄存器),DI(目的变址寄存器),IP(指令指针),等等……

对于程序,编译器会对其分配一段内存,在逻辑上可以分为代码段,数据段,堆,栈
代码段:保存程序文本,指令指针EIP就是指向代码段,可读可执行不可写
数据段:保存初始化的全局变量和静态变量,可读可写不可执行
BSS:未初始化的全局变量和静态变量
堆(Heap):动态分配内存,向地址增大的方向增长,可读可写可执行
栈(Stack):存放局部变量,函数参数,当前状态,函数调用信息等,向地址减小的方向增长,非常非常重要,可读可写可执行
如图所示

eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。

比方说:add eax,-2 ;   //可以认为是给变量eax加上-2这样的一个值。

这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。

EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。

ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

EDX 则总是被用来放整数除法产生的余数。

ESI/EDI 分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

EBP 是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:

push ebp ; 保存当前ebp
mov ebp,esp ; EBP设为当前堆栈指针
sub esp, xxx ; 预留xxx字节给函数临时变量.
...

这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.

ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。 在32位平台上,ESP每次减少4字节。

esp:寄存器存放当前线程的栈顶指针
ebp:寄存器存放当前线程的栈底指针
eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

寄存器
EAX:累加(Accumulator)寄存器,常用于函数返回值
EBX:基址(Base)寄存器,以它为基址访问内存
ECX:计数器(Counter)寄存器,常用作字符串和循环操作中的计数器
EDX:数据(Data)寄存器,常用于乘除法和I/O指针
ESI:源变址寄存器
DSI:目的变址寄存器
ESP堆栈(Stack)指针寄存器,指向堆栈顶部
EBP基址指针寄存器,指向当前堆栈底部
EIP指令寄存器,指向下一条指令的地址


一般寄存器:AX、BX、CX、DX
AX:累积寄存器,BX:基底寄存器,CX:計数寄存器,DX:資料寄存器

索引寄存器:SI、DI 
SI:來源索引寄存器,DI:目的索引寄存器 

堆叠、基底寄存器:SP、BP 
SP:堆叠指标寄存器,BP:基底指寄存器 

EAX、ECX、EDX、EBX:為ax,bx,cx,dx的延伸,各為32位
ESI、EDI、ESP、EBP:為si,di,sp,bp的延伸,32位


DISP/16:AX(累加器),BX(基址寄存器),CX(计数器),DX(数据与地址寄存器),SP(堆栈指针),BP(基址指针),SI(源变址器),DI(目的变址器)
  DISP/8:AH(8),AL(8),BH,BL,CH,CL.DH,DL
  IP指令指针,存放代码段中的偏移地址;EA偏移地址,段内相对地址,有效地址
  CS代码段,SS堆栈段,DS数据段,ES附加段
  堆栈:方便事项程序要求保留和恢复有关信息的特殊存储部件,是一种数据结构。
  pws(状态):CF(进位),PF(奇偶),SF(符号),OF(溢出),ZF(零),DF(方向),IF(中断),TF(跟踪)
  PA20位物理地址 ;MOV传送

    A,d,c寄存器为调用者寄存器,子进程随便用,B,s,d为被调用者寄存器,用于返回现场。

一、寻址方式

1、立即寻址
  用来表示常数
  MOV AX,1946H;1946H(立即数)-->AX
2
、寄存器寻址
  MOV AX,CX ;cx-->ax 

3、直接寻址
  MOV BX,[1000H] ;[1000H]EA,操作数默认DS
  MOV AX,ES:VAR ;越段前缀
4
、寄存器间接寻址
  EA=BXSIDIBP;∨表示或者
  aPA=DS×16+{BXSIDI}
  bPA=SS×16+BP
  cPA=越段寄存器×16+{BXSIDIBP}
5
、寄存器相对寻址
  直接变址寻址
   BX
  EA=SI+{DISP}
   DI
   BP
  mov ax,count[si] ;ea=count+si,(ea)ax,约定为DS
  mov al,es:string[bp] ;越段前缀
6
、基址变址寻址
  使用数组和表格
  EA={BXBP}+{SIDI}
  pA=DS×16+BX+{SIDI}
  pA=SS×16+BP+{SIDI}
  mov cx,es:[bx][di]
  mov ax,[bx][si] ;ea=bx+si,eaax
7
、相对基址变址寻址
  EA={BXBP}+{SIDI}+{DISP}
  mov ax,array[bx][si] ;ea=array+bx+si,eaax
8
、字符串寻址
  movsb ;([si])=>([di]),si+1=>si,di+1=>di
   ;=>目,可理解为mov [di],[si]

二、进栈时,先减小地址,出栈时,先出,再增加地址。

三、leal S,D;将s的结果放到D中。

LEA: 目标地址传送指令: 将一个近地址指针写入到指定的寄存器。
区别MOV传送指令:MOV传送的是地址所指的内容,而LEA只是地址。

另外,在二进制中,0xCC 对应的就是汇编的:int 3指令(中断).


1. 通用寄存器
通用寄存器包括了8个16/32位的寄存器:AX/EAX、BX/EBX、CX/ECX、DX/EDX、SP/ESP、BP/EBP、DI/EDI及SI/ESI。其中AX/EAX、BX/EBX、CX/ECX、DX/EDX在一般情况下作为通用的数据寄存器,用来暂时存放计算过程中所用到的操作数、结果或其他信息。它们还可分为两个独立的8位寄存器使用,命名为AL、AH、BL、BH、CL、CH、DL和DH。这4个通用数据寄存器除通用功能外,还有如下专门用途:

AX/EAX作为累加器用,所以它是算术运算的主要寄存器。在乘除指令中指定用来存放操作数。另外,所有的I/O指令都使用AX或AL与外部设备传送信息。

BX/EBX在计算存储器地址时,可作为基址寄存器使用。

CX/ECX常用来保存计数值,如在移位指令、循环指令和串处理指令中用作隐含的计数器。DX在作双字长运算时,可把DX和AX组合在一起存放一个双字长数,DX用来存放高16位数据。此外,对某些I/O操作,DX可用来存放I/O的端口地址。

SP/ESP、BP/EBP、SI/ESI、DI/EDI四个16/32位寄存器可以象数据寄存器一样在运算过程中存放操作数,但它们只能以字(16/32位)为单位使用。此外,它们更经常的用途是在存储器寻址时,提供偏移地址。因此,它们可称为指针或变址寄存器。

SP/ESP称为堆栈指针寄存器,用来指出栈顶的偏移地址。

BP/EBP称为基址指针寄存器,在寻址时作为基地址寄存器使用,但它必须与堆栈段寄存器SS联用来确定堆栈段中的存储单元地址。

2、标志寄存器FLAG
条件码标志用来记录程序中运行结果的状态信息,它们是根据有关指令的运行结果由(CPU)自动设置的。由于这些状态信息往往作为后续条件转移指令的转移控制条件,所以称为条件码。
① 进位标志 CF,记录运算时最高有效位产生的进位值。
② 符号标志 SF,记录运算结果的符号。结果为负时置1,否则置0。
③ 零标志  ZF,运算结果为0时ZF位置1,否则置0。
④ 溢出标志 OF,在运算过程中,如操作数超出了机器可表示数的范围称为溢出。溢出时OF位置1,否则置0。
⑤ 辅助进位标志 AF,记录运算时第3位(半个字节)产生的进位值。
⑥ 奇偶标志 PF,用来为机器中传送信息时可能产生的代码出错情况提供检验条件。当结果操作数中1的个数为偶数时置1,否则置0。

********************************************************************************
1、传送指令MOV(move)
********************************************************************************
传送指令是使用最频繁的指令,它相对于高级语言里的赋值语句。指令的格式如下:
MOV Reg/Mem, Reg/Mem/Imm
其中:Reg—Register(寄存器),Mem—Memory(存储器),Imm—Immediate(立即数),它们可以是8位、16位或32位(特别指出其位数的除外)。

********************************************************************************
2、传送—填充指令
********************************************************************************
传送—填充指令是把位数短的源操作数传送给位数长的目的操作数。指令格式如下:
MOVSX/MOVZX Reg/Mem, Reg/Mem/Imm
其中:80386+表示80386及其之后的CPU,其它类似符号含义类同,不再说明。
指令的主要功能和限制与MOV指令类似,不同之处是:在传送时,对目的操作数的高位进行填充。根据其填充方式,又分为:符号填充和零填充。

符号填充指令MOVSX
MOVSX的填充方式是:用源操作数的符号位来填充目的操作数的高位数据位

零填充指令MOVZX
MOVZX的填充方式是:恒用0来填充目的操作数的高位数据位

例如,AL=87H,指令MOVSX CX, AL;MOVZX DX, AL执行后,问CX和DX的值是什么?

根据传送-填充指令的填充方式可知:
指令MOVSX CX, AL执行后,(CX)=0FF87H,指令MOVZX DX, AL执行后,(DX)=0087H。

从上例可看出,两条指令的源操作数完全一样,但因为它们的填充方式不同,所得到的结果而就不同。

********************************************************************************
3、交换指令XCHG
********************************************************************************
交换指令XCHG是两个寄存器,寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同。其指令格式如下:
XCHG Reg/Mem, Reg/Mem

例如,AX=5678H,BX=1234H,指令XCHG AX, BX执行后,AX和BX的值是什么?

这是两个寄存器内容进行交换,指令执行后,有:(AX)=1234H,(BX)=5678H。

********************************************************************************
4、取有效地址指令LEA(Load)
********************************************************************************
指令LEA是把一个内存变量的有效地址送给指定的寄存器。其指令格式如下:
LEA Reg, Mem

********************************************************************************
5、取段寄存器指令
********************************************************************************
该组指令的功能是把内存单元的一个“低字”传送给指令中指定的16位寄存器,把随后的一个“高字”传给相应的段寄存器(DS、ES、FS、GS和SS)。其指令格式如下:
LDS/LES/LFS/LGS/LSS Reg, Mem

********************************************************************************
6、堆栈操作指令
********************************************************************************
堆栈是一个重要的数据结构,它具有“先进后出”的特点,通常用来保存程序的返回地址。它主要有两大类操作:进/压栈操作和出/弹栈操作。

1)、进栈操作

、PUSH
指令格式:PUSH Reg/Mem
PUSH Imm
一个字进栈,系统自动完成两步操作:SP←SP-2,(SP)←操作数;
一个双字进栈,系统自动完成两步操作:ESP←ESP-4,(ESP)←操作数。

、PUSHA
指令格式:PUSHA
其功能是依次把寄存器AX、CX、DX、BX、SP、BP、SI和DI等压栈。

、PUSHAD
指令格式:PUSHAD
其功能是把寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI等压栈。

2)、出栈操作
、POP
指令格式:POP Reg/Mem
弹出一个字,系统自动完成两步操作:操作数←(SP),SP←SP-2;
弹出一个双字,系统自动完成两步操作:操作数←(ESP),ESP←ESP-4。

、POPA
指令格式:POPA
其功能是依次把寄存器DI、SI、BP、SP、BX、DX、CX和AX等弹出栈。其实,程序员不用记住它们的具体顺序,只要与指令PUSHA对称使用就可以了。

、POPAD
指令格式:POPAD
其功能是依次把寄存器EDI、ESI、EBP、ESP、EBX、EDX、ECX和EAX等弹出栈,它与PUSHAD对称使用即可。

********************************************************************************
算术运算指令
********************************************************************************
算术运算指令是反映CPU计算能力的一组指令,也是编程时经常使用的一组指令。它包括:加、减、乘、除及其相关的辅助指令。
该组指令的操作数可以是8位、16位和32位(80386+)。当存储单元是该类指令的操作数时,该操作数的寻址方式可以是任意一种存储单元寻址方式。

1、加法指令

指令的格式:ADD Reg/Mem, Reg/Mem/Imm
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是把源操作数的值加到目的操作数中。

、带进位加指令ADC(见得较少)

指令的格式:ADC Reg/Mem, Reg/Mem/Imm
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是把源操作数和进位标志位CF的值(0/1)一起加到目的操作数中。

、加1指令INC

指令的格式:INC Reg/Mem
受影响的标志位:AF、OF、PF、SF和ZF,不影响CF
指令的功能是把操作数的值加1。

、交换加指令XADD(见得较少)

指令的格式:XADD Reg/Mem, Reg
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是先交换两个操作数的值,再进行算术“加”法操作

2、减法指令

、减法指令SUB

指令的格式:SUB Reg/Mem, Reg/Mem/Imm
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是从目的操作数中减去源操作数。

、带借位减SBB(见得较少)

指令的格式:SBB Reg/Mem, Reg/Mem/Imm
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能是把源操作数和标志位CF的值从目的操作数中一起减去。

、减1指令DEC

指令的格式:DEC Reg/Mem
受影响的标志位:AF、OF、PF、SF和ZF,不影响CF
指令的功能是把操作数的值减去1。

、求补指令NEG

指令的格式:NEG Reg/Mem
受影响的标志位:AF、CF、OF、PF、SF和ZF
指令的功能:操作数=0-操作数,即改变操作数的正负号

3、乘法指令

计算机的乘法指令分为无符号乘法指令和有符号乘法指令,它们的唯一区别就在于:数据的最高位是作为“数值”参与运算,还是作为“符号位”参与运算。

乘法指令的被乘数都是隐含操作数,乘数在指令中显式地写出来。CPU会根据乘数是8位、16位,还是32位操作数,来自动选用被乘数:AL、AX或EAX。

指令的功能是把显式操作数和隐含操作数相乘,并把乘积存入相应的寄存器中。

、无符号数乘法指令MUL/FMUL

指令的格式:MUL Reg/Mem
受影响的标志位:CF和OF(AF、PF、SF和ZF无定义)
指令的功能是把显式操作数和隐含操作数(都作为无符号数)相乘

、有符号数乘法指令IMUL/FIMUL

指令的格式: IMUL Reg/Mem
IMUL Reg, Imm
IMUL Reg, Reg, Imm
IMUL Reg, Reg/Mem

4、除法指令

除法指令的被除数是隐含操作数,除数在指令中显式地写出来。CPU会根据除数是8位、16位,还是32位,来自动选用被除数AX、DX-AX,还是EDX-EAX。

除法指令功能是用显式操作数去除隐含操作数,可得到商和余数。当除数为0,或商超出数据类型所能表示的范围时,系统会自动产生0号中断。

、无符号数除法指令DIV/FDIV

指令的格式:DIV Reg/Mem
指令的功能是用显式操作数去除隐含操作数(都作为无符号数)。指令对标志位的影响无定义。

、有符号数除法指令IDIV/FIDIV

指令的格式:IDIV Reg/Mem
受影响的标志位:AF、CF、OF、PF、SF和ZF

********************************************************************************
逻辑运算指令
********************************************************************************
逻辑运算指令是另一组重要的指令,它包括:逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)和异或指令(XOR),逻辑运算指令也是经常使用的指令。

1、逻辑与操作指令AND

指令的格式:AND Reg/Mem, Reg/Mem/Imm
受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF无定义)
指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑“与操作”,操作结果存入目标操作数中。

2、逻辑或操作指令OR

指令的格式:OR Reg/Mem, Reg/Mem/Imm
受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF无定义)
指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑”或操作”,操作结果存入目标操作数中。

3、逻辑非操作指令NOT

指令的格式:NOT Reg/Mem
其功能是把操作数中的每位变反,即:1←0,0←1。指令的执行不影响任何标志位。

4、逻辑异或操作指令XOR

指令的格式:XOR Reg/Mem, Reg/Mem/Imm
受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF无定义)
指令的功能是把源操作数中的每位二进制与目的操作数中的相应二进制进行逻辑”异或操作”,操作结果存入目标操作数中。

检测位指令TEST

检测位指令是把二个操作数进行逻辑“与”操作,并根据运算结果设置相应的标志位,但并不保存该运算结果,所以,不会改变指令中的操作数。在该指令后,通常用JE、JNE、JZ和JNZ等条件转移指令。

指令的格式:TEST Reg/Mem, Reg/Mem/Imm

受影响的标志位:CF(0)、OF(0)、PF、SF和ZF(AF无定义)

********************************************************************************
循环指令
********************************************************************************
循环指令本身的执行不影响任何标志位。

1、循环指令

循环指令LOOP的一般格式:

LOOP 标号
LOOPW 标号      ;CX作为循环计数器
LOOPD 标号      ;ECX作为循环计数器

….
….
inc eax
dex ebx
cmp eax,ebx
jne/je XXXX ^

求1+2+…+1000之和,并把结果存入AX中。

方法1:因为计数器CX只能递减,所以,可把求和式子改变为:1000+999+…+2+1。

XOR AX, AX
MOV CX, 1000D
again: ADD AX, CX ;计算过程:1000+999+…+2+1
DEC CX
LOOP again

方法2:不用循环计数器进行累加,求和式子仍为:1+2+…+999+1000。

XOR AX, AX
MOV CX, 1000D
MOV BX, 1
again: ADD AX, BX ;计算过程:1+2+…+999+1000
INC BX
LOOP again

从程序段的效果来看:方法1要比方法2好。为什么?^_^

********************************************************************************
转移指令
********************************************************************************
转移指令是汇编语言程序员经常使用的一组指令。在高级语言中,时常有“尽量不要使用转移语句”的劝告,但如果在汇编语言的程序中也尽量不用转移语句,那么该程序要么无法编写,要么没有多少功能,所以,在汇编语言中,不但要使用转移指令,而且还要灵活运用,因为指令系统中有大量的转移指令。

转移指令分无条件转移指令和有条件转移指令两大类。

1、无条件转移指令

无条件转移指令包括:JMP、子程序的调用和返回指令、中断的调用和返回指令等。

下面只介绍无条件转移指令JMP

JMP指令的一般形式:

JMP 标号/Reg/Mem

2、条件转移指令

条件转移指令是一组极其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段。微机的指令系统提供了丰富的条件转移指令来满足各种不同的转移需要,在编程序时,要对它们灵活运用。

条件转移指令又分三大类:基于无符号数的条件转移指令、基于有符号数的条件转移指令和基于特殊算术标志位的条件转移指令。

、无符号数的条件转移指令

指令的助忆符

JE/JZ
ZF=1 Jump Equal or Jump Zero

JNE/JNZ
ZF=0 Jump Not Equal or Jump Not Zero

JA/JNBE
CF=0 and ZF=0 Jump Above or Jump Not Below or Equal

JAE/JNB
CF=0 Jump Above or Equal or Jump Not Below

JB/JNAE
CF=1 Jump Below or Jump Not Above or Equal

JBE/JNA
CF=1 or AF=1 Jump Below or Equal or Jump Not Above

、有符号数的条件转移指令

指令的助忆符

JE/JZ
ZF=1 Jump Equal or Jump Zero

JNE/JNZ
ZF=0 Jump Not Equal or Jump Not Zero

JG/JNLE
ZF=0 and SF=OF Jump Greater or Jump Not Less or Equal

JGE/JNL
SF=OF Jump Greater or Equal or Jump Not Less

JL/JNGE
SF≠OF Jump Less or Jump Not Greater or Equal

JLE/JNG
ZF=1 or SF≠OF Jump Less or Equal or Jump Not Greater

、特殊算术标志位的条件转移指令

指令的助忆符
检测的转移条件 功能描述
JC
CF=1 Jump Carry

JNC
CF=0 Jump Not Carry

JO
OF=1 Jump Overflow

JNO
OF=0 Jump Not Overflow

JP/JPE
PF=1 Jump Parity or Jump Parity Even

JNP/JPO
PF=0 Jump Not Parity or Jump Parity Odd

JS
SF=1 Jump Sign (negative)

JNS
SF=0 Jump No Sign (positive)

例,已知一个字节变量char,试编写一程序段,把其所存的大写字母变成小写字母。

解:
next: …
char DB ‘F’ ;变量说明

MOV AL, char
CMP AL, ‘A’
JB next ;注意:字符是无符号数,不要使用指令JL
CMP AL, ‘Z’
JA next
ADD char, 20

********************************************************************************
子程序的调用和返回指令
********************************************************************************
子程序的调用和返回是一对互逆操作,也是一种特殊的转移操作。
一方面,之所以说是转移,是因为当调用一个子程序时,程序的执行顺序被改变,CPU将转而执行子程序中的指令序列,在这方面,调用子程序的操作含有转移指令的功能,子程序的返回指令的转移特性与此类似;
另一方面,转移指令是一种“一去不复返”的操作,而当子程序完后,还要求CPU能转而执行调用指令之下的指令,它是一种“有去有回”的操作。
为了满足子程序调用和返回操作的特殊性,在指令系统中设置了相应的特定指令。

1、1调用指令(CALL)
调用子程序指令的格式如下:

CALL 子程序名/Reg/Mem

子程序的调用指令分为近(near)调用和远(far)调用。如果被调用子程序的属性是近的,那么,CALL指令将产生一个近调用,它把该指令之后地址的偏移量(用一个字来表示的)压栈,把被调用子程序入口地址的偏移量送给指令指针寄存器IP即可实现执行程序的转移

如果被调用子程序的属性是远的,那么,CALL指令将产生一个远调用。这时,调用指令不仅要把该指令之后地址的偏移量压进栈,而且也要把段寄存器CS的值压进栈。在此之后,再把被调用子程序入口地址的偏移量和段值分别送给IP和CS,这样完成了子程序的远调用操作

00405600 call 00406895
00405604 ……

子程序调用指令本身的执行不影响任何标志位,但子程序体中指令的执行会改变标志位,所以,如果希望子程序的执行不能改变调用指令前后的标志位,那么,就要在子程序的开始处保护标志位,在子程序的返回前恢复标志位。

例如:

CALL DISPLAY
;DISPLAY是子程序名
CALL BX
;BX的内容是子程序的偏移量
CALL WORD1
;WORD1是内存字变量,其值是子程序的偏移量
CALL DWORD1
;DWORD1是双字变量,其值是子程序的偏移量和段值
CALL word ptr [BX]
;BX所指内存字单元的值是子程序的偏移量
CALL dword ptr [BX]
;BX所指内存双字单元的值是子程序的偏移量和段值

1、2返回指令(RET)
当子程序执行完时,需要返回到调用它的程序之中。为实现此功能,指令系统提供了一条专用的返回指令。其格式如下:

RET/RETN/RETF [Imm]

子程序的返回在功能上是子程序调用的逆操作。为了与子程序的远、近调用相对应,子程序的返回也分:远返回和近返回。返回指令在堆栈操作方面是调用指令的逆过程。

五、汇编代码: rep stos dword ptr es:[edi]

在网上查了相关资料显示:
/************************************************************/
lea     edi,[ebp-0C0h] 
mov     ecx,30h 
mov     eax,0CCCCCCCCh 
rep stos dword ptr es:[edi]
rep指令的目的是重复其上面的指令.ECX的值是重复的次数.
STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址.


如果设置了direction flag, 那么edi会在该指令执行后减小, 
如果没有设置direction flag, 那么edi的值会增加.

 

REP可以是任何字符传指令(CMPS, LODS, MOVS, SCAS, STOS)的前缀. 
REP能够引发其后的字符串指令被重复, 只要ecx的值不为0, 重复就会继续. 
每一次字符串指令执行后, ecx的值都会减小.

stos((store into String),意思是把eax的内容拷贝到目的地址。
用法:stos dst,dst是一个目的地址,例如:stos dword ptr es:[edi]。dword ptr前缀告诉stos,一次拷贝双字(4个字节)的数据到目的地址。为什么一次非要拷贝双字呢?这和eax寄存器有关,到底神马关系,慢慢道来。。
执行stos之前必须往eax(32为寄存器)放入要拷贝的数据。上图中,eax的内容是cccccccc,不用说都明白int3中断。
这段代码是初始化堆栈和分配局部变量用的,往分配好的局部变量空间放入int3中断的原因是:防止该空间里的东东被意外执行。

push ebp    ;压入ebp10 mov ebp, esp    ;ebp = esp,保留esp,待函数调用完再恢复,因为函数调用中肯定会用到esp.11 sub esp, 0CCh    ;为该函数留出临时存储区, 堆栈大小为 0CCh12 push ebx;压入ebx13 push esi;压入esi14 push edi;压入edi15 lea edi, [ebp+var_CC]    ;读入[ebp-0C0h]有效地址,即原esp-0C0h,正好是为该函数留出的临时存储区的最低位16 mov ecx, 33h    ;ecx = 30h(48),30h*4 = 0C0h17 mov eax, 0CCCCCCCCh    ;重复在es:[edi]存入30个;0CCCCCCCCh? Debug模式下把Stack上的变量初始化为0xcc,检查未初始化的问题18 rep stosd





http://www.programlife.net/some-basic-knowledge-about-assembly-language.html
http://blog.csdn.net/ypist/article/details/8467163

0 0
原创粉丝点击