在STM32平臺上輸入一下代碼段:
int main(void)
{
uint8_t a = 6;
int8_t b = -20;
if(b+a>6){
LED0=1;
}else{
LED0=0;
}
}
程序最終會執行,LED0=0,即表示 6+(-20)<6。
通過MDK的反彙編得到代碼:
10: uint8_t a = 6;
0x080002FC 2106 MOVS r1,#0x06
11: int8_t b = -20;
12:
0x080002FE F06F0213 MVN r2,#0x13
13: if(b+a>6){
0x08000302 1850 ADDS r0,r2,r1
0x08000304 2806 CMP r0,#0x06
0x08000306 DD03 BLE 0x08000310
14: LED0=1;
15: }else{
0x08000308 2001 MOVS r0,#0x01
0x0800030A 4B04 LDR r3,[pc,#16] ; @0x0800031C
0x0800030C 6018 STR r0,[r3,#0x00]
0x0800030E E002 B 0x08000316
16: LED0=0;
17: }
0x08000310 2000 MOVS r0,#0x00
0x08000312 4B02 LDR r3,[pc,#8] ; @0x0800031C
0x08000314 6018 STR r0,[r3,#0x00]
18: }
0x08000316 2000 MOVS r0,#0x00
0x08000318 4770 BX lr
把uint8_t 修改爲uint16_t ,得到的彙編代碼:
10: uint16_t a = 6;
0x080002FC 2106 MOVS r1,#0x06
11: int16_t b = -20;
12:
0x080002FE F06F0213 MVN r2,#0x13
13: if(b+a>6){
0x08000302 1850 ADDS r0,r2,r1
0x08000304 2806 CMP r0,#0x06
0x08000306 DD03 BLE 0x08000310
14: LED0=1;
15: }else{
0x08000308 2001 MOVS r0,#0x01
0x0800030A 4B04 LDR r3,[pc,#16] ; @0x0800031C
0x0800030C 6018 STR r0,[r3,#0x00]
0x0800030E E002 B 0x08000316
16: LED0=0;
17: }
0x08000310 2000 MOVS r0,#0x00
0x08000312 4B02 LDR r3,[pc,#8] ; @0x0800031C
0x08000314 6018 STR r0,[r3,#0x00]
18: }
0x08000316 2000 MOVS r0,#0x00
0x08000318 4770 BX lr
這跟uint8_t時的彙編代碼一樣,沒有變化。
當把uint8_t 修改爲uint32_t 時,即代碼如下:
int main(void)
{
uint32_t a = 6;
int32_t b = -20;
if(b+a>6){
LED0=1;
}else{
LED0=0;
}
}
得到的彙編也變了:
10: uint32_t a = 6;
0x080002FC 2106 MOVS r1,#0x06
11: int32_t b = -20;
12:
0x080002FE F06F0213 MVN r2,#0x13
13: if(b+a>6){
0x08000302 1850 ADDS r0,r2,r1
0x08000304 2806 CMP r0,#0x06
0x08000306 D903 BLS 0x08000310
14: LED0=1;
15: }else{
0x08000308 2001 MOVS r0,#0x01
0x0800030A 4B04 LDR r3,[pc,#16] ; @0x0800031C
0x0800030C 6018 STR r0,[r3,#0x00]
0x0800030E E002 B 0x08000316
16: LED0=0;
17: }
0x08000310 2000 MOVS r0,#0x00
0x08000312 4B02 LDR r3,[pc,#8] ; @0x0800031C
0x08000314 6018 STR r0,[r3,#0x00]
18: }
0x08000316 2000 MOVS r0,#0x00
0x08000318 4770 BX lr
3個程序段得到的代碼,只有在跳轉指令不同(LED0=1上面一句):
uint8_t 和uint16_t 中,跳轉指令是:0x08000306 DD03 BLE 0x08000310
而在uint32_t 中,跳轉指令是:0x08000306 D903 BLS 0x08000310
區別就在與BLE 和BLS,爲搞懂這兩個指令的含義,需要找ST官方的文檔PM0056,在該文檔的3.8.5章節由說到跳轉指令:
PS:BLE和BLS是B指令,不是BL指令,LE和LS是條件碼。
可選條件碼在剛文檔的表23, Table 23: Condition code suffixes on page 57:
簡言之,BLE就是有符號類的小於等於,BLS就是無符號類的小於等於。
明白了以上一點,就再繼續分析。
STM32爲32爲的CPU,其寄存器就是32位的,在執行
uint32_t a = 6;
int32_t b = -20;
或
uint16_t a = 6;
int16_t b = -20;
或
uint8_t a = 6;
int8_t b = -20;
和
a+b
以上程序時,得到的彙編代碼都是一樣的:
0x080002FC 2106 MOVS r1,#0x06
0x080002FE F06F0213 MVN r2,#0x13
0x08000302 1850 ADDS r0,r2,r1
最後得到的結果就是a+b = R0=0xFFFF FFF2,而這個R0的值,到底是把它當有符號看,還是無符號看,就要看後面的指令了,STM32就只是個存儲。
前面說到,BLE就是有符號類的小於等於,BLS就是無符號類的小於等於。對於uin32_t 彙編得到的是BLS,因此R0這個數就是一個無符號的數,所以 a+b = 0xFFFF FFF2 = 4294967282 > 6
對於uint8_t 彙編得到的數是BLE,因此R0這個數是一個有符號數,所以 a+b = 0xFFFF FFF2 = -14 < 6
因此對於STM32來說,並非所有情況都能使 6 + (-20) > 6 成立。
那麼什麼時候這個條件成立?先說類型轉換規則:
(1)、進行運算的兩個變量的數據類型長度,若都小於32位,則都轉換爲有符號32位數據,即int32_t
(2)、若兩變量中數據類型長度大的那一個,且它的數據類型大於等於32位,則另一個數據轉換爲與數據類型大的那一個一樣
(3)、若兩變量中數據類型長度一樣,若存在無符號數,則都轉換爲無符號數。
根據規則,判斷如下情況:
/********************************/
uint8_t a = 6;
int8_t b = -20;
uint16_t a = 6;
int8_t b = -20;
uint32_t a = 6;
int8_t b = -20;
uint64_t a = 6;
int8_t b = -20;
/********************************/
/********************************/
uint8_t a = 6;
int16_t b = -20;
uint16_t a = 6;
int16_t b = -20;
uint32_t a = 6;
int16_t b = -20;
uint64_t a = 6;
int16_t b = -20;
/********************************/
/********************************/
uint8_t a = 6;
int32_t b = -20;
uint16_t a = 6;
int32_t b = -20;
uint32_t a = 6;
int32_t b = -20;
uint64_t a = 6;
int32_t b = -20;
/********************************/
/********************************/
uint8_t a = 6;
int64_t b = -20;
uint16_t a = 6;
int64_t b = -20;
uint32_t a = 6;
int64_t b = -20;
uint64_t a = 6;
int64_t b = -20;
/********************************/
可以使用代碼自行實驗:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define TYPE uint8_t
#define FirstVar -20
#define SeconedVar 6
int main()
{
char *p="int64_t";
uint8_t a = FirstVar;
TYPE b = SeconedVar;
if(a+b>6){
printf("uint8_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
}else{
printf("uint8_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
}
uint16_t c = FirstVar;
TYPE d = SeconedVar;
if(c+d>6){
printf("uint16_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
}else{
printf("uint16_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
}
uint32_t e = FirstVar;
TYPE f = SeconedVar;
if(e+f>6){
printf("uint32_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
}else{
printf("uint32_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
}
uint64_t g = FirstVar;
TYPE h = SeconedVar;
if(g+h>6){
printf("uint64_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
}else{
printf("uint64_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
}
getchar();
return 0;
}
//int main()
//{
// char *p="uint8_t";
//
// int8_t a = FirstVar;
// TYPE b = SeconedVar;
//
// if(a+b>6){
// printf("int8_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
// }else{
// printf("int8_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
// }
//
//
// int16_t c = FirstVar;
// TYPE d = SeconedVar;
// if(c+d>6){
// printf("int16_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
// }else{
// printf("int16_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
// }
//
// int32_t e = FirstVar;
// TYPE f = SeconedVar;
// if(e+f>6){
// printf("int32_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
// }else{
// printf("int32_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
// }
//
// int64_t g = FirstVar;
// TYPE h = SeconedVar;
// if(g+h>6){
// printf("int64_t %d + %s %d > 6 \r\n",FirstVar,p,SeconedVar);
// }else{
// printf("int64_t %d + %s %d < 6 \r\n",FirstVar,p,SeconedVar);
// }
//
//
// getchar();
// return 0;
//}