找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 599|回复: 6

常见汇编语句

[复制链接]

1793

主题

457

回帖

0

积分

管理员

积分
0
发表于 2013-8-15 15:48:03 | 显示全部楼层 |阅读模式
80386  CPU  的寄存器可以分为 8 组:通用寄存器,段寄存器,指令指针寄存器,标志寄
存器,系统地址寄存器,控制寄存器,调试寄存器,测试寄存器,它们的宽度都是 32 位的。
1、通用寄存器
    EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP,             16                 8086      
AX,BX,CX,DX,SI,DI,SP,BP,它们的含义如下:
    EAX:累加器
    EBX:基址寄存器(Base)
    ECX:计数器
    EDX:数据寄存器(Data)
    ESI:源地址指针寄存器(Source)
    EDI:目的地址指针寄存器(Directy)
    EBP:基址指针寄存器(Base)
    ESP:堆栈指针寄存器(Stack)
这些寄存器可以将低 16 位单独存取,也就是 8086 AX,BX,CX,DX,SI,DI,SP,BP,在存取这
些寄存器的低 16 (AX,BX,CX,DX,SI,DI,SP,BP),
们的高 16 位不受影响,同时和 8086 一样对于 AX,BX,CX,DX 这四个寄存器来讲,可以单
独存取它们的高 8 位和低 8 (AH,AL,BH,BL,CH,CL,DH,DL) (High/Low)
    2、段寄存器
除了 8086 4 个段外(CS,DS,ES,SS)80386 还增加了两个段 FSGS,这些段寄存器都是
16 位的,它们的含义如下:
    CS:代码段(CodeSegment)
    DS:数据段(Data Segment)
    ES:附加数据段(ExtraSegment)
    SS:堆栈段(StackSegment)
    FS:附加段
    GS        附加段
    3、指令指针寄存器
    EIP,它的低 16 位就是 8086 IP,它存储的是下一条要执行指令的地址。
    4、标志寄存器
    EFLAGS, 8086 16 位标志寄存器相比,增加了 4 个控制位,不过这 4 个控制位它们在
实模下不起作,这四个控制位分别是:
    IOPL(I/O  Privilege Level),I/O 特权级字段,它的宽度为 2bit,它指定了 I/O 指令的特权级。
如果当前的特权级别在数值上小于或等于 IOPL,那么 I/O 指令可执行。否则,将发生一个
保护性异常。
    NT(Nested Task):控制中断返回指令                           IRET,它宽度为         1       位。NT=0,用堆栈中保存的值恢复
EFLAGSCS EIP 从而实现中断返回;NT=1,则通过任务切换实现中断返回。
    RF(RestartFlag):重启标志,它的宽度是 1 位。它主要控制是否接受调试故障。RF=0 接受,
RF=1 忽略。如果你的程序每一条指令都被成功执行,那么 RF 会被清 0。而当接受到一个非
调试故障时,处理器置 RF=1
    VM(VirtualMachine):虚拟 8086 模式(用软件来模拟 8086 的模式,所以也称虚拟机)VM=0,

file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image001.gif
处理器工作在一般的保护模式下;VM=1,工作在 V8086 模式下。
其它 16 个标志位的含义和 8086 一样,在这里也重温一遍:
    CF(Carry Flag):进位标志位,由 CLC(Clear)STC(Set)两标志位来控制
    PF(ParityFlag):奇偶标志位
    AF(AssistantFlag):辅助进位标志位
    ZF(Zero Flag):零标志位
    SF(SingalFlag):符号标志位
    IF(InterruptFlag):中断允许标志位, CLISTI 两条指令来控制
    DF(DirectionFlag):向量标志位,由 CLDSTD 两条指令来控制
    OF(OverflowFlag):溢出标志位。

1793

主题

457

回帖

0

积分

管理员

积分
0
 楼主| 发表于 2013-8-15 15:48:52 | 显示全部楼层
