-- TOC --
C语言天生与汇编就有很直接的对应关系。对于switch语句,编译成汇编后,有可能出现性能很高的jump table代码,这比连续的if..else...if...判断性能高很多。本文就来看看jump table是什么样的。
为什么C语言有do-while循环?我认为就是因为do-while结构几乎与汇编能够直接对应。
下面是测试用C代码:
int main(int argc, char **argv) {
int a;
switch(argc){
case 0:
a = 101;
break;
case 1:
case 2:
a = 102;
break;
case 3:
a = 103;
break;
case 4:
a = 104;
break;
case 5:
a = 105;
case 6:
a = 106;
break;
default:
a = 1000;
break;
}
return a;
}
用-Og
编译,不要管warning,得到的汇编如下:
main:
cmp edi, 6
ja .L2
mov edi, edi
jmp [QWORD PTR .L4[0+rdi*8]]
.L4:
.quad .L8
.quad .L9
.quad .L9
.quad .L6
.quad .L5
.quad .L3
.quad .L3
.L8:
mov eax, 101
ret
.L6:
mov eax, 103
ret
.L5:
mov eax, 104
ret
.L3:
mov eax, 106
ret
.L2:
mov eax, 1000
ret
.L9:
mov eax, 102
ret
.L4就是传说中的jump table!
.L4中有两个.L9入口,对应的是case 1和2。case 5被优化调用,因为Fall Through,因此有两个.L3入口。代码首先用入参与6比较,如果比6大,就直接到.L2,这里对应的是default。然后一个mov,这行mov的效果是,将rdi寄存器的高32位清零。最后,根据rdi寄存器的值,直接跳到jump table中的某个位置,jmp [QWORD PTR .L4[0+rdi*8]]
,这行汇编有两个[]
嵌套,这是Intel语法。
gcc在什么情况下会生成jump table?
《CSAPP》中是这样说的:case的数量要多一点,至少要4个,而且进入case的值的分布,要尽量在一个小范围内。
本文链接:https://cs.pynote.net/hd/asm/202307218/
-- EOF --
-- MORE --