首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【学员笔记分享】0基础学逆向笔记精整理(一)

【学员笔记分享】0基础学逆向笔记精整理(一)

作者头像
Ms08067安全实验室
发布2020-04-28 10:58:21
8470
发布2020-04-28 10:58:21
举报

本文作者:念真(二进制逆向星球学员)

01

进制

进制也就是进位计数制,是人为定义的带进位的计数方法(有不带进位的计数方法,比如原始的结绳计数法,唱票时常用的“正”字计数法,以及类似的tally mark计数)。对于任何一种进制---X进制,就表示每一位置上的数运算时都是逢X进一位。十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。

比如:10进制,1,2...9,10,11。逢10进一

2进制,10001。逢2进一。

16进制,1,2,3...9,a,b,c,d,e,f,10。逢16进一。

进制之间的一个换算,这里主要讲2进制与10进制的换算,如:100001,可以通过算法:1*2^0+0*2^1+0*2^2+...+1*2^5=33。(注:从右往左,可以分成0到5总共6位的排序,这些排序的位数对应与之相对应的2^n次方的指数。)

对于16进制换算为10进制,其实跟2进制的结构是类似的,比如:2f8,转换为10进制,可以写出算法为:8*16^0+f*16^1+2*16^2。

那么如何讲10进制的数转换为16进制或者2进制呢,其实也很简单(百度一下,你就知道23333)算法为:将10进制的数除以x(x为x进制),余数为x进制数的第1位,然后再将商除以x,余数为第2位,然后再将商除以x,以此类推。(故视频中的数字的转换就可以以此来进行换算,当然这里就不给答案啦,大家也可以利用计算器来进行转换)

02

进制的运算

进制的运算与我们平时所了解的运算方法基本上是一致的,唯一注意的就是进制的进位与借位,比如一个X进制的数,在进行运算的时候,他的进位和借位就为X,不能按照平时我们所学的10的惯性思维去以为进位和借位为10。

03

逻辑运算

逻辑运算主要有我们熟知的与或非,异或,同或等等。

与门(C语言中为&,汇编中为and)即:同真为真,不同为假。

或门(C语言中为|,汇编中为or)即:有真则真,同假为假。

非门(C语言中为!,汇编中为not)即:按位取反。

异或(C语言中为^,汇编中为xor)即:不同则真,相同则假。

同或(在C语言中和汇编中好像没有定义的符号)即:相同则真,不同则假。

左移与右移运算(C语言中为<<,>>)并且如果左移右移高位溢出的话,则弃之,空缺位补0。注:在没有发生高位溢出的情况下(高位溢出,即指最左边的一位不为1),左移x位相当该数乘以2^x次方,同理,右移呢?则是除以2^x次方。

在汇编语言当中,左移的逻辑算术符号为,左移指令包含sal和shl,这两条指令的作用是相同的。右移指令sar和shr,其中右移sar的指令用法,sar右移会用符号位填充,如果符号位是1,就填充1,如果是0就填充0。(符号位,表示的是eflags寄存器里面的符号位,规定当中,负数的高位均采用补码的形式,也就是高位为0的话补1)(这里提一个问:所有的移位操作,最终的结果是不是都会为0呢?左移的最终结果是不是全为0呢?)

注:xor运算可以用于加解密,因为它本身的特性,可以进行一种还原操作。

对于作业中的题,前面几道只需将16进制数转换为2进制数,然后进行逻辑运算即可。至于最后一题00001101,取出第5位(这里老师应该讲错了,应该是第4位,在我们的计算逻辑中,这应该是第四位),其实很简单,将(00001101)&(00001000)即可,也可以用异或运算(实际中我估计应该不会这么用,太傻了)(00001101)xor(00000101)

第一章(汇编基础)(环境搭建略过)

前面的三节视频基本上要总结的不多,就用几张图来概括了

注意:寄存器是我中有你,你中有我的兼容关系,跟指令集一样,是有向下兼容的。