80386 处理器的寻址方式
在实式模式下,80386 处理器的最大寻址空间仍然为 1M,和 8086/8088 相似。即段地址
*10H+段内偏移地址,从而形成 20 位地址。此种模式下,段基址是 16 的倍数,长度最大不
超过 64K
在保护模式下,80386 处理器可以使用所有的物理内存。段基址可以是 32 位,也可以不
16 的倍数,同时它的最大长度为 4G,这与 8086 完全不同,在形成逻辑地址时用段基址
直接加上段内偏移地址,而并不将段基址左移 4 (乘以 16)。通常情况下,除了访问堆栈外,
默认的段都为 DS,有跨段前缀就另当别论了。在以 BPEBPESP 作为基址寄存器时,这
时默认的段寄存器应该是 SS,举几个简单的例子:
    MOV EAX,[SI];这里的段寄存器是 DS
    MOVEAX,FS:[ESI];这里的段寄存器是 FS,因为指令中使用跨段前缀显示指定了
    MOV EAX,[BP];这里的段寄存器是 SS,因为指令中使用了 BP 作为基址寄存器
    MOVEAX,GS:[BP];这里段寄存器是 GS,因为指令中使用跨段前缀显示指定了
    80386 32 位数的操作的顺序是高高低低,即是说高 16-》高 16,高 8-》高 8,低 16-
16,低 8-》低 8,这和 8086 相似。同时 80386 微处理器兼容所有 8086 的寻址方式,而且
8086 的寻址方式有很大的改进和扩展。在 8086 下,只允许 BPBXSIDI 作为寻址
寄存器,但在 80386 下,8 个通用寄存器都可以作为寻址寄存器。不过有一点要注意的是在
基址变址寄存器寻址方式或相对基址变址寻址方式中,段寄存器由基址寄存器来确定,而不
是由变址寄存器来确定,同时除 ESP 外其它的 7 个通用寄存器都可以作为变址寄存器,用
代码来表示就是:
    MOVEAX,[EBP+ESP+2];这条指令是错误的,因为不可以用 ESP 作为变址寄存器
    MOVEAX,[EBP+ESI+10H];这里的段寄存器应该有基址寄存器来决定。基址寄存器是 BP
那么这里的段寄存就是 SS
    MOVEAX,GS:[EBP+EDI+100H];不用看了,这里的段寄存器应该是 GS,因为指令通过跨
段前缀显示指定了
    80386                                                                                                                                                       支持的基地址+变址+位移量寻址进一步满足了高级语言支持的数据类型。对于                                                                   C
语言来讲,普通变量,数组,结构体,结构体的数组,数组的构体我们既可存放在栈中(
态定义-static definition),也可以存放在堆中(动态定义-dynamicdefinition), ASM 也一样可
以实现。基址变址寄存器提供了两个可以改变的部分,而位移量则是静态的。
80386 8086 的寻址方式差不多完全一样,只不过 80386 的寻址方式更灵活,它的操作数
32 位,16 位,8 位。
8086 的寻址方式:
    a.立即寻址,所谓立即寻址就是操作数就在指令中,比如说:MOVAX,5678H
    b.直接寻址,即直接包含操作数的有效地址 EA,比如说 MOV AX,[1234]
    c. 寄存 器间址寻址,用寄 存器的内容来作 为操作数的有效 地址,比如说   SI=1234,MOV
AX,[SI]8086 下可用的寄存器只有 4 个:BXBPSIDI80386 8 个通用的寄存器都
可以使用。
    d.寄存器相对寻址,即在寄存器间址寻址方式的基础上再加一个位移量,位移量可以是 8
位也可以是 16 位,比如说 MOV AX[BX+90H]

file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image001.gif
    e.基址变址寻址,即操作数的有效地址由一基址寄存器和一变址寄存器产生,如     MOV
AX,[BX+SI]。那么在 8086 下,只有 SIDI 可以作为变址寄存器,在 80386 下除 ESP 外的
其它 7 个通用寄存器都可以作为变址寄存器,比如说 MOV AX,[BX+SI]
    f.                                                                                           e                                                                                                      MOV
