先看一段代碼:
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