这里再讲一下一些重要的寄存器:

EAX:(针对操作数和结果数据的)累加器,一些指令的会将结果返回给EAX中。

EBX:(DS段中的数据指针)基址寄存器。

ECX:(字符串和循环操作的)计数器,一些指令会用该寄存器来进行计数。

EDX:(I/O指针)数据寄存器。

EBP:(SS段中栈内数据指针)扩展基址指针寄存器。

ESI:(字符串操作源指针)源变址寄存器。

EDI:(字符串操作目标指针)目的变址寄存器

ESP:(SS段中栈指针)栈指针寄存器。

EBP到ESP的这四个寄存器主要用作保存内存地址的指针。

ESP指示栈区域的栈顶地址,某些指令(PUSH,POP,CALL,RET)可以直接用来操作ESP(注:栈区域管理是程序中相当重要的部分,请不要把ESP用作其他用途)

EBP表示栈区域的基地址,函数被调用时保存EBP的值,函数返回时再把值返回给ESP,保证栈不会崩溃(这称为栈帧技术,这是逆向中的一个重要概念)。ESI和EDI与特定指令(LODS,STOS,REP,MOVS等)一起使用,主要用于内存复制。

段寄存器:段,这一术语来自IA-32的内存管理模型,在IA-32中,段是一种保护内存的技术,它把内存分为多个区段,并为每个区段赋予了起始地址,范围,访问权限等,以保护内存。此外,它还同分页技术一起用于将虚拟内存变更为实际物理内存。段内存记录在SDT(段描述符表中,这里有兴趣的可以去看滴水中级的视频,里面有对段描述符和段描述符表的介绍),而段寄存器就持有这些SDT的索引。

各段寄存器的名称如下:

CS:code segment 代码段寄存器

SS:stack segment 栈段寄存器

DS:data segment 数据段寄存器

ES:extra segment 附加(数据)寄存器

FS:data segment (附加)数据段寄存器

GS:data segmet (附加)数据段寄存器

这些段寄存器就存放了对于的段的段基址。

摘自滴水中级,有兴趣的伙伴可以去看看

这里讲一下内存的五种表达形式里面的比例因子

dword ptr [eax+ecx*4]

eax 表示一个数组的首地址,ecx则用来存储我们要搜寻的那个数组内部元素的位数,索引的意思。这个4呢(1,2,4,8)表示这个数组的这个索引位置的数的空间是多少。dword表示指明这个数据的宽度,所谓数据宽度就是存储一个数据的容器的大小,因为是32位的寄存器,所以宽度为双字。ptr指向[...]中的地址。注意这一点,[]中的内容始终是一个地址。

因此,如果eax=0x00041000,ecx=0x02,比例因子为4那么比例因子法表达出来的地址应该是多少呢?eax+ecx*4应该是 0x00041008而不是0x00041002。这里我在OD上,增加了一些汇编代码可以发现,这行代码的意思是,(我增加的是,mov eax 01009020.movecx,2.mov ebx,dword ptr [eax+ecx*4],lea edx,[eax+ecx*4])然后运行出来的结果就是01009028处往后的4个字节的内容。后面即使再加一个数,也只是指再加一个偏移罢了,偏移,也就是offset。(这里我的失误,后面我会尽量对一些内容多动手测验一次)

(这里就不解释偏移了,字面意思即可)

1、状态标志(Status Flags)

EFLAGS寄存器的状态标志(0、2、4、6、7以及11位)指示算术指令(如ADD, SUB, MUL以及DIV指令)的结果,这些状态标志的作用如下:

CF(bit 0)[Carry flag](进位标志) 若算术操作产生的结果在最高有效位(most-significant bit)发生进位或借位则将其置1,反之清零。这个标志指示无符号整型运算的溢出状态,这个标志同样在多倍精度运算(multiple-precision arithmetic)中使用。