AX,[BX+SI+100H]
8086 下,我们如进行字节或字操作,往往要加上伪指令 WORD PTR BYTE  PTR
80386 下不用显示指定,处理器会自动处理,当发现目的操作为 8 位时,处理器就会进行
8 位操作,同理当发现目的操作为 16 位,处理器就会进行 16 位操作,80386 下以目的操作
数的长度为准,以下几条简单的传送指令:
    MOVAL,CS:[EAX];8 位操作,段寄存器是 CS,寻址方式是寄存器间址寻址
    MOVAL,ES:[BX];8 位操作,段寄存器是 ES,寻址方式是寄存器间址寻址
    MOVEDX,[EDX+EBX+1234H];32 位操作,段寄存器是 DS,寻址方式是相对基址变址寻
    MOV AX,[EBX+ESI*4];16位操作,段寄存器是 DS,寻址方式是基址变址寻址
    MOVBH,ES:[EBX+EDI+900H];8 位操作,段寄存器是 ES,寻址方式是相对基址变址寻址
    MOVDL,[EBP+ESI+1900H];8 位操作,段寄存是 SS,因为用了 EBP 作为基址寄存器。寻
址方式是相对基址变址寻址

1793

主题

457

回帖

0

积分

管理员

积分
0
 楼主| 发表于 2013-8-15 15:49:34 | 显示全部楼层
数据传送
80386 的指令集包含了 8086/80888018680286 的指令集,可以分为几个大类:数据传送
指令,算术运算/逻辑运算指令,移位指令,控制转移指令,串操作指令,高级语言支持的
指令,条件字节设置指令,位操作指令,处理器控制指令和保护方式指令。高级语言支持指
令始于 80186,保护方式指令始于 80286,条件字节设置指令和位操作指令是 80386 新增的。
数据传送指令可以分为:通用数据传送,累加器专用传送,地址传送,标志传送
一、数值传送指令   MOV,  MOVZX, MOVSX,  XCHG,  PUSH, PUSHA,  PUSHAD,  POPA,
POPAD
   1MOV,指令和 8086 相似,不过它支持 32 位操作。
   2MOVZX,零扩展传送,格式--MOVZX  DST,SRC,表示将源操作送给目的操作数,目
的操作数空出的部分用 0 填补。
   3MOVSX,符号扩展传送,格式--MOVSX  DST,SRC,表示将源操作送给目的操作数,
目的操作数空出的部分用 SRC 的符号位来填补,举个简单的例子来演示:
   MOV DL,90H;
   MOVSX AX,DL;AX=FF90H
   MOVZX AX,DL;AX=0090H
   MOVSX ESI,DL;ESI=FFFFFF90H
   MOVZX ESI,DL;ESI=00000090H
事实上在 8086 中也有两条指令 CBWCWD 可以对操作数进行扩展。MOVSX 可以对有
符号数进行扩展,MOVZX 可以对无符号数进行扩展,看看 CBWCWD 的用法:
    CBW 将字节数据扩展成字,符号位扩展到 AH
    CWD 将字数据扩展成双字,符号位放到 DX
    MOV AL,70H;
    CBW;//AX=0070
   CWD;//DX=0000,AX=0070
    3XCHG,功能和 8080 相同,不过它支持 8 位,16 位,32 位操作,下面的语句均是合法
的。
    XCHG AH,AL
    XCHG AX,AL
    XCHG ESI,EDI
    XCHGESI,[EBX+EDI+1000H]
    4PUSH,和 8086 不同的是,它支持立即数入栈,8 位入栈,当然还有 32 位入栈,下面
的语句均是合法的。
    PUSH AL
    PUSH BH
    PUSH 100H
    PUSH EAX
    PUSH EBX
    PUSH DWORD PTR[EAX]
    5POP,功能和用法和 8086 一样。
Call EIP + 5


file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image001.gif
Pop eax


Push mem1
Pop mem2
    6PUSHA,将 8 个通用寄存器全部进栈,进栈顺序为:AXCXDXBXSPBPSI
DI,然后 SP 指针寄存减 16,不过 SP 入栈的内容是 PUSHA 指令执行前的内容。
    7POPA8 个通用寄存器全部出栈,堆栈指针寄存器不是堆栈中弹出的内容,而是加 16
