当我在 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
Is the MOVSXD https://c9x.me/x86/html/file_module_x86_id_206.html and ADD https://c9x.me/x86/html/file_module_x86_id_5.html最好的方法是,
movsxd rax, dword [rdx + rdi*4]
add rax, rdx
这不是和使用一样吗LEA https://c9x.me/x86/html/file_module_x86_id_153.html 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;
}