PF(bit 2)[Parity flag](奇偶标志) 如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零。

AF(bit 4)[Adjust flag](辅助进位标志) 如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。这个标志在BCD(binary-code decimal)算术运算中被使用。

ZF(bit 6)[Zero flag](0标志) 若结果为0则将其置1,反之清零。

SF(bit 7)[Sign flag](符号标志) 该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)

OF(bit 11)[Overflow flag](溢出标志) 如果整型结果是较大的正数或较小的负数,并且无法匹配目的操作数时将该位置1,反之清零。这个标志为带符号整型运算指示溢出状态。

在这些状态标志中,只有CF标志能够通过使用STC, CLC以及CMC指令被直接修改,或者通过位指令(BT, BTS, BTR以及BTC)将指定的位拷贝至CF标志中。

这些状态标志允许单个的算术操作产生三种不同数据类型的结果:无符号整型,有符号整型以及BCD整型。如果把该结果当做无符号整型,那么CF标志指示越界(out-of-range)状态——即进位或借位,如果被当做有符号整型,则OF标志指示进位或借位,若作为BCD数,那么AF标志指示进位或借位。SF标志指示有符号整数的符号位,ZF指示结果为零。此外在执行多倍精度算术运算时,CF标志用来将一次运算过程中带进位的加法(ADC)或带借位的减法(SBB)产生的进位或借位传递到下一次运算过程中。

2、DF标志(DF flag)

这个方向标志(位于EFLAGS寄存器的第10位)控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。设置DF标志使得串指令自动递减(从高地址向低地址方向处理字符串),清除该标志则使得串指令自动递增。STD以及CLD指令分别用于设置以及清除DF标志。

3、系统标志以及IOPL域(System Flags and IOPL Field)

EFLAGS寄存器中的这部分标志用于控制操作系统或是执行操作,它们不允许被应用程序所修改。这些标志的作用如下:

TF(bit 8)[Trap flag](单步标志) 将该位设置为1以允许单步调试模式,清零则禁用该模式。

IF(bit 9)[Interrupt enable flag](中断使能标志) 该标志用于控制处理器对可屏蔽中断请求(maskable interrupt requests)的响应。置1以响应可屏蔽中断,反之则禁止可屏蔽中断。

IOPL(bits12 and 13) [I/O privilege level field] 指示当前运行任务的I/O特权级(I/O privilege level),正在运行任务的当前特权级(CPL)必须小于或等于I/O特权级才能允许访问I/O地址空间。这个域只能在CPL为0时才能通过POPF以及IRET指令修改。

NT(bit 14)[Nested task flag] 这个标志控制中断链和被调用任务。若当前任务与前一个执行任务相关则置1,反之则清零。

RF(bit 16)[Resume flag] 控制处理器对调试异常的响应。

VM(bit 17)[Virtual-8086 mode flag] 置1以允许虚拟8086模式,清除则返回保护模式。

AC(bit 18)[Alignment check flag] 该标志以及在CR0寄存器中的AM位置1时将允许内存引用的对齐检查,以上两个标志中至少有一个被清零则禁用对齐检查。

VIF(bit19) [Virtual interrupt flag] 该标志是IF标志的虚拟镜像(Virtual image),与VIP标志结合起来使用。使用这个标志以及VIP标志,并设置CR4控制寄存器中的VME标志就可以允许虚拟模式扩展(virtual mode extensions)

VIP(bit20) [Virtual interrupt pending flag] 该位置1以指示一个中断正在被挂起,当没有中断挂起时该位清零。【Software sets and clears this flag; the processor only reads it.】与VIF标志结合使用。

ID(bit 21)[Identification flag] 程序能够设置或清除这个标志指示了处理器对CPUID指令的支持。

