先看一段代码:
unsigned i1 ;
for (i1=9;i1>=0;i1--)
{
printf("%u\n",i1);
}
由于作为无符号整型的i1始终大于等于0,所以是个死循环,如果把i1改为int类型,就不再是死循环了。那么,编译以后,汇编指令怎么分别判断无符号类型或整型变量与0的大小呢?经过以下程序调试过程中的反汇编代码得知,当i1为unsigned类型是,i1>=0是通过cmp i1,0 (这里姑且用伪汇编来说明)后,使用jb Label来跳出循环。jb判断的是carry flag,即减法中有无借位(或进位),适用于判断无符号数的大小;当i1是带符号整型int变量时程序编译为cmp i1,0;jl Label ,jl当符号位不等于over flag溢出标志时跳转(比如结果为负且没有溢出,或者两个负数相加结果为正有溢出的情况),用于带符号数的比较,本例中当结果为负时跳出循环,这是适用于带符号数比较大小的情形。总结:jg、jge、jl、jle、jnl用于带符号数的比较转移;ja,jae,hb,jbe,jna,jnb用于无符号数的比较转移。
/*以下是程序的反汇编清单*/
1: #include <stdio.h>
2: #include <windows.h>
3: int main()
4: {
00401010 push ebp
00401011 mov ebp,esp //保存栈帧指针
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
5: int i1 ;
6: for (i1=9;i1>=0;i1--)
//[ebp-4]为变量i的位置,初始化为9
00401028 mov dword ptr [ebp-4],9
0040102F jmp main+2Ah (0040103a)
//i1--
00401031 mov eax,dword ptr [ebp-4]
00401034 sub eax,1
00401037 mov dword ptr [ebp-4],eax
//判断i-0,/结果为负则跳转(结束循环)
0040103A cmp dword ptr [ebp-4],0
0040103E jl main+43h (00401053)
7: {
8: printf("%u\n",i1);
00401040 mov ecx,dword ptr [ebp-4]
00401043 push ecx
00401044 push offset string "%u\n" (00424024)
00401049 call printf (004011a0)
0040104E add esp,8
9:
10: }
00401051 jmp main+21h (00401031)
11: system("PAUSE");
00401053 push offset string "PAUSE" (0042401c)
00401058 call system (00401090)
0040105D add esp,4
12: return 0;
00401060 xor eax,eax
13: }
00401062 pop edi
00401063 pop esi
00401064 pop ebx
00401065 add esp,44h
00401068 cmp ebp,esp
0040106A call __chkesp (00401220)
0040106F mov esp,ebp
00401071 pop ebp
00401072 ret