而得到的,虽然这样得到的值和从堆栈中弹出来的内容一样
8PUSHAD,将 8 32 位通用寄存器全部入栈,入栈顺序 EAXECXEDXEBX
ESPEBPESIEDIESP 的内容是执行指令 PUSHAD 之前的内容
    9POPAD8 32 位通寄存器全部出栈
二、地址传送指令 LEA, LDS,LES, LFS, LGS, LSS
    1LEA,取有效地址,功能,用法与 8086 相同,不过它支持 32 位操作。规则:目的操
作必须是 16 位或 32 位通用寄存器,当目的操作数是 16 位时,那么只装入有效地址的低 16
位。事实上 LEA 指令相当于伪指令 OFFSET,看例子:
    MOVEAX,12345678H
    MOVEBX,56784321H
    LEAECX,[EAX+EBX];ECX=99999999H
    2LDS,装入指针,功能,用法与 8086 相同,不过它支持 32 位操作。格式:LDSREG,OPRD
规则,目的寄存器必须是 16 位或 32 位的通用寄存器,OPRD 必须是内存单元,不可以是立
即数。如果目的寄存器是 16 位,那么源操作数 OPRD 32 位指针;如果目的寄存器是 32
位,那么源操作数有 48 位指针。该指令将目的操作数 OPRD 所指向的内存单存的 4 个或 6
个连续字节的内容送给助记符指令中指定的 DS 段寄存器和指令中目的寄存器。比如:
    LDS  EAX,[1000H];这表明将偏移地址为 10001001H 这两个字节单元的内容送给段寄存
DS,将偏移地址 1002100310041005 四个字节单元的内容送往 EAX
    LDS AX,[1000H];这表明将偏移地址为 10001001H 这两个字节单元的内容送给段寄存器
DS,将偏移地址 10021003H 两个字节单元的内容送往 EAX
    3LES,同 LDS,不过段寄存器是 ES
    4LFS,同 LDS,不过段寄存器是 FS
    5LGS,同 LDS,不过段寄存器是 GS
    6LSS,同 LDS,不过段寄存器是 SS
三、标志传送指令 LAHF, SAHF,PUSHF, PUSHFD, POPF, POPFD
    1LAHF,将标志寄存器的低 8 位送至 AH 中,包括 SFZFZFPFCF
    2SAHF,与 1 的过程恰好相反
    3PUSHF,将标志寄存器的 EFLAGS 16 位内容入栈,和 8086 相同
    4PUSHFD,将标志寄存器 EFLAGS 的内容入栈
    5POPF,将栈顶的一个字弹出,并将它送到标志寄存器 EFLAGS 的低 16
    6POPFD,将栈顶的两个字弹出,并将它送到标志寄存器 EFLAGS
四、累加器传送指令 IN, OUT,XLAT
    1IN,和 8086 相同,但可以输入一个双字节,同样如果端口的范围位于 00H-FFH,可



file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image001.gif
以直接用,如果超出这个范围,则先要将端口号送至 DX,下面的语句是合法的:
    IN AL,20H; 20H 端口读入一个字节
    IN AX,20H; 20H 端口读入一个字
    MOV DX,378H
    IN EAX,DX; 378H 端口读两个字节
    2OUT,和 8086 相同,但可以输出一个双字节,同样如果端口的范围位于 00H-FFH
可以直接用,如果超出这个范围,则先要将端口号送至 DX,下面的语句是合法的:
    OUT 20H,AL; 20H 端口输出一个字节
    IN 20H,AX; 20H 端口输出一个字
    MOV DX,0378H
    IN EAX,DX; 378H 端口输出两个字
    3XLAT,查表指令,功能和用法与 8086 相同,不过基址寄存器用的是 EBX,来看看 XLAT
的实现过程:XLAT BX 作为基址寄存器,以 AL 作为变址寄存进器对指定的缓冲区进行
查表,将 AL 指定位置的内容送往 AL


1793

主题

457

回帖