(摘抄自https://blog.csdn.net/jn1158359135/article/details/7761011)

关于VS2017下运行汇编指令,这个可以参照之前的vs2015的安装方法去安装对应的组件即可。

offset这个属于伪指令,可以进行简单的计算,作用是获取后面所跟的内容的地址的偏移,注意!是偏移。这里再顺便提一提这个指令与lea指令的区别,lea是机械代码,可以进行一些复杂的计算(lea的作用是,获取目标位置的地址,然后放到目的位置。

这里我顺便也把视频中的汇编代码打一遍吧(其中一些汇编代码的意思我也不是很清楚,因为没有用过汇编代码直接写程序过,但是有些类似的结构可以通过C语言来进行一个类比,具体大家可以参考汇编代码的书籍,如王爽老师的书籍,这里我看网上说,他的书籍里面有关于这个格式的讲解)

.586.MODEL flat, stdcallincludelib user32.libincludelib kernel32.libExitProcess PROTO, dwExitCode : DWORDMessageBoxA PROTO hWnd : DWORD, lpText : BYTE, lpCaption: BYTE, uType : DWORD.data Number DWORD 0text db "shellcode", 0.codemain proc    mov eax, 5    mov ebx, 6    add eax, ebx    add eax, Number    push 0    push offsettext    push offsettext    push 0    call    MessageBoxA    sub  esp, 16    callExitProcessmain ENDPEND main

(看不懂没关系,后续看的懂了,我再把注释什么的补上)

继续接上面的代码,开始分析一下代码的结构

.586指的是指令集,指令集是向下兼容的,也就是80386架构的兼容80286,80486架构的兼容80386的。因此,除了.586外,还有.486,.386。这里再附上CPU的发展历程。

另外cpu版本历史:8080 8086/8088 80286 80386 80486奔腾一 奔腾二 奔腾三 奔腾四 酷睿系列(最新为i7处理器)

.MODEL flat, stdcall,程序工作模式,flat为Windows程序使用的模式(代码和数据使用同一个4GB段),stdcall为API调用时右边的参数先入栈

includelib 这个可以参考C语言中一开始调用函数的那个include指令,类似的,这里指的是调用动态链接库,个人感觉就是PE文件里面的调用的dll库(动态链接库,也就是函数库)

.data 指的是数据段,这里存放了一些申明了的变量,如果是.data?则是存放未申明的变量,.code则是指的代码段,存放代码的位置。其实还有一个.stcak栈段,但是这个我们一般不会使用。

.const则是常量段,用来存储常量。

.stack,.data,.data?,.const和 .code是分段伪指令.

Win32中实际上只有代码和数据之分

  • .data,.data?和 .co.nst是数据段.
  • .code是代码段.
  • .stack段定义常常被忽略

因为和DOS汇编不同,Win32汇编不必考虑堆栈,系统会为程序分配一个向下扩展的、足够大的段作为堆栈段。

这里我从网上又找了一个关于内存分段的介绍。

BSS段:bss segment,通常是指用来存放程序中未初始化的全局变量的一块内存区域。

数据段:data segment,通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段:code segment,通常是指用来存放程序执行代码的一块内存区域。1).这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。2).在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。代码段是存放程序代码的数据。3).例如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段。

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)。当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

栈(stack):栈又称为堆栈,是用户存放程序临时创建的局部变量的地方。除此以外,在函数被调用时,其参数也被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存/交换临时数据的内存区。

分段优点:

1、内存分段和内存分页一样都是一种内存管理技术,分段:权限保护,分页:虚拟内存。

2、分段后,程序员可以定义自己的段,各段有独立的地址空间,像进程的地址空间相互独立一样。

3、同一个类的实例分配在一个段中,只有该类的方法可以访问,如果其他类的方法去访问,会因为段保护而出错。可以从硬件上实现类的数据保护和隐藏。

至于main proc 程序的入口罢了,可以参考C语言的使用,不过这个main我们可以换成其他的名字,这里没有强制要求。这里就类似C语言中的main(){},然后proc后面还可以进行一个传参操作。

