【整理】⼏个汇编语句代码的解析
1、
mov eax,0a
test eax,eax ;即eax与eax作“与”操作
je xxxx,这个跳会跳吗?能详细解释下test eax,eax这是什么意思嘛?这样检测下来的结果不是永远相等的嘛!
=================
test eax,eax 基本上和 And eax,eax 是⼀样的,不同的是test 不改变eax的结果,只是改变FLAG寄存器的状态,也就是改变进位标志,零标志,溢出标志等 等。举⼀个例⼦,如果eax=01h,test eax,eax 就是两个01h 作与操作,所以结果还是01h,不是0的话,就不会跳转je xxxx。所以要跳转je xxxx,只有⼀种可能就是eax=0h.所以现在eax=0a 则不会跳转 je xxxx
2、
MOV EAX,DWORD PTR SS:[EBP-1C]这句话什么意思?
=================
MOV是⼀个赋值语句,这句话的意思是:将EBP寄存器的值减1CH,然后在SS(堆栈段)寻址,到EBP-1C这个地址的值,然后将这个值转换成 DWORD类型,也就是32位,取4字节,然后存在EAX这个寄存器⾥。
3、
⼀直对寄存器ESP和EBP的概念总是有些混淆,查看定义ESP是栈顶指针,EBP是存取堆栈指针。还是不能很透彻理解。之后借于⼀段汇编代码,总算是对两者有个⽐较清晰的理解。
下⾯是按调⽤约定__stdcall 调⽤函数test(int p1,int p2)的汇编代码
;假设执⾏函数前堆栈指针ESP为NN
push p2 ;参数2⼊栈, ESP -= 4h , ESP = NN - 4h
push p1 ;参数1⼊栈, ESP -= 4h , ESP = NN - 8h
call test ;压⼊返回地址 ESP -= 4h, ESP = NN - 0Ch
;
//进⼊函数内
{
push ebp ;保护先前EBP指针, EBP⼊栈, ESP-=4h, ESP = NN - 10h
mov ebp, esp ;设置EBP指针指向栈顶 NN-10h
mov eax, dword ptr [ebp+0ch] ;ebp+0ch为NN-4h,即参数2的位置
mov ebx, dword ptr [ebp+08h] ;ebp+08h为NN-8h,即参数1的位置
sub esp, 8 ;局部变量所占空间ESP-=8, ESP = NN-18h
...
add esp, 8 ;释放局部变量, ESP+=8, ESP = NN-10h
pop ebp ;出栈,恢复EBP, ESP+=4, ESP = NN-0Ch
ret 8 ;ret返回,弹出返回地址,ESP+=4, ESP=NN-08h, 后⾯加操作数8为平衡堆栈,ESP+=8,ESP=NN, 恢复进⼊函数前的堆栈.
}
看完汇编后,再看EBP和ESP的定义,哦,豁然开朗,
原来ESP就是⼀直指向栈顶的指针,⽽EBP只是存取某时刻的栈顶指针,以⽅便对栈的操作,如获取函数参数、局部变量等。
4、
int main( )
{ int var = 10;
teach(var);
汇编指令有多少个return 0;
}
void teach(int testvar)
{
_asm
{
mov ebx,[ebp+8]
mov ebx,[ebx]
}
}
请问,这段程序执⾏后ebx将得到var的变量地址,中间发⽣了什么,是怎么取到var的地址的?
⼀楼的有⽑病,[ebp+8]位置是⼀个指针的地址,我只是想知道这个地址怎么产⽣的!
=====================================
c++⽣成变量就是在堆栈中按照你数据的类型来给你分配空间。所以这⾥有什么异议吗?
[ebp+8]指向的是 堆栈中的⼀个空间 就是 你定义变量的那个 内存地址的⾸地址。
如果你想知道为什么是[ebp+8]反汇编调试下你就明⽩了
在汇编语⾔中 ebx是基址寄存器,这个⽤的是 寄存器间接寻址⽅式,将ebx中的内容作为偏移引⽤ds段
来到偏移也就是说 这句指令就是 mov ebx,ds:[ebx]
段地址*10+偏移地址=物理地址。到物理地址后取出 其中的值送给ebx寄存器
mov ebx,[ebp+8];这句指令是将var的偏移传送给ebx
⽽此时 ebx中的值是var的偏移地址 所以就是讲 var中的数据传送给ebx寄存器中
5、
我把00401000的字符串放到EAX⾥,把00401020的字符串放到EDI⾥,然后⽐较,相等就跳,⽤汇编代码怎么实现
还有这样写对不对:
mov eax,00401000
mov edi ,00401020
cmp eax,edi
jz XXXXXX
但是我发现即使00401000和00401020的字符串相等,但是那个jz xxxxx(相等就跳)却没有跳,这是为什么
是代码格式错误么?
=====================================
这样的赋值⽐较,当然只是⽐较地址.如果加个[]的话,才是真正的⽐较!
⽐如:00401000是字符串1,00402000是字符串2.
mov eax,dword ptr ds:[401000]
mov edx,dword ptr ds:[402000]
cmp eax,edx
这样⽐较,才是⽐较字符串的ASCII值,即⽐较字符串!
但是,单这样进⾏⽐较的话有个漏洞:字符串的⽐较是⽐较每个字符的ASCII值,所以,返回的值是ASCII值,但是,每个寄存器只有32位的,也就是只能返回4个字符,所以,字符超过4位的话,只要前4位相等的话,⽆论后⾯是多少,都会提⽰你相等!
如果想要⽐较多位数的话,完美进⾏处理的话,可以逐位进⾏⽐较!
6、
sbb r, r
and r, (val1 - val2)
add r, val2
=======================================
neg r 指令的结果是设置Carry Flag, 也就是借位的标志位. 因为neg r的操作语义是0 - r, 零减去任何⾮零的数,都会产⽣"借位"的. 当然这⾥r寄存器中的值也被改掉了,不过没关系, 反正它都要被稍后的指令再改掉的.
紧接着,sbb r, r 指令设置r为零或者-1. 因为语义为⽤⼀个值去减掉它⾃⾝, 结果当然是零啰. 但是,这样做会把carry flag⼀起给减掉的, 该指令的公式是
r – r – CF –> r 所以,如果r最开始就是0, 那么sbb r, r的结果是将r设置为0. 如果不是零,那么结果是0-CF = 0-1 = –1 = FFFFFFFF
第三个操作是⼀个mask的操作, 如果r是0的话,任何数与0做与操作都是0. 如果r不是0, 那么任何数与FFFFFFFF做与操作,都会留下那个值.也就是说, 如果r是0, 那么r为0; 如果不为0, 那么结果为val1 – val2.
第四个操作是把val2加到r上,结合之前的结论, 我们可以得出如果r是0, 那么结果等于val2, 如果r不是0, 那么结果等于val1 – val2 + val2,结果为val1.
总结⼀下,整个四句指令⼀起的意思就是, 如果r为0, 那么r中的值为val2, 如果r不为0, 那么r中的值会是val1. 即r ? val1 : val2
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论