在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 成立。
那么什么时候这个条件成立?先说类型转换规则:
根据规则,判断如下情况:
/********************************/
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
#include
#include
#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;
//}