这里再多说一句,上面的分段呢,其实刚好就跟PE文件里面的节区相对应了,当程序生成一个可执行文件的的时候,这些分段就会进入各自的节区,如code区,data区,resource区。

常用的汇编指令

基于IA-32处理器和32位汇编语言

首先说明:算术运算结果包括两部分,即运算结果和状态标志。

一:加法类指令

1.加法指令:ADD DEST,SRC ;DEST=DEST+SRC

将源操作数和目的操作数相加并返回给目的操作数。

2.带进位的加法指令(ADC,ADD WITH CARRY):ADC DEST,SRC ;DEST=DEST+SRC+CF

将源操作数和目的操作数和CF相加并返回给目的操作数。

3.增量指令:INC 操作数

将操作数加1并返回给原位置。不影响CF的值。

二:减法类指令

1.减法指令:SUB DEST,SRC ;DEST=DEST-SRC

将目的操作数和原操作数相减并返回给目的操作数。

2.带借位的减法指令(SBB,SUBTRACT WITH BORROW):SBB DEST,SRC ;DEST=DEST-SRC-CF

将目的操作数减原操作数减CF并返回给目的操作数。

3.减量指令 :DEC 操作数

将操作数减1并返回给原位置。不影响CF的值。

4.求补指令:NEG 操作数

用0减操作数并返回给操作数。

5.比较指令:CMP DEST,SRC ;DEST-SRC

用目的操作数和源操作数的差影响的状态标志来比较大小。主要用于给数据转换指令传送状态标志。

三:乘法指令

MUL(无符号乘法指令)和IMUL(有符号乘法指令)。

MUL SRC ;如果是8,16,32位数,分别乘AL,AX,EAX,结果放在AX,DX.AX,EDX.EAX中。

IMUL SRC ;如果是8,16,32位数,分别乘AL,AX,EAX,结果放在AX,DX.AX,EDX.EAX中。

IMUL DEST SRC ;DEST=DEST*SRC。

IMUL DEST SRC 立即数 ;DEST=SRC*立即数。

前两种的结果最高一半位数是无效数,则CF,OF是0,否则是1。ZF,SF,PF受影响。

四 :除法指令

DIV(无符号除法指令)和IDIV(有符号除法指令)。

DIV SRC ;如果是8,16,32位,用AX,EAX,EDX.EAX分别除,商放在AL,AX,EAX中,余数放在AH,DX,EDX中

IDIV SRC ;如果是8,16,32位,用AX,EAX,EDX.EAX分别除,商放在AL,AX,EAX中,余数放在AH,DX,EDX中

如果除数是0或者商很大,会发生除法溢出,这时会用0中断执行。

五:零位扩展和符号扩展指令

零位扩展:MOVZX DEST,SRC ;将SRC扩展后放在DEST中。

在数前补0。

符号扩展:MOVSX DEST,SRC ;将SRC扩展后放在DEST中。

如果是无符号数,补0。如果是有符号数,在补码前补1。

常用的算术,逻辑指令对标志位的影响

加法指令 ADD (addition)

指令对标志位的影响:

CF=1 最高有效位向高位有进位

CF=0 最高有效位向高位无进位

OF=1 两个同符号数相加(正数+正数 或 负数+负数),结果符号与其相反。

OF=0 两个不同符号数相加,或同符号数相加,结果符号与其相同。

带进位加法指令 ADC (add with carry)

指令对标志位的影响:

CF=1 最高有效位向高位有进位

CF=0 最低有效位相高位无进位

OF=1 两个同符号数相加,结果符号与其相反,

OF=0 两个同符号数相加,或同符号相加,结果符号与其相同

加1指令 INC (increament)

指令对标志位的影响:

对CF无影响

OF=1 两个同符号数相加,结果符号与其相反,

OF=0 两个同符号数相加,或同符号相加,结果符号与其相同。

减法指令 SUB (subtract)

指令对标志位的影响:

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

