sol*_*ego 2 assembly x86-64 switch-statement
源代码
void switch_eg(long x, long n, long* dest) {
long val = x;
switch(n) {
case 0:
val *= 13;
break;
case 2:
val += 10;
case 3:
val += 11;
break;
case 4:
case 6:
val += 11;
break;
default:
val = 0;
}
*dest = val;
}
Run Code Online (Sandbox Code Playgroud)
对应的汇编代码
.LFB0:
// x in %rdi, n in %rsi, *dest in %rdx
cmpq $6, %rsi
ja .L8 // if n > 6, switch->default
-------------------------
leaq .L4(%rip), %rcx
movslq (%rcx,%rsi,4), %rax
addq %rcx, %rax
jmp *%rax
-------------------------
.L4:
.long .L3-.L4 // case 0
.long .L8-.L4 // case 1
.long .L5-.L4 // case 2
.long .L6-.L4 // case 3
.long .L7-.L4 // case 4
.long .L8-.L4 // case 5
.long .L7-.L4 // case 6
.L3:
leaq (%rdi,%rdi,2), %rax // %rax = 3 * val
leaq (%rdi,%rax,4), %rdi // val = 4 * 3 * val + val = 13val
jmp .L2 // break
.L5:
addq $10, %rdi // val += 10
.L6:
addq $11, %rdi // val += 11
.L2:
movq %rdi, (%rdx) // *dest = val
ret // return
.L7:
addq $11, %rdi // val += 11
jmp .L2 // break
.L8:
movl $0, %edi // val = 0
jmp .L2 // break
Run Code Online (Sandbox Code Playgroud)
谁能解释一下下面这段汇编代码的含义?
leaq .L4(%rip), %rcx
movslq (%rcx,%rsi,4), %rax
addq %rcx, %rax
jmp *%rax
Run Code Online (Sandbox Code Playgroud)
在我看来,
leaq .L4(%rip), %rcx
%rcx 接收跳转表数组的首地址
movslq (%rcx, %rsi, 4), %rax
%rax 接收具体的数组元素值,即case对应的操作的地址
但我不知道addq %rcx, %rax这里的意思是什么...
谁能帮助我...谢谢!
跳转表实际上不是用来包含跳转地址的,而是包含偏移量的。看 (.L3-.L4)。
当从表中取出偏移量时,需要加上表的基址,位于leaq .L4(%rip), %rcx。
该方案使得目标文件可重定位;并且使用符号扩展加载允许使用 32 位整数来解码偏移量以节省空间。