0

积分

管理员

积分
0
 楼主| 发表于 2013-8-15 15:51:42 | 显示全部楼层
运算
算术运算指令,逻辑运算指令,移位指令
一、算术运算指令
    1、加减法运算 ADD, ADC, INC, SUB, SBB, DEC, CMP,NEG
    1.1ADD 8086 功能,用法相同,不过支持 32 位操作,下面的语句都是合法的。
    ADD ESIEDI
    ADD EAXDWORD PTR   1000H
    1.2ADC,带进位的加法指令,即 OPRDSOPRDDCF,其中 OPRDS 代表源操作数,
OPRDD 代表目的操作,CF 代表进位标志位,功能和用法与 8086 相同,支持 32 位操作。
    1.3SUB,和 8086 相同,支持 32 位操作。
    1.4SBB,带进位的减法指令,即 OPRDDOPRDSCF,其中 OPRDS 代表源操作数,
OPRDD 代表目的操作数,CF 代表进位标志位,功能和用法与 8086 相同,支持 32 位操作。
    1.5DEC,减 1 操作,功能和用法与 8086 相同,支持 32 位操作。
    1.6CMP,比较操作,功能和用法与 8086 相同,支持 32 位操作。
    1.7NEG,求补操作,功能和用法与 8086 相同,支持 32 位操作。
    1.8INC      1 操作,功能和用法与 8086 相同,支持 32 位操作。
    2、乘除法指令 MUL, DIV, IMUL, IDIV
    2.1MUL,无符号数乘法指令,和 8086 功能用法一样,即指令中只给出一个操作,被乘
数已默认,如果指令给出的操作数是   32  位的话,被乘数默认为   EAX,那么乘积将存放在
EDXEAX 中,其中 EDX 存放高 32 位,EAX 存放低 32 位,如果此时 EDX0,即高 32
位为 0 的话,那么 OF0CF0,否则被置 1。如果指令给出的操数作是 16 位的话,被乘
数默认为 AX 那么乘积将放在 DXAX 中,其中 DX 中将存放高 16 位,AX 中存放低 16
位。如果指令给出的操作数是 8 位的话,被乘数默认为 AL,那么乘积将放在 AXAH 中存
放高 8 位,AL 中存放低 8 位。
    2.2DIV,无符号数的除法指令,和 8086 一样,指令给出一个操作数,被除数已默认。
如果指令中给出的操作数为 32,那么被除数将是 EDXEAX 最终的商将存放在 EAX
数将存放在 EDX 中。如果指令给出操作数为 16 位,那么被除数为 EAX,最终得到的商放
AX,余数放在 EAX 的高 16 位。如果指令中给出的操作数为 8 位,那么被除数是 16 位,
最终得到的商将放在 AL 中,余数放在 AH 中。
    2.3IMUL,有符号数的乘法指令,除了具有 8086 的用法外,有新的形式:
    2.41.IMULDST,SRC;将源操作数 SRC 与目的操作 DST 相乘,并将结果送往 DST
    2.52.IMUL  DST,SRC1,SRC2;将源操作数 SRC1 与源操作数 SRC2 相乘,并将结果送往
DST
使用这种形式必须遵守的规则,形式 c1 指令中目的操作数必须是 16 位或 32 位通寄存器,
源操作数的长度必须与目的操作的长度一样(8 位立即数除外,即 00HFFH 80H7FH)
源操作数可以是通用寄存器,也可以是存储单元或立即数。形式 c2 指令中的源操作数 SRC1
可以是通用寄存器也可以是存储单元,源操作数 SRC2 必须是立即数,DST 必须是 16 位或
32  位通用寄存器。呵呵,对于这些规则无需去问为什么,这是硬件的特性决定的,如果一
定要问为什么,那只能问 INTEL 公司的硬件工程师了。同时,有一点要注意的是:这两种
形式的指令,目的寄存器的长度与源操作数长度一样(8    位立即数除外),这样的话,该指
令事实上对有符号数和无符号数是一样的,因为乘积的低位部分均存储在目的寄存器中,而

