看了一篇博文,該文章中有如下描述
1 #include <stdio.h>
2
3 int main()
4 {
5 unsigned short a = 1;
6 unsigned short b = 0;
7
8 if (a < (b-1)) //a和b-1的結果-1都被轉換為int類型進行比較,1<-1,顯然false
9 {
10 printf("in if\n");
11 }
12
13 return 0;
14
15 }
預期結果時列印“in if”,但實際運作時卻發現啥都沒有輸出。改為如下代碼就可以正常輸出“in if”,此時與預期相符
1 #include <stdio.h>
2
3 int main()
4 {
5 unsigned short a = 1;
6 unsigned int b = 0;
7
8 if (a < (b-1)) //b-1的結果-1,被轉換為0xffffffff,1<0xffffffff,顯然true啊
9 {
10 printf("in if\n");
11 }
12
13 return 0;
14
15 }
使用彙編,直接對比兩者結果(公司安全不讓發送外網圖檔..),發現主要差異在如下5行,前四行中對short進行了擴充,由2位元組擴充為4位元組,高位填充0。導緻運作結果與與預期不符合的原因就在第5行:jge 8048461
1 08048425 <main>:
2 8048425: 8d 4c 24 04 lea 0x4(%esp),%ecx
3 8048429: 83 e4 f0 and $0xfffffff0,%esp
4 804842c: ff 71 fc pushl -0x4(%ecx)
5 804842f: 55 push %ebp
6 8048430: 89 e5 mov %esp,%ebp
7 8048432: 51 push %ecx
8 8048433: 83 ec 14 sub $0x14,%esp
9 8048436: 66 c7 45 f6 01 00 movw $0x1,-0xa(%ebp)
10 804843c: 66 c7 45 f4 00 00 movw $0x0,-0xc(%ebp)
11 8048442: 0f b7 45 f6 movzwl -0xa(%ebp),%eax
12 8048446: 0f b7 55 f4 movzwl -0xc(%ebp),%edx
13 804844a: 83 ea 01 sub $0x1,%edx
14 804844d: 39 d0 cmp %edx,%eax
15 804844f: 7d 10 jge 8048461 <main+0x3c>
16 8048451: 83 ec 0c sub $0xc,%esp
17 8048454: 68 00 85 04 08 push $0x8048500
18 8048459: e8 a2 fe ff ff call 8048300 <puts@plt>
19 804845e: 83 c4 10 add $0x10,%esp
20 8048461: b8 00 00 00 00 mov $0x0,%eax
21 8048466: 8b 4d fc mov -0x4(%ebp),%ecx
22 8048469: c9 leave
23 804846a: 8d 61 fc lea -0x4(%ecx),%esp
24 804846d: c3 ret
25 804846e: 66 90 xchg %ax,%ax
彙編中的數值是沒有符号之分的,但指令是有符号分别的,上述使用的jge即是有符号比較的方式,導緻比較結果為:if (1<-1),為false,不會列印字元串
指令 | 含義 | 運算符号 |
jbe | unsigned below or equal (lower or same) | <= |
jae | unsigned above or equal (higher or same) | >= |
jb | unsigned below (lower) | < |
ja | unsigned above (higher) | > |
jle | signed less or equal | |
jge | signed greater or equal | |
jl | signed less than | |
jg | signed greater than |