Когда я компилирую оператор switch с оптимизацией в GCC, он устанавливает таблицу переходов следующим образом:
(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
и ADD
лучшим способом сделать это,
movsxd rax, dword [rdx + rdi*4]
add rax, rdx
Разве это не то же самое, что использование LEA
с 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;
}