file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image001.gif
高位部分在这两种形式的指令中不予以存储。
    2.6IDIV,有符号数的除法指令,用法和 8086 相同,不过支持 32 位操作。
三、符号扩展指令 CBWCWDCWDECDQ
    3.1 CBW,前面已介绍
    3.2 CWD,前面已介绍。
    3.3 CWDE,是 80386 新增的指令。格式:CWDE。功能:将 AX 的符号位扩展到 EAX
16 位中。
    3.4 CDQ,是 80386 新增的指令。格式:CDQ。功能,将 EAX 的符号位扩展到 EDX 中。
    3.5        以上四条指令均不影响标志位。
四、逻辑运算指令和移位指令 NOT,  AND,  OR, XOR, TEST,  SAL, SAR, SHL, SHR, ROL,
ROR, RCL, RCR
    4.1NOT,AND,OR,XOR,TEST 这些指令的功能和用法与 8086 完全相同,不过它们支持 32
位操作。
    4.2 TEST,测试指令,该指令测试的结果并不回送到目的操作数和源操数。之所以要使用
这条的指令,主要是因为根据 TEST 指令得到的结果,进行程序的条件转移。
    4.3 SAL(Left),算术左移,功能和 8086 一样,但在 8086 中,如果在移位的位数超过 1 位,
那么一定要移位的位数放在 CX 寄存器中。在 80386 中,可以不用这样做,其它的移位指令
也一样。除了这一点以外,用法和 8086 一样,当然也支持 32 位操作。以下的语句均是合法
的。
    SHL AL,5;这在 8086 中是非法,但在 80386 中是合法的
    SHL WORD PTR[SI],3
    4.4  SAR(Right),算术右移,将操作数右移指定的位数,但左边的符号位保持不变,移出
的最低位进入 CF 标志位。
    4.5 SHL,逻辑左移,用法和功能与 SAL 一样。
    4.6  SHR,逻辑右移,将操作右移指定的位数,同时每移一位,左边用 0 补充,移出的最
低位进入 CF 标志位。
4.7  说明:SAL, SHL 相当于乘法;SARSHR 相当于除法
    4.8 ROL,循环左移,支持 32 位操作数,用法和 8086 一样。
    4.9 ROR,循环右移,支持 32 位操作数,用法和 8086 一样。
    5.0 RCL,带进位的循环左移,支持 32 位操作数,用法和 8086 一样。
    5.1 RCR,带进位的循环右移,支持 32 位操作数,用法和 8086 一样。
8 的二进制  1000
SAL 1 位之后  16
作业:自己看二进制数据以及汇编相关资料,搞明白,SAL,SHLSARSHRROL
RORRCLRCR 的移位方式。

0

主题

3

回帖

0

积分

新手上路

积分
0
发表于 2013-8-15 18:22:39 | 显示全部楼层
字太小了啊,楼主可否放大一些

1793

主题

457

回帖

0

积分

管理员

积分
0
 楼主| 发表于 2013-8-18 09:44:32 | 显示全部楼层