带借位减法指令 SBB (subtract with borrow)

指令对标志位的影响:

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

减1指令 DEC (decrement)

指令对标志位的影响:

对CF无影响

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

比较指令 CMP (compare)

指令对标志位的影响:

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

求补指令 NEG (negate)

指令对标志位的影响:

CF=1  不为0的操作数求补时

CF=0  为0的操作数求补时

OF=1 操作数为-128(字节运算)或操作数为-32768(字运算)

OF=0 当求补运算的操作数不为-128(字节)或-32768(字)时

无符号乘法指令 MUL (unsigned multiple) 有符号乘法指令 IMUL(signed muliple)

指令对标志位的影响:乘法指令只影响标志位CF和OF,其他条件码位无定义。

MUL指令的条件码设置为:

CF OF=0 0 乘积的高一半为0(字节操作的(AH)或字操作的(DX))

CF OF=1 1 乘积的高一半不为0

IMUL指令的条件码设置为:

CF OF=0 0 乘积的高一半为低一半的符号扩展.

CF OF=1 1 其他情况

无符号数除法 DIV (unsigned divide) 带符号数除法 IDIV (singeddivide)

指令对标志位的影响:不影响条件码。

逻辑与 AND (logic and)

指令对标志位的影响:

指令执行后 CF 和 OF 置零,AF无定义。

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0

逻辑或 or (logic or)

指令对标志位的影响:

令执行后 CF 和 OF 置零,AF无定义。

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0

逻辑非 NOT (logic not)

指令对标志位的影响:对标志位无影响

异或 XOR (exclusice or)

指令对标志位的影响:

令执行后 CF 和 OF 置零,AF无定义。

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0

测试指令 TEST

指令对标志位的影响:

指令执行后 CF 和 OF 置零,AF无定义。

PF=1 结果操作数中1的个数为偶数时置1

PF=0 结果操作数中1的个数为奇数时置0

逻辑左移 SHL (shift logical left)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

逻辑右移 SHR (shift logical right)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

算术左移 SAL (shift arithmetic left)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

算术右移SAR (shift arithmetic right)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

循环左移 ROL (rotate left)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

循环右移 ROR (rotate right)

指令对标志位的影响:

CF=移入的数值

OF=1 当cnt=1时,移动后最高位的值发生变化。

OF=0 当cnt=1时,移动时最高位的值未发生变化。

带进位的循环左移 RCL (rotate left through carry)

指令对标志位的影响:

CF=移入的数值。

OF=1 当cnt=1时,移动后最高位的值未发生变化。

OF=0 当cnt=1时,移动后最高位的值发生变化。

SF、ZF、PF标志位不受影响。

带进位的循环右移 RCR (rotate right through carry)

指令对标志位的影响:

CF=移入的数值。

OF=1 当cnt=1时,操作数最高位的值未发生变化。

OF=0 当cnt=1时,操作数最高位的值发生变化。

SF、ZF、PF标志位不受影响。

串传送 MOVSB / MOVSW (move string byte/word)

指令对条件码的影响:不影响条件码。

存串 STOSB / STOSW (stroe from string byte/word)

指令对条件码的影响:不影响条件码。

取串LODSB / LODSW (load from string byte/word)

指令对条件码的影响:不影响条件码。

串比较 CMPSB / CMPSW (compare string byte/word)

指令对条件码的影响:

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

串扫描 SCASB / SCASW (scan string byte / word)

指令对条件码的影响:

CF=1 二进制减法运算中最高有效位向高位有借位(被减数小于减数,不够减的情况)

CF=0 二进制减法运算中最高有效为向高位无借位(被减数〉=减数,够减的情况)

OF=1 两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同。

OF=0 同符号数相减时,或不同符号数相减,其结果符号与减数不同。

