2013年5月5日 星期日

c 有號數與無號數的比較

我已經看完 C 专家编程, 但重看時不知道的還是不知道, 好像沒吸收進去。這是 C 专家编程 p24 程式碼。

t1.c
 1 #include <stdio.h>
 2 
 3 int array[]={23, 34, 12, 17,204, 99,16};
 4 
 5 #define TOTAL_E (sizeof(array)/sizeof(array[0]))
 6 
 7 int main(int argc, char *argv[])
 8 {
 9   int d = -1, x; 
10 
11   if (d <= TOTAL_E - 2)
12   {
13     printf("1\n");
14   }
15   else
16   {
17     printf("2\n");
18   }
19   return 0;
20 }


程式會執行 L17。
改成以下才會是正確的執行結果:
11 if (d <= (int)TOTAL_E - 2)

書上的解釋就不用在說明了, 我不是要把書上有的東西重提一次。組合語言下沒有秘密, 我們來看看反組譯的差別。

right case:

8048434: 55 push %ebp
8048435: 89 e5 mov %esp,%ebp
8048437: 83 e4 f0 and $0xfffffff0,%esp
804843a: 83 ec 20 sub $0x20,%esp
804843d: c7 44 24 1c ff ff ff movl $0xffffffff,0x1c(%esp) 8048444: ff
8048445: 83 7c 24 1c 05 cmpl $0x5,0x1c(%esp)
804844a: 7f 0e jg 804845a

804844c: c7 04 24 30 85 04 08 movl $0x8048530,(%esp)
8048453: e8 18 ff ff ff call 8048370
8048458: eb 0c jmp 8048466

804845a: c7 04 24 32 85 04 08 movl $0x8048532,(%esp)
8048461: e8 0a ff ff ff call 8048370
8048466: b8 00 00 00 00 mov $0x0,%eax
804846b: c9 leave
804846c: c3 ret
804846d: 8d 76 00 lea 0x0(%esi),%esi


wrong case:

8048434: 55 push %ebp
8048435: 89 e5 mov %esp,%ebp
8048437: 83 e4 f0 and $0xfffffff0,%esp
804843a: 83 ec 20 sub $0x20,%esp
804843d: c7 44 24 1c ff ff ff movl $0xffffffff,0x1c(%esp) 8048444: ff
8048445: 8b 44 24 1c mov 0x1c(%esp),%eax
8048449: 83 f8 05 cmp $0x5,%eax
804844c: 77 0e ja 804845c

804844e: c7 04 24 30 85 04 08 movl $0x8048530,(%esp)
8048455: e8 16 ff ff ff call 8048370
804845a: eb 0c jmp 8048468

804845c: c7 04 24 32 85 04 08 movl $0x8048532,(%esp)
8048463: e8 08 ff ff ff call 8048370
8048468: b8 00 00 00 00 mov $0x0,%eax
804846d: c9 leave
804846e: c3 ret
804846f: 90 nop




signed greater than JG BGT BGT sign=overflow and not zero
unsigned above (higher) JA BHI BHI * not borrow and not zero

一個用 unsigned 另外一個用 signed 來 compare, 於是 0xffffffff 被當成 4,294,967,295 和 -1, 這就是陷阱。




來看看 arm cortex-m3 的版本, 很難看是吧!我也覺得很難看, 我不是要說明 arm 組合語言, 所以只要看紅色部份就好, 簡單多了吧!

4294967295 是 0xffffffff 也是 -1

right
 dc6:   f04f 33ff       mov.w   r3, #4294967295
 dca:   62fb            str     r3, [r7, #44]   ; 0x2c
 dcc:   6afb            ldr     r3, [r7, #44]   ; 0x2c
 dce:   2b05            cmp     r3, #5
 dd0:   dc0a            bgt.n   de8

 dd2:   f44f 4088       mov.w   r0, #17408      ; 0x4400
 dd6:   f2c4 0000       movt    r0, #16384      ; 0x4000
 dda:   f640 61d8       movw    r1, #3800       ; 0xed8
 dde:   f2c0 0100       movt    r1, #0
 de2:   f7ff fce3       bl      7ac
 de6:   e009            b.n     dfc

 de8:   f44f 4088       mov.w   r0, #17408      ; 0x4400
 dec:   f2c4 0000       movt    r0, #16384      ; 0x4000
 df0:   f640 61dc       movw    r1, #3804       ; 0xedc
 df4:   f2c0 0100       movt    r1, #0
 df8:   f7ff fcd8       bl      7ac



wrong
 dc6:   f04f 33ff       mov.w   r3, #4294967295
 dca:   62fb            str     r3, [r7, #44]   ; 0x2c
 dcc:   6afb            ldr     r3, [r7, #44]   ; 0x2c
 dce:   2b05            cmp     r3, #5
 dd0:   d80a            bhi.n   de8

 dd2:   f44f 4088       mov.w   r0, #17408      ; 0x4400
 dd6:   f2c4 0000       movt    r0, #16384      ; 0x4000
 dda:   f640 61d8       movw    r1, #3800       ; 0xed8
 dde:   f2c0 0100       movt    r1, #0
 de2:   f7ff fce3       bl      7ac
 de6:   e009            b.n     dfc

 de8:   f44f 4088       mov.w   r0, #17408      ; 0x4400
 dec:   f2c4 0000       movt    r0, #16384      ; 0x4000
 df0:   f640 61dc       movw    r1, #3804       ; 0xedc
 df4:   f2c0 0100       movt    r1, #0
 df8:   f7ff fcd8       bl      7ac





bhi.n unsigned

bgt.n signed

一樣有針對有號數無號數的比較指令。

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。