当我在 GCC 中编译一个带有优化的 switch 语句时,它会设置一个像这样的跳转表,
(fcn) sym.foo 148
sym.foo (unsigned int arg1);
; arg unsigned int arg1 @ rdi
0x000006e0 83ff06 cmp edi, 6 ; arg1
0x000006e3 0f87a7000000 ja case.default.0x790
0x000006e9 488d156c0100. lea rdx, [0x0000085c]
0x000006f0 89ff mov edi, edi
0x000006f2 4883ec08 sub rsp, 8
0x000006f6 486304ba movsxd rax, dword [rdx + rdi*4]
0x000006fa 4801d0 add rax, rdx ; '('
;-- switch.0x000006fd:
0x000006fd ffe0 jmp rax ; switch table (7 cases) at 0x85c
movsxd rax, dword [rdx + rdi*4]
add rax, rdx
LEA
这和使用with不一样吗displacement
lea rax, [rdx + rdi*4 + rdx]
我突然想到我可能不明白这里发生了什么。RDX
似乎是跳表的开始。RDI
是 switch 语句的传入参数。为什么我们要添加RDX
两次?
这是我正在编译的 switch 语句-O3
,
int foo (int x) {
switch(x) {
//case 0: puts("\nzero"); break;
case 1: puts("\none"); break;
case 2: puts("\ntwo"); break;
case 3: puts("\nthree"); break;
case 4: puts("\nfour"); break;
case 5: puts("\nfive"); break;
case 6: puts("\nsix"); break;
}
return 0;
}