高级语言支持
高级语言支持指令,开始于   80186,主要是用来简化高级语言的某些特征,总共有   3  条指
:ENTERLEAVEBOUND
一、ENTERLEAVE,建立与释放堆栈框架命令。在 C 语言中,栈不仅用来向函数传递入
口参数,而且在函数内部的局部变量也存放在栈中。为了准确地存取这些局变量和准确
地获得入口参数,就需要建立堆栈框架。
00401050 D>/> \55                          push ebp
00401051     |.    8BEC                      mov ebp,esp                                                       ;    建立堆栈框架
00401053     |.    83EC 4C                sub esp,4C
00401056     |.    53                          push ebx
00401057     |.    56                          push esi
00401058     |.    57                          push edi
00401059     |.    8D7D B4                lea edi,dword ptr ss:[ebp-4C]
0040105C     |.    B9 13000000        mov ecx,13
00401061     |.    B8 CCCCCCCC        mov eax,CCCCCCCC
00401066     |.    F3:AB                    rep stos dword ptr es:[edi]
00401068     |.    C745 FC 070000>mov dwordptr ss:[ebp-4],7                         ;    参数 x
0040106F     |.    C745 F8 080000>mov dwordptr ss:[ebp-8],8                         ;    参数 y
00401076     |.    C745 F4 000000>mov dwordptr ss:[ebp-C],0                         ;    参数 nRet
0040107D     |.    8B45 F8                mov eax,dword ptrss:[ebp-8]                      ;    取第 2 个参数
00401080     |.    50                          push eax                                                             ;    压栈
00401081     |.    8B4D FC                mov ecx,dword ptrss:[ebp-4]                      ;    取第一个参数
00401084     |.    51                          push ecx                                                             ;    压栈
00401085     |.    E8 7BFFFFFF        call Debug.00401005                                        ;    调用函数
0040108A     |.    83C4 08                add esp,8                                                           ;    esp 回归
0040108D     |.    8945 F4                mov dword ptrss:[ebp-C],eax                      ;    返回值放到第 3 个参数
00401090      |.    8B55 F4                mov edx,dword ptrss:[ebp-C]                      ;    交换到寄存器
00401093     |.    52                          push edx                                                             ; /压栈
00401094     |.    68 1C204200        push Debug.0042201C                                        ; |压第 2 个参数
00401099     |.    E8 32000000        call Debug.printf                                            ; \printf
0040109E     |.    83C4 08                add esp,8
004010A1     |.    5F                          pop edi                                                               ;    保持堆栈平衡
004010A2     |.    5E                          pop esi
004010A3     |.    5B                          pop ebx
004010A4     |.    83C4 4C                add esp,4C
004010A7     |.    3BEC                      cmp ebp,esp
004010A9     |.    E8 A2000000        call Debug._chkesp
004010AE     |.    8BE5                      mov esp,ebp                                                       ;    释放栈框架
004010B0     |.    5D                          pop ebp
004010B1     \.    C3                          retn

二、建立栈框架指令 ENTER,格式如下:ENTER  CNT1,CNT2。其中 CNT1 表示框架的大
小,即子程序中需要放在栈中局部变量的字节数;CNT2 是立即数,表示子程序嵌套级别,
即从调用框架复制到当前框架的指针数。在立即数 CNT2 0 时,ENTER 指令的实过程是:
    PUSH EBP
    ESP=>EBP
   ESP<=ESP-CNT1
三、释放栈框架指令 LEAVE,其具体实现过程:
    EBP=>ESP
    POP EBP
四、ENTER LEAVE 指令均不影响标志寄存器中的各标志位,同时 LEAVE 指令只负责释
放栈框架,并不负责函数返回。因此,要在 LEAVE 指令后安排一条返回指令
00401020 D>       C8 020000            enter 2,0
00401024             90                          nop
00401025             90                          nop
00401026             90                          nop
00401027             90                          nop
00401028             90                          nop
00401029             90                          nop
0040102A             90                          nop
0040102B             90                          nop
0040102C              90                          nop
0040102D             90                          nop
0040102E             90                          nop
0040102F             90                          nop
00401030             90                          nop
00401031             90                          nop
00401032             90                          nop
00401033             90                          nop
00401034             90                          nop
00401035             90                          nop
00401036             90                          nop
00401037             90                          nop
00401038     |.    8B45 08                mov eax,dword ptr ss:[ebp+8]
0040103B     |.    0345 0C                add eax,dword ptr ss:[ebp+C]
0040103E             C9                          leave
0040103F             90                          nop
00401040             90                          nop
00401041             90                          nop
00401042             90                          nop
00401043             90                          nop
00401044     \.    C3                          retn


0

主题

8

回帖

0

积分

新手上路

积分
0
发表于 2013-12-3 22:37:54 | 显示全部楼层
这个好 对于初学od 看懂od代码用处很大 收藏了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

果子博客
扫码关注微信公众号

Archiver|手机版|小黑屋|风叶林

GMT+8, 2026-2-1 03:27 , Processed in 0.209557 second(s), 20 queries .

Powered by 风叶林

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表