int a = -1;
unsigned int b = 1;
if(a < b)
printf("a < b\r\n");
else
printf("a > b\r\n");
if(a < (int)b)
printf("a < b\r\n");
else
printf("a > b\r\n");
运行结果:
a > b
a < b
直接比较a和b的话,a会被当做是0xFFFFFFFF来和b比较,因此a>b,而强制类型转换b为int类型时,才能得到正确结果。
将程序反汇编看看到底为什么:
0x08002CC2 F04F35FF MOV r5,#0xFFFFFFFF
58: unsigned int b = 1;
0x08002CC6 2401 MOVS r4,#0x01
59: if(a < b)
0x08002CC8 42A5 CMP r5,r4
0x08002CCA D203 BCS 0x08002CD4
60: printf("a < b\r\n");
61: else
0x08002CCC A029 ADR r0,{pc}+4 ; @0x08002D74
0x08002CCE F7FDFB03 BL.W __2printf (0x080002D8)
0x08002CD2 E002 B 0x08002CDA
62: printf("a > b\r\n");
63:
0x08002CD4 A029 ADR r0,{pc}+4 ; @0x08002D7C
0x08002CD6 F7FDFAFF BL.W __2printf (0x080002D8)
64: if(a < (int)b)
0x08002CDA 42A5 CMP r5,r4
0x08002CDC DA03 BGE 0x08002CE6
65: printf("a < b\r\n");
66: else
0x08002CDE A025 ADR r0,{pc}+2 ; @0x08002D74
0x08002CE0 F7FDFAFA BL.W __2printf (0x080002D8)
0x08002CE4 E002 B 0x08002CEC
67: printf("a > b\r\n");
可以看到 “if(a < b)” 和 “if(a < (int)b)” 都被编译成了 “CMP r5,r4” ,但是下面的判断语句有区别,ARM指令集中B指令是跳转指令,后面跟着跳转条件,可以看到 “if(a < b)”的跳转条件为 “CS” ,而 “if(a < (int)b)” 的跳转条件为 “GE”,这就是区别所在,下面进行简单分析。
CMP 指令与 SUBS 指令的区别在于CMP 指令不保存运算结果。在进行两个数据大小判断时,常用CMP指令及相应的条件码来操作。B 指令用于跳转,其后跟的跳转条件如下:
- BEQ Branch if EQual
- BNE Branch if Not Equal
- BVS Branch if oVerflow Set
- BVC Branch if oVerflow Clear
- BHI Branch if HIgher
- BLS Branch if Lower or the Same
- BPL Branch if PLus
- BMI Branch if MInus
- BCS Branch if Carry Set
- BCC Branch if Carry Clear
- BGE Branch if Greater than or Equal
- BGT Branch if Greater Than
- BLE Branch if Less than or Equal
- BLT Branch if Less Than
- BLEQ Branch with Link if EQual
…. - BLLT Branch with Link if Less Than
BCS表示如果 进位标志位 置位的话则跳转。如果寄存器 r5 中代表的无符号数据小于寄存器 r4 中代表的无符号数据的话,执行CMP指令之后,进位标志位置位,这里显然无符号数0xFFFFFFFF是大于0x01的。
BGE表示判断 r5 是否大于等于 r4,如果是,则跳转,这里就是有符号数的运算,虽然CMP指令的运算依然是一样的,但是对CMP指令的运算结果的看待方式改变了,以有符号数的运算来判断结果,因此0xFFFFFFFF其实被看成是 -1 ,所以 -1 < 1。
参考文章:
https://blog.csdn.net/u014069939/article/details/81107340
https://blog.csdn.net/mickey35/article/details/82011449