【发布时间】:2017-01-19 02:40:44
【问题描述】:
我一直在努力学习为 AMD64 处理器编写汇编代码。我一直在看 gcc 生成的代码。最终,我开始看到诸如
之类的说明 call *(%rax)
操作数前面的 * 是做什么的?在我正在阅读的 System V ABI 文档中出现了类似的情况,上面的答案将帮助我继续。以下是上下文中使用的语法示例,取自 System V ABI 文档本身:
// System V ABI suggested implementation of a
// C switch statement with case labels 0, 1, and 2,
// and a default label.
// Jump to the default case if the control variable is
// less than 0.
cmpl $0, %eax
jl .Ldefault
// Jump to the default case if the control variable is
// greater than 2.
cmp $2, %eax
jg .Ldefault
movabs $.Ltable, %r11
jmpq *(%r11,%eax,8) /* Here is that syntax. */
.section .lrodata,"aLM",@progbits,8
.align 8
.Ltable: .quad .Lcase0
.quad .Ldefault
.quad .Lcase2
.quad .previous
.Ldefault:
// Code for default case
.Lcase0:
// Code for case 0
.Lcase1:
// Code for case 1
.Lcase2:
// Code for case 2
【问题讨论】:
-
看起来像一个指针解引用运算符。
-
当你用它组装一条指令和一个不带它的指令并检查机器代码时你发现了什么?
-
我在查看编译器生成的代码时第一次遇到它,并且无法重现我在做什么。我终于使用了fuz的答案并尝试了(在C中) void (*array[3])();数组[0] = f; (*数组[0])();在生成的代码中,该函数被加载到 %rdx 中,然后被称为“call *%rdx”。奇怪的是,同样不适用于不在数组中的函数指针。