if else 判断
void func(int a,int b){
if (a > b) {
g = a;
}else{
g = b;
}
}
汇编代码如下:
_func:
// 拉伸栈空间
00000001000067a4 sub sp, sp, #0x10 ; CODE XREF=_main+28
// w0、w1 入栈
00000001000067a8 str w0, [sp, #0xc]
00000001000067ac str w1, [sp, #0x8]
// w8 = sc,w9 = s8
00000001000067b0 ldr w8, [sp, #0xc]
00000001000067b4 ldr w9, [sp, #0x8]
// w8与w9相减,(会修改状态寄存器)
00000001000067b8 subs w8, w8, w9
// 如果是小于等于则跳转loc_1000067d0
00000001000067bc b.le loc_1000067d0
00000001000067c0 ldr w8, [sp, #0xc]
00000001000067c4 adrp x9, #0x100008000
// g = sc
00000001000067c8 str w8,[x9,#0xd88] ; _g
// 跳转loc_1000067dc
00000001000067cc b loc_1000067dc
// w8 < w9
loc_1000067d0:
00000001000067d0 ldr w8, [sp, #0x8]; CODE XREF=_func+24
00000001000067d4 adrp x9, #0x100008000
// g = s8
00000001000067d8 str w8, [x9, #0xd88] ; _g
// 栈平衡
loc_1000067dc:
00000001000067dc add sp, sp, #0x10 ; CODE XREF=_func+40
00000001000067e0 ret
cmp(Compare)比较指令
CMP 把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,但不存储结果,只是正确的更改标志(CMP 后面跟的是 B.LE ,即else的条件)
一般 CMP 做完判断后会进行跳转,后面通常会跟上 B 指令。
BL 标号:跳转到标号处执行
B.LT 标号:比较结果是小于(less than ),执行标号,否则不跳转
B.LE 标号:比较结果是小于等于(less than or equal to),执行标号,否则不跳转
B.GT 标号:比较结果是大于(greater than),执行标号,否则不跳转
B.GE 标号:比较结果是大于等于(greater than or equal to),执行标号,否则不跳转
B.EQ 标号:比较结果是等于,执行标号,否则不跳转
B.NE 标号:比较结果是不等于(not equal),执行标号,否则不跳转
B.HI 标号:比较结果是无符号大于,执行标号,否则不跳转
B.HS 标号:比较结果是无符号大于等于,执行标号,否则不跳转
switch
判断条件为3个,则采用同 if、else 相同的寄存器比较操作。
void funcA(int a){
switch (a) {
case 1:
printf("打坐");
break;
case 2:
printf("加红");
break;
case 3:
printf("加蓝");
break;
default:
printf("啥都不干");
break;
}
}
汇编代码如下:
判断条件大于3个,则会去查内部的表:
void funcA(int a){
switch (a) {
case 1:
printf("打坐");
break;
case 2:
printf("加红");
break;
case 3:
printf("加蓝");
break;
case 4:
printf("摆摊");
break;
default:
printf("啥都不干");
break;
}
}
汇编代码如下:
x8(其实是一张表)地址加上4 取出来放进 x10,也就是00 00 00 20
修改 case 值,发现表的长度变了:
void funcA(int a){
switch (a) {
case 5:
printf("打坐");
break;
case 2:
printf("加红");
break;
case 7:
printf("加蓝");
break;
case 8:
printf("打坐");
break;
default:
printf("啥都不干");
break;
}
}
如果 case 跨度偏大,编译器还是会采取寄存器比较的方案。
void funcA(int a){
switch (a) {
case 10:
printf("打坐");
break;
case 221:
printf("加红");
break;
case 399:
printf("加蓝");
break;
case 4888:
printf("打坐");
break;
default:
printf("啥都不干");
break;
}
}
总结
1、假设 switch 语句的分支比较少时(例如3,少于4的时候没有意义),没有必要使用次结构,相当于 if-else。 2、各个分支常量的差值较大时,编译器会在效率还是内存进行取舍,这时编译器还是会编译成类似于if-else的结构。 3、在分支比较多的时候,在编译的时候会生成一个表(跳转表每个地址四个字节)。