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、
neg r
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