汇编语言zf的标志位中jaz oper zf等于几

&汇编零基础学习&文字教程_江炼伟吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:7贴子:
&汇编零基础学习&文字教程
学会计,到佰平!
需要注意的是汇编不是一种语言,不同平台有不同的汇编语言对应,因为汇编和操作系统平台相关,所以汇编语言没有移植性。对于IA-32架构平台而言,选用的是32位80386汇编语言,也就是说本教程讨论的操作系统平台是32位的,可执行文件的格式也是32位而不是64位或16位的。
实际分析中读者要知道研究的程序是运行在什么平台上,以选择相应的汇编语言,对应IA-32架构而言,IA-16架构的汇编语言原理其实和IA-32的汇编语言一样,学习过16位的80x386汇编语言的读者只需花一点时间就可以转到32位80386汇编语言上。
16位操作系统与32位操作系统的80x86汇编语言主要区别如下:
(1)16位操作系统中的中断调用相当于32位操作系统中的API调用。16位操作系统中的段地址和偏移地址在32位中消失了,在32位操作系统中统一采用平坦的内存地址模式寻址。
(2)16位操作系统中的程序运行在RING0级,也就是说普通程序和操作系统程序运行在同一个级别并且拥有最高权限,而32位操作系统中的程序一般只拥有RING3级运行权限,程序的所有操作都受到操作系统控制,若程序要获得RING0操作特权只能通过驱动程序实现。
(3)16位操作系统的可执行文件格式和32位操作系统的可执行文件格式不同,在32位的Windows操作系统中,可执行文件的格式叫PE格式,32位的Windows操作系统运行在CPU的保护模式之上,而16位的系统则运行在CPU的实模式上。
什么是IA-32?IA-32(Intel Architecture),英特尔体系架构,英特尔从486开始采用,也就叫X86-32架构,在同一时间内可以处理32位二进制数据。CPU的工作宽度是32位。其它公司在软硬方面都兼容此架构,也列属于IA-32架构。
IA-32架构中一共有4个32位寄存器,用于保存临时数据,它们分别是EAX、EBX、ECX和EDX。
这4个32位寄存器的通用寄存器名字前面都有一个“E”字母,含义是“Expand”扩展,这是由于在16位的时代,这4个通用寄存器的名字是AX、BX、CX和DX,到了32位后就在它们的名字前面加个“E”来区别是32位还是16位。
这4个32位的通用寄存器可以当作16位使用,也可以当作8位使用。当作8位使用时,就将AX折开为AH和AL,AH中的“H”代表“high”,意思是高位的意思,AL中的“L”代表“low”,意思是地位的意思。同理,BX、CX和DX可折开为BH、BL、CH、CL、DH、DL来使用。 一些寄存器是别的寄存器的一部分:例如,如果EAX保存了值,这里是其他寄存器的值。EAX 12 782345AX12782345AH12782345ALEA782345
(1)EAX寄存器:EAX称为累加器,常用于算数运算、布尔操作、逻辑操作、返回函数结果等。(2)EBX寄存器:EBX称为基址寄存器,常用于存档内存地址。(3)ECX寄存器:ECX称为计数寄存器,常用于存放循环语句的循环次数,字符串操作中也常用。(4)EDX寄存器:称为数据寄存器,常常和EAX一起使用。 注意:上面所述的4个通用寄存器的专门用途不是一成不变的,编译器在编译程序的时候会根据很多因素,例如编译器、编译条件、操作系统等做出相应的改变,读者要知道着手研究的程序是用什么编译器编译,然后针对具体的编译器参考该编译器的说明。
学会计,到佰平!
EBP和ESP寄存器(1)EBP:EBP称为基址寄存器,可作为通用寄存器用于存放操作数,常用来代替堆栈指针访问堆栈中的数据。(2)ESP:ESP称为堆栈指针寄存器,不可作为通用寄存器使用,ESP存放当前堆栈栈顶的地址,一般情况下,ESP和EBP联合使用来访问函数中的参数和局部变量。 EBP和ESP寄存器的用途:EBP和ESP常配合使用完成堆栈的访问,下面是一段常见的堆栈访问指令。PushebpMovebp,espSubesp,78PushesiPushediCmpdword ptr [ebp+8],0
标志寄存器EFLAGS一共有32位,在这32位中大部分是保留和给编写操作系统的人用的,一般情况下只需知道32位的低16位中的8位即可,图1-3列出了标志寄存器EFLAGS中需要了解的8个位的位置。*OF(Overflow Flag):溢出标志,溢出时为1,否则置0。*DF (Direction Flag):方向标志,在串处理指令中控制信息的方向。*IF (Interrupt Flag) :中断标志*AF (Auxiliary carry Flag) :辅助进位标志,有进位时置1,否则置0。*ZF (Zero Flag) :零标志,运算结构为0时ZF位位置1,否则置0。 *SF (Sign Flag):符号标志,结果为负时置1,否则置0。*CF (Carry Flag): 进位标志,进位时置1,否则置0。*PF (Parity Flag): 奇偶标志。结果操作数中1的个数为偶数时置1,否则置0。
EFLAGS寄存器的用途
正如上面所说EFLAGS是实现条件判断和逻辑判断的一种机制,在汇编语言中一般不直接访问EFLAGS寄存器,而是通过指令的操作隐含访问EFLAGS寄存器,下面是一个利用EFLAGS寄存器的例子。 Cmpdword ptr [ebp+8],0影响标志CF、ZF、SF、OF、AF和PFJz 如果ZF等于1,则跳转到
(1)立即寻址示例:Moveax,56H作用:通 常 用 于赋 值。(2)直接寻址示例:Moveax,[H]作用:通常用于处理变量。(3)寄 存器寻 址示例Moveax,[edi]作用:地址在寄存 器中。(4)寄 存器相对寻址示例MovEAX,[EDI+32H]作用:常用于访问数组和结构。(5)基 址加变址寻址示例MovEAX,[EBP+ESI]作用:常用于访问数组(6)相对基 址加变址寻址。示例MOVEAX,[EBX+EDI-10H]作用:常 用于 访问结 构。
一般高级语言中的数据结构和寻址方式有一定的关系,熟悉这些关系对逆向分析反汇编指令有很大的帮助。表1-1所示为高级语言中的数据结构和80386寻址方式的关系。
观察一下Intel 的80x86 CPU文档手册会发现,Intel的80x86 CPU支持几百条指令,如此多的指令莫说深入研究,连入门恐怕也非易事。
幸运的是,在这几百条的指令中,常用的也不过几十条而已,Intel 的80x86 CPU之所以支持几百条指令,原因在于Intel 的80x86 CPU为了保持向下兼容的问题,所以从过去到现在的所有指令都包含在CPU里面,例如有、8和80386等。 Intel格式和AT&T格式(&在英语里读and)
编写IA-32架构的汇编语言常见有两种格式,一种是Intel格式,另一种是AT&T格式。(1)Intel 格式的指令格式。 指令名称
目标操作数DST,源操作数SRC示例代码:Moveax,[edx]
//将内存地址为EDX的数据放入EAX寄存器Xchgeax,edi
//交换EAX和EDI寄存器的值
Addeax,ebx
// 将EAX和EBX相加,结构放回EAX中Shleax,4
//将EAX逻辑左移4位。(2) AT&T格式的指令格式。 指令名称 源操作数SRC,目标操作数DST示例代码:Mov(%EDX),%EAX
//将内存地址为EDX的数据放入EAX寄存器XCHG%EDI,%EAX
//交换EAX和EDI寄存器的值ADD%EBX,%EAX
//将EAX和EBX相加,结构放回EAX中SHL$4,%EAX
//将EAX逻辑左移4位。本教程中讲解的汇编语言统一采用Intel 格式的汇编格式。下节课介绍在实际中的80386汇编语言常见指令集。
80386的数据传送指令是为了实现CPU和内存、输入/输出端口之间的数据传送。 (3) MOV:称为数值传送指令,格式是“MOV DST,SRC”。(4) MOV指令将源操作数SRC传送到目的操作数DST中,(5)传送的数据格式可以是8字节、16字节和32字节。
示例代码:MOVEAX,56
//将56H立即数传送到EAX寄存器MOVESI,DWROD PTR [EAX*2+1] //将内存地址为EAX*2+1处的4字节数据传送到ESI寄存器。MOVAH,BYTE PTR [ESI*2+EAX]
//将内存地址为ESI*2+EAX处的8位数据传送到AH寄存器。MOVDWORD PTR [ESP+36],EBX
//将EBX寄存器的值以4字节传送到堆栈地址为ESP+36所指向的地方。
(6) XCHG:称为交换指令,XCHG实现寄存器间和内存间的数据交换。格式是“XCHG DST,SRC”。XCHG指令交换SRC和DST之间的数据,交换的数据可以是8字节、16字节和32字节,其中SRC和DST必须格式相同。 示例代码:XCHGEAX,EDX
//将EDX寄存器的值和EAX寄存器的值交换XCHG[ESP-55],EDI //将EDI寄存器的值和堆栈地址为[esp-55]处的值交换。XCHGBH,BL
//将BL寄存器和BH寄存器的值交换。
PUSH和POP:称为压入堆栈指令和弹出堆栈指令,格式是“PUSH SRC(源操作数)”和“POPDST(目的操作数)”。PUSH指令和POP指令是匹配出现的,上面的代码有多少个PUSH下面的代码就有多少个POP,否则堆栈就会不平衡。  PUSH指令将源操作数SRC压入堆栈,同时ESP-4,而POP恰恰相反,POP指令从堆栈的顶部弹出4字节的数值然后放入DST。在32位的Windows操作系统上,PUSH和POP指令的操作是以4字节为单位的。  PUSH和POP指令常用于向函数传递参数。  示例代码: PUSHEAX //将EAX寄存器的值以4字节压入堆栈,同时ESP-4PUSHDWORD PTR [12FF8589] //将内存地址为12FF8589所指向的值以4字节压入堆栈,同时ESP-4-------------------------POPDWORD PTR [12FF8589] //将堆栈顶部的4字节弹出到内存地址为12FF8589所指地方,同时ESP+4POPEAX
//将堆栈顶部的4字节弹出到EAX寄存器,同时ESP+4
80x86有3条地址传送指令,分别是LEA,LDS和LES。其实LDS和LES指令和段寄存器有关,在32位的Windows操作系统上,一般的程序员都不需要管理段寄存器,所以相对而言,LDS和LES寄存器使用得比较少,一般情况下常见的只有LEA指令。
LEA:称为地址传送指令,格式是“LEADST,ADDR”。LEA指令将ADDR地址加载到DST,其中ADDR可以是内存,也可以是寄存器,而DST必须是一个通用寄存器。
LEA指令相当于C语言中的“&”and操作符,需要注意的是LEA和MOV是不同的,前者传送的是地址,后者传送的是操作数。
示例代码: LEAEAX,[]MOVEAX,[]//指令执行后EAX寄存器的值为H,而MOVEAX,[] 指令执行后EAX寄存器的值为内存地址指向的那个数值。 还有一点需要注意LEA指令可用于算法运算。示例代码:LEAECX,[ECX+EAX*4]
//ECX=ECX+EAX*4
80x86提供了8条加减法指令:ADD、ADC、SUB、SBB、INC、DEC、CMP和NEG,4条乘除法指令:MUL、IMUL、DIV和IDIV。 (1)常用的加减法指令。1.ADD:称为加法指令,格式是“add OPER1,OPER2”。(操作数(operand))ADD指令将OPER1+OPER2结果存放在OPER1中。 示例代码:ADDEAX,ESI //将EAX寄存器的值加上ESI寄存器的值,得出的结果保存在EAX寄存器中。ADDEBX,DWORD PTR [] //将EBX寄存器的值加上内存地址为所指的4字节值,得出的结构保存在EBX寄存器中,其中DWORD PTR的意思是显示说明按多少字节来操作,DWORD是DOUBLE WORD的缩写,也就是两个WORD的意思。
不同的平台和编译器中,DWORD占用的字节数不同,在32位的Windows中一个WORD占用16字节空间,DWORD占用32字节空间,读者可以在32位的Windows平台上使用Visual C++编译器编写C语言Printf(&%d&,sizeof(DWORD))来验证。  在汇编语言中常用的还有WORD PTR和BYTE PTR,表示的意思分别是按WORD来操作和按BYTE来操作。 (7) SUB:称为减法指令,格式是“SUB OPER1,OPER2”。SUB指令将OPER1-OPER2结果存放在OPER1中。 示例代码:SUBECX,4H
//将ECX寄存器的值减去4H,得出的结果保存在EAX寄存器中。SUBBYTE PTR[EAX],CH //将内存地址为EAX所指向的数据按字节为单位和CH寄存器相减,得出的结果按字节为单位保存在EAX所指向的地方。 INC:称为加1指令,格式是“INC OPER”。INC指令将操作数OPER加1,得出的结果保存在OPER中。 示例代码:INCEAX //将EAX寄存器的值加1,得出的结果存放在原来的地方。INCWORD PTR [EBX+2] //将内存地址为EBX+2的数据按WORD为单位加1,得出的结果存放在原来的地方。 DEC:称为减1指令,格式是“EDC OPER”。DEC指令将操作数OPER减1,得出的结果保存在OPER中。 示例代码:DECEDX //将EDX寄存器的值减1,得出的结果存放在原来的地方DECDWORD PTR [EBP+36] //将堆栈地址为EBP+36的数据按DWORD为单位减1,得出的结果存放在原来的地方。 DIV:称为除法指令,格式是“DIV OPER”。DIV指令将64位(EDX和EAX)或32位(EAX)的值除以OPER,得出的商保存在EAX寄存器中,而余数则保存在EDX寄存器中,由OPER操作数决定按多少字节操作。 示例代码:DIVECX //将EAX寄存器的值按4字节为单位除以ECX寄存器的值,得出的结果商保存在EAX寄存器中,余数保存在EDX寄存器中。DIVWORD PTR [ESP+36] //将EAX寄存器的值按WORD为单位除以堆栈地址为ESP+36所指向的数据,得出的结果商保存在EAX寄存器中,余数保存在EDX寄存器中。 IDIV:称为有符号除法指令,原理和操作可以参考DIV指令,IDIV和DIV的区别是IDIV将参与运算的操作数当成有符号数来处理。
moveax,1000cwddivecx 1000(H)/7=5.1 CWD是汇编语言中的字扩展指令,它的功能是将一个字型变量扩展为双字型变量,即Change Word to Double word。
80x86提供了OR、AND、NOT/XOR和TEST这5条逻辑运算指令,逻辑运算指令是数据加密/解密的基础,所以应该熟练掌握它们的用法。 (1)OR:称为或操作指令,格式是“OR OPER1,OPER2”。OR指令将OPER1操作数和OPER2操作数进行或运算,得出的结果保存在OPER1中。
OR指令主要用于维持某个二进制的某些位的值不变,而另一些位设置为1的情况。把不需要改变的位用0进行或运算,把要设置为1的位用1进行或运算即可。
示例代码:OREAX,H
//将EAX寄存器和立即数H进行或运算,实际上是将EAX寄存器的31位和15位置1ORAH,BH
//将AH寄存器或BH寄存器进行或运算。 EAX=1C1EA4OREAX,H得到:eax=801C9EA4 AH=1BH=2
1 二进制 0001Or
2 二进制 0010
0011(也就是10进制3)因为第一位是1,第二位是0,而第二个数的第一位是0第二位是1根据 or计算原理.1 or 0=1,0 or 0=0,0 or 1=1,1 or 1=1的原理得到的就是0011 (2) AND:称为与操作指令,格式是“AND OPER1,OPER2”。AND指令将OPER1操作数和OPER2操作数进行与运算,得出的结果保存在OPER1中。
AND指令主要用于维持某个二进制数的某些位的值不变,而另一些位设置为0的情况。把不需要改变的位用1进行与运算,把要设置为0的位用0进行与运算即可。
示例代码:ANDCH,80H //将CH寄存器的值和80H进行与运算,实际上是将CH寄存器的第7位保存不变,其余位置0.ANDDWORD PTR [EAX],H //将内存地址为EAX所指向的数据按DWORD为单位与H进行与运算,实际上是将内存地址为EAX指向的4字节数据的第31位和15位置保存不变,其余位置0. ANDCH,80HCH=1
二进制   80 二进制 And
根据 and计算原理 0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是 ANDDWORD PTR [EAX],HEAX=001C1EA4001C1EC8
(十六进制就是)根据 and计算原理 0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是 (3) NOT:称为取反指令,格式是“NOT OPER”。NOT 指令将OPER操作数取反。注意NOT和NEG不同,NOT指令是按位取反,NEG是求补,意即将0减去操作数。例如:
15H的二进制为
0 0 0 1 0 1 0 1 B NEG
15H的二进制为 1 1 1 0 1 0 1 1 B NOT
15H的二进制为 1 1 1 0 1 0 1 0 B 根据 NOT计算原理 0 not 1, 1 not 0
得 1 1 1 0 1 0 1 0
执行后就是用FFFFFFFF-1=FFFFFFFE
(1) XOR:称为异或操作指令,格式是“XOR OPER1,OPER2”。XOR指令将OPER1操作数和OPER2操作数进行异或运算,得出的结果保存在OPER1中。 XOR指令主要用于维持某个二进制数的某些位的值不变,而某些位取反的情况。把不需要改变的位用0进行异或运算,把需要取反的位用1进行异或运算即可。 示例代码:XOREAX,FFFF0000H //将EAX寄存器的值和立即数FFFF0000H进行异或运算,实际上将EAX寄存器的值的高16位取反,低16位保存不变。XORAH,F0H
//将AH寄存器的值和立即数F0F0H进行异或运算,实际上是将AH寄存器的值的第15位和7位取反,其余位保持不变。 EAX=001C1EA4001C1EA4_0100100FFFF0
_ (十六进制:FFE31EA4)根据 XOR 计算原理:0 xor 0 =0, 1 xor 1 =0,1 xor 0 =1 得到:FFE31EA4 XORAH,F0HAH=50_
(A0十六进制)根据 XOR 计算原理:0 xor 0 =0, 1 xor 1 =0,1 xor 0 =1 得到:A0
(2) TEST:称为测试指令,格式是“TEST OPER1,OPER2”。TEST指令将OPER1操作数和OPER2操作数进行与运算,不保存结果,只设置标志寄存器EFLAGS相应的标志位的值。 TEST指令常用于测试一个二进制位的某些位是否为1,但不改变源操作数的情况。 示例代码:TESTEAX,F0000000H
//将EAX寄存器的值和立即数FH进行与运算,实际上是测试EAX寄存器的第31、30、29、28位是否为1,并且设置标志寄存器EFLAGS相应的标志位的值。
TESTEAX,F0000000HEAX=001C1EA4001C1EA4_F
根据 and计算原理 0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是 080x86有4条普通移位指令和4条循环移位指令,它们都隐含地使用CF寄存器参与运算。
(7)普通移位指令。SAL算术左移指令、SAR算术右移指令、SHL逻辑左移指令和SHR逻辑右移指令。 这4条普通移位指令的格式都是一样的:普通移位指令名称 OPER1,OPER2,其中OPER1可以是寄存器或内存,OPER2代表的是移位的位数。其中SAL指令和SHL指令指向结果是一样的。 对于有符号和无符号数而言,SAL算术左移指令和SHL逻辑左移指令每移动一位相当于乘以2.而SAR算术右移指令和SHR逻辑右移指令有点不同。对于有符号和无符号而言,SAR算术右移指令每移动一位相当于除以2,而SHR逻辑右移指令不管操作数是有符号数还是无符号数,每向右移动一位,左边都是用0填充,所以当操作数是无符号数的时候,SHR逻辑右移指令每移动一位才等于除以2. 示例代码:SALEAX,2 //将EAX寄存器的值向左移动2位,得出的结果保存在EAX寄存器中,相当于EAX=EAX*4SARDWORD PTR DS:[ESI],4 //将内存地址为ESI所指向的数据按DWORD为单位右移4位,相当于将内存地址为ESI所指向的数据按DWORD为单位的数据除以2*2*2*2=16(十进制)SHLDWORD PTR [EBP+2H],2 //将堆栈地址为EBP+2H所指向的数据按DWORD为单位左移2位,相当于将内存地址为EBP+2H所指向的数据按DWORD为单位的数据乘以4.SHREDI,4
//将EDI寄存器的值逻辑右移ECX位。EDI值除以2*2*2*2=16(十进制)
循环移位指令ROL左循环移位指令、ROR右循环移位指令、RCL带进位左循环移位指令和RCR带进位右循环移位指令。 这4条循环移位指令的格式都是一样的:循环移位指令名称 OPER1,OPER2,其中OPER1可以是寄存器或内存,OPER2要么是CL寄存器要么是1,代表移动的次数,如果要移的次数多于1次,则需要把移位次数存放在CL寄存器中。 ROL、ROR和RCL、RCR的区别是前者没有将标志寄存器EFLAGS的CF进位标志包含参与循环移位,后者则把CF进位标志包含参与循环移位。 示例代码: ROLAL,1
//将EAX寄存器的值向左移动一位,被移出的位送到CF,同时将被移出的位放到最低位。ROREAX,CL
//将EAX寄存器的值向右移动CL位,被移出的位送到CF,同时将被移出的位放到最高位。RCLEAX,1
//将EAX寄存器的值向左移动1位,被移出位送到CF,同时将CF之前的值放到最低位。RCREAX,CL
//将EAX寄存器的值向右移动CL位,被移出位送到CF,同时将CF之前的值放到最高位。
ROLAL,1ROREAX,CL把82H转成二进制数(B)循环左移1位后变成:(B),换算成十六进制数便是05(H)循环右移1位后变成:(B),换算成十六进制数便是41(H)
RCLAL,1RCRAL,CL首先把82H转换成二进制数B带进位循环左移1位后变成:B,CF=1换算成十六进制数便是04H带进位循环右移1位后变成:B,CF=0换算成十六进制数便是C1H
汇编指令英文全称 1.通用数据传送指令MOV----&moveMOVdest,dest←srcMOV指令把一个字节或字的操作数从源地址src传送至目的地址dest。MOVSX----&extendedmove with sign dataMOVZX----&extendedmove with zero dataPUSH----&pushPOP----&pop进栈出栈指令PUSHA----&pushallPOPA----&popallPUSHAD----&pushall dataPOPAD----&popall dataBSWAP----&byteswapXCHG----&exchange交换指令用来将源操作数和目的操作数内容交换,操作数可以是字、也可以是字节,可以在通用寄 存器与通用寄存器或存储器之间对换数据,但不能在存储器与存储器之间对换数据。movax,1234ax=1234hmovbx,5678bx=5678hxchgax,ax=5678h,bx=1234hxchgah,ax=7856hCMPXCHG----&compareand changeXADD----&exchangeand addXLAT----&translate换码指令用于将BX指定的缓冲区中、AL指定的位移处的数据取出赋给AL。2.输入输出端口传送指令IN----&inputOUT----&output3.目的地址传送指令LEA----&loadeffective addres有效地址传送指令movbx,0400hmovsi,3chleabx,[bx+si+0f62h] ;BX=139EH这里BX得到的是主存单元的有效地址,不是物理地址,也不是该单元的内容。LDS----&loadDSLES----&loadESLFS----&loadFSLGS----&loadGSLSS----&loadSS4.标志传送指令LAHF----&loadAH from flagSAHF----&saveAH to flagPUSHF----&pushflagPOPF----&popflagPUSHD----&pushdflagPOPD----&popdflag二、算术运算指令ADD----&add加法指令 mov al,0al=0fbhaddal,07al=02hADC----&addwith carryINC----&increase1AAA----&asciiadd with adjustDAA----&decimaladd with adjustSUB----&substractSBB----&substractwith borrowDEC----&decrease1NEC----&negativeCMP----&compareAAS----&asciiadjust on substractDAS----&decimaladjust on substractMUL----&multiplicationIMUL----&integermultiplicationAAM----&asciiadjust on multiplicationDIV----&divideIDIV----&integerdivideAAD----&asciiadjust on divideCBW----&changebyte to wordCWD----&changeword to double wordCWDE----&changeword to double word with sign to EAXCDQ----&changedouble word to quadrate word 三、逻辑运算指令AND----&andor----&orXOR----&xorNOT----&notTEST----&testSHL----&shiftleftSAL----&arithmaticshift leftSHR----&shiftrightSAR----&arithmaticshift rightROL----&rotateleftROR----&rotaterightRCL----&rotateleft with carryRCR----&rotateright with carry四、串指令MOVS----&movestringCMPS----&comparestringSCAS----&scanstringLODS----&loadstringSTOS----&storestringREP----&repeatREPE----&repeatwhen equalREPZ----&repeatwhen zero flagREPNE----&repeatwhen not equalREPNZ----&repeatwhen zero flagREPC----&repeatwhen carry flagREPNC----&repeatwhen not carry flag五、程序转移指令1&无条件转移指令(长转移)JMP----&jumpCALL----&callRET----&returnRETF----&returnfar2&条件转移指令(短转移,-128到+127的距离内)JA---&jumpwhen aboveJAE----&jumpwhen above or equalJNB----&jumpwhen not belowJB----&jumpwhen belowJNAE----&jumpwhen not above or equalJBE----&jumpwhen below or equalJNA----&jumpwhen not aboveJG----&jumpwhen greaterJNLE----&jumpwhen not less or equalJGE----&jumpwhen greater or equalJNL----&jumpwhen not lessJL----&jumpwhen lessJNGE----&jumpwhen not greater or equalJLE----&jumpwhen less or equalJNG----&jumpwhen not greaterJE----&jumpwhen equalJZ----&jumpwhen has zero flagJNE----&jumpwhen not equalJNZ----&jumpwhen not has zero flagJC----&jumpwhen has carry flagJNC----&jumpwhen not has carry flagJNO----&jumpwhen not has overflow flagJNP----&jumpwhen not has parity flagJPO----&jumpwhen parity flag is oddJNS----&jumpwhen not has sign flagJO----&jumpwhen has overflow flagJP----&jumpwhen has parity flagJPE----&jumpwhen parity flag is evenJS----&jumpwhen has sign flag3&循环控制指令(短转移)LOOP----&loopLOOPE----&loopequalLOOPZ----&loopzeroLOOPNE----&loopnot equalLOOPNZ----&loopnot zeroJCXZ----&jumpwhen CX is zeroJECXZ----&jumpwhen ECX is zero4&中断指令INT----&interruptINTO----&overflowinterruptIRET----&interruptreturn5&处理器控制指令HLT----&haltWAIT----&waitESC----&escapeLOCK----&lockNOP----&nooperationSTC----&setcarryCLC----&clearcarryCMC----&carrymake changeSTD----&setdirectionCLD----&cleardirectionSTI----&setinterruptCLI----&clearinterrupt六、伪指令DW----&definwwordPROC----&procedureENDP----&endof procedureSEGMENT----&segmentASSUME----&assumeENDS----&endsegmentEND----&end
条件转移指令
程序的结构可以分为3大部分,分别是顺序结构、分支结构、循环结构。像高级语言一样,在高级语言里有if-else条件分支、do-while循环、for 循环和goto语句来改变程序的执行流程。在汇编语言中没有高级语言里的if-else条件分支、do-while循环和for循环,汇编语言通过提供条件转移指令来实现程序执行流程的改变。 在汇编语言中条件转移指令分为无条件转移指令和条件转移指令。(1)无条件转移指令JMPJMP指令格式是:JMP OPER,其中OPER是目的地址。示例代码:JMPEAX //跳转到EAX寄存器指示的4字节地址。JMPDWORD PTR DS:[ESI+2]
//跳转到内存地址为ESI+2指示的2字节地址。 (3)条件转移指令。汇编的条件转移指令非常多,通常可以分为3大部分:无符号数的条件转移指令、有符号数的条件转移指令和算术条件转移指令。 条件转移指令格式是:条件转移指令名称 OPER,其中OPER是目的地址。无符号数的条件转移指令名称、转移条件、转移说明如表1-2表示。表1-2
无符号数的条件转移说明表 指令名称转移条件转移说明JA/JNBECF=0且 ZF=0结果低于等于转移,或者高于转移JAE/JNBCF=0结果不低于转移,或者高于转移JB/JNAECF=1结果低于转移,或者不高于等于转移JBE/JNACF=1结果低于等于转移,或者不高于转移有符号数的条件转移指令名称、转移条件、转移说明如表1-3所示。表1-3
有符号数的条件转移说明表指令名称转移条件转移说明JG/JNLEZF=0且SF=OF不小于等于转移,或者大于转移JGE/JNLSF=OF不小于转移,或者大于等于转移JL/JNGESF≠OF小于转移,或者大于等于转移JLE/JNGZF=1且 F≠OF小于等于转移,或者不大于转移算术条件转移指令名称、转移条件、转移说明如表1-4所示。表1-4
算术条件转移说明表指令名称转移条件转移说明JZ/JEZF=1等于0转移,或者相等转移JNZ/JNEZF=0不等于0转移,或者不相等转移JSSF=1为负转移JNSSF=0为正则转移JOOF=1溢出转移JNOOF=0不溢出转移JCCF=1进位标志被置转移JNCCF=0进位标志被清转移JP/JPEPF=1偶数转移JNP/JPOPF=0奇数转移函数调用指令CALL
在高级语言中,对函数再熟悉不过了,一个程序的功能可以认为是一组函数互相调用的结果,函数是计算并且返回某些值的一段代码。
在汇编语言中,使用CALL指令和RET指令或者CALL指令和ADD ESP,OPER指令实现函数的调用与函数返回。
CALL指令的格式是:CALL OPER,其中OPER是函数地址(子程序地址)CALL指令首先将ESP堆栈指针寄存器的值减4,然后将EIP程序指令计数器的值压入堆栈,最后计算函数地址,将当前EIP程序指令计数器的值设置为函数地址。例如:调用下面的C语言函数,计算机会执行如下操作:
PUSH a[i]Print(&%d&,a[i]):
PUSH OFFSET String &%d&
CALL print
Add esp,8 在高级语言中调用函数时不需要编程人员管理堆栈和恢复函数调用前的环境,因为高级语言的编译器在编译源代码的时候已经做好了。
在汇编语言中,编程人员使用CALL调用完函数后需要使用RET指令或ADD ESP指令恢复函数调用前的坏境,以便调用完函数后程序能继续正常执行。 RET函数返回指令的格式是:RET OPER,其中OPER是需要从堆栈中弹出的字节数。
RET指令首先将堆栈中弹出4字节数据到EIP,然后ESP=ESP+2,最后根据OPER的值修改ESP堆栈指针的值ESP=ESP+OPER。
对于遵从Cdecl调用约定(后面会讲到)的那些函数而言,函数调用完后不是使用RET指令,而是由调用者使用ADD ESP,OPER从堆栈中弹出OPER字节数据来清理堆栈。 如何判断CALL有多少个参数?
1.看CALL前面的有几个PUSH,假设有3个,就是有3个参数
2.进入CALL,看CALL尾部retn指令 是几,假设是:retn4 说明该CALL有1个参数,假设retn 0c
说明有3个参数,0c(十六进制)=12(10进制),之所以4为一个参数,是因为1个PUSH 占用4字节。 如果平衡堆栈?
根据上面的方法可以判断出CALL有几个参数,
平衡堆栈就是用add esp,参数个数*4再转换成16进制
假设:有5个参数,5*4=20(十进制) =转换成十六进制(14) 也就是: add esp,14Push1Push2Push3Push4Push5CallAddesp,14 用于:CALL调用后能达到效果,但是游戏奔溃。在早期的编程语言中具有代表性的有C语言、Pascal、Basic、不辛的是这些具有代表性的编程语言各自使用不同的函数参数传递方式和由谁负责清除传递参数时使用的堆栈,俗称堆栈平衡方式,从而导致了有几种调用约定。
调用约定是规定函数参数传递的顺序和堆栈平衡的方式。常见的函数调用约定有Pascal调用约定、Cdecl调用约定和StdCall调用约定。
使用Delphi、编写的程序都遵从Pascal调用约定,C/C++/JAVA编写的程序都遵从Cdecl调用约定,Windows的API调用遵从的是StdCall调用约定。
调用约定的参数传递顺序假设有一高级语言函数Message(parameter1,paramerer2,parameter3),按照Pascal调用约定、Cdecl调用约定和StdCall调用约定的参数传递顺序如表1-5所示。表1-5
常见的函数调用约定
Pascal调用约定Cdecl调用约定StdCall调用约定PUSHparameter1PUSHparameter3PUSHparameter3PUSHparameter2PUSHparameter2PUSHparameter2PUSHparameter3PUSHparameter1PUSHparameter1CALLMessageCALLMessageCALLMessageADDESP,0CH参数从左到右传递,由被调用的函数清理堆栈参数从右到左传递,调用函数清理堆栈参数从右到左传递,由被调用的函数清理堆栈。
为什么要设立? 因为游戏更新基址,较大的偏移会变化,为了方便,所以设立OD死码,方便快速获取游戏更新后的相关数据。=======================什么是OD汇编死码与OD二进制死码? OD汇编死码指的就是OD反汇编中游戏更新后也不变的汇编。OD二进制死码指的就是OD反汇编中游戏更新后也不变的二进制。======================= 如何设立OD汇编死码? 条件:最多8条汇编,因为OD里ctrl+s搜的时候最多只能8条 哪些汇编不能用于OD死码:call 内存地址
jz/jnz/je(等跳转语句) 内存地址
mov eax,[ecx+0abc]
偏移abc比较大的不可以。
mov eax,[esp+30]
汇编里有ESP堆栈寄存器的不可以,后面跟的偏移+30会变化 举例:LEAEAX,DWORD PTR SS:[ESP+10]LEAECX,DWORD PTR SS:[ESP+40]LEAEDX,DWORD PTR SS:[ESP+4]PUSHESIPUSHEDIPUSHEAX
=======================如何设立OD二进制死码? 根据上面不能用于死码的情况来设立二进制死码: 具体设立是:OD中选中一块汇编,右键-二进制-二进制复制。 快捷键:ctrl+b 举例:
MOV EAX,DWORD PTRSS:[ESP+D0]0077B83C
PUSH ECX0077B83D
PUSH EDX0077B83E
PUSH EAX0077B83F
E80C9B1200
CALL elementc.008A5350
B 84 24 D0 00 00 00 51 52 50 E8 0C 9B 12 00 B 84 24 ?? 00 00 00 51 52 50 E8 ?? ?? ?? ?? =======================
贴吧热议榜
使用签名档&&
保存至快速回贴}

我要回帖

更多关于 汇编zf 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信