经部分代码运行证明,上面的一些如INC,DEC以及NOT指令等等,虽然不会影响CF进位标志,但是对于一些其他的标志,可能还是会造成影响,如AF,PF,ZF标志等等。这里大家可以具体的去运行看看,可以说,完全对标志位不参生任何影响的算术指令是几乎没有的,总是会或多或少的对标志位产生影响。

内容整理自:https://blog.csdn.net/csdn_lyy/article/details/45049079,https://blog.csdn.net/qq_22642239/article/details/51442739

串操作指令

MOVS OPRD1,OPRD2。将OPRD2中的数据放入OPRD2当中。

STOS串存储指令,英文缩写 store string , 将 eax 中的数据传送到目的地址(目的地址默认为 es:[edi])。注意:如果要进行对edi写入的话,要确保edi所在的内存空间是可写的。

rep指令,就是重复一条指令,每重复一次,ecx减一,直到ecx等于0为止。这个跟loop的区别就在于,这个是原地TP,loop会进行一个标志位置的跳转。共同点就是都利用了ECX来进行一个条件判定。

cmp OPRD1,OPRD2 将OPRD2-OPRD1,然后根据相减的结果,对标志位产生相应的影响。ZF=1 这个简单,则说明两个数相等,因为zero为1说明结果为0

当无符号时:

若CF=1 则说明了有进位或借位,cmp是进行的减操作,故可以看出为借位,所以,此时oprd1<oprd2

CF=0 则说明了无借位,但此时要注意ZF是否为0,若为0,则说明结果不为0,故此时oprd1>oprd2

当有符号时:

若SF=0,OF=0 则说明了此时的值为正数,没有溢出,可以直观的看出,oprd1>oprd2

若SF=1,OF=0 则说明了此时的值为负数,没有溢出,则为oprd1<oprd2

若SF=0,OF=1 则说明了此时的值为正数,有溢出,可以看出oprd1<oprd2

若SF=1,OF=1则说明了此时的值为负数,有溢出,可以看出oprd1>oprd2

最后两个可以作出这种判断的原因是,溢出的本质问题:

两数同为正,相加,值为负,则说明溢出

两数同为负,相加,值为正,则说明溢出

故有,正正得负则溢出,负负得正则溢出

JCC指令表

JCC指令

中文含义

检查符号位

典型C应用

JZ/JE

若为0则跳转;若相等则跳转

ZF=1

if (i == j);if (i == 0);

JNZ/JNE

若不为0则跳转;若不相等则跳转

ZF=0

if (i != j);if (i != 0);

JS

若为负则跳转

SF=1

if (i < 0);

JNS

若为正则跳转

SF=0

if (i > 0);

JP/JPE

若1出现次数为偶数则跳转

PF=1

(null)

JNP/JPO

若1出现次数为奇数则跳转

PF=0

(null)

JO

若溢出则跳转

OF=1

(null)

JNO

若无溢出则跳转

OF=0

(null)

JC/JB/JNAE

若进位则跳转;若低于则跳转;若不高于等于则跳转

CF=1

if (i < j);

JNC/JNB/JAE

若无进位则跳转;若不低于则跳转;若高于等于则跳转;

CF=0

if (i >= j);

JBE/JNA

若低于等于则跳转;若不高于则跳转

ZF=1或CF=1

if (i <= j);

JNBE/JA

若不低于等于则跳转;若高于则跳转

ZF=0或CF=0

if (i > j);

JL/JNGE

若小于则跳转;若不大于等于则跳转

SF!=OF

if (si < sj);

JNL/JGE

若不小于则跳转;若大于等于则跳转;

SF=OF

if (si >= sj);

JLE/JNG

若小于等于则跳转;若不大于则跳转

ZF!=O或ZF=1

if (si <= sj);

JNLE/JG

若不小于等于则跳转;若大于则跳转

SF=0F且ZF=0

if(si>sj)

call与retn指令,唯一需要注意的是,call指令在执行的时候,会先执行一次pop语句,retn会执行push eip语句。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Ms08067安全实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档