一般情况下我们的判断往往都是有跳转指令的,这个跳转指令的分类我就不详细的分了,大的一般分为6字节(5字节)或是2字节的,具体看下表了解一下就好: 这里要对书上做一个补充:书上的无条件跳转指令(JMP)只说了两种类型: 1:目标地址为0~FF(有符号) 2:目标地址为0~FFFF(有符号)(通常见到的都是这个) 3(补充):后面直接跟目标地址的
这里贴一个条件设置的指令吧 这些指令都可以用于修改类似于标志寄存器标志位的0,1值的,针对于有条件跳转的修改。 当然,有的时候会遇到优化比较强的此时就会整合我们的代码从而不直接展现出我们的if,else来,如:
neg eax sbb eax,eax and al,0FCH add eax,5 retn这里世界上就是针对一个bool量的0和1的判断,在上面的汇编程序中我们发现: 如果eax为0,由neg检测的为0就放在标志寄存器中,此时就会让CF位为0,然后sbb就相当于 eax = 0 - 0 此时and 以后同样为0,然后加5就为5,此时eax作为返回值,所以就是return 5 如果eax为1,此时CF为1,然后sbb就是eax = 0 - 1 ,eax = FFFFFFFF,此时and 0FC以后就变成看了FFFFFFFC然后加5,CF为1,eax 为 0,此时eax作为返回值,所以就是return 0 所以这里对应的语句应该是:
if(bool) return 0; else return 5;再看看循环 在8086汇编中循环是一个loop 联合一个FLAG和ecx递减计数用的 但是在逆向过程中,我们的for循环,while循环的形式一般就不用loop了,具体大概就是: for(i = 0;i<10;++i: (我这里变量都用寄存器代替了吧)
xor eax,eax jmp 1 0 inc eax 1 cmp eax,a jg 2 ..... jmp 0 2 ...其实这里就是一个for 的思路,首先执行第一个分号前的东西,然后判断中间是否成立,然后执行后面的循环内容,然后执行第三个括号里面的东西然后判断中间是否成立。 while的话其实就是相对上面那个少了个初始化的过程 do - while也是一样的。
数学运算; 在汇编里面一般见得到的运算命令有:add sub mul div这四个基础类,后面还扩展到了包含标志寄存器的类似于上面的sbb之类的,当然还有其他的一系列。。。 这里要说一些关于编译器进行特别优化的一些:
printf("%s",a + b + 1); //mov eax,[a] //mov ecx,[b] //lea edx , dword ptr[eax + ecx + 1] //push edx //push ...这里就只是想说明,在有的编译器下会直接以类似于lea edx , dword ptr[eax + ecx + 1]的形式进行加减并传参(速度最快)这里说一下,lea 和[]就非常类似于C里面的&和*两个符号,所以此时edx的值实际上就是eax + ecx + 1 这里再提一下乘法,乘法一般的话就直接用mul就好,但是有的时候是基数此时如果要以效率优先那么就会用lea eax[eax +4*eax](这里是a *= 5)因为此时以3,4,8之类的二的幂计算实际上就只需要用到位移就行,一次位移就之消耗一个CPU时钟。 再出发里面我们一般会用到a/b = a*1/b的算法,或使用到位移 这里介绍两个汇编的位移: shr右位移(除二)shl左位移(乘法)
