gpt4 book ai didi

c++ - 在内联汇编中使用函数范围的标签

转载 作者:行者123 更新时间:2023-11-28 07:55:56 25 4
gpt4 key购买 nike

我在带有 Eclipse CDT 和 gdb 的 64 位小端 Ubuntu 12.04 LTS 上使用 gcc-4.7 在 C++ 中使用内联汇编。我正在尝试做的事情的总体方向是为一些深奥的基于堆栈的编程语言制作某种字节码解释器。

在这个例子中,我一次处理 4 位指令(实际上这取决于指令),当没有更多的非零指令时(因为 0 将是 nop)我读取下一个 64 -位字。

不过我想问一下,如何在内联汇编中使用函数范围的标签?

似乎汇编中的标签是全局的,这是不利的,而且我找不到从汇编语句跳转到 C++ 函数范围标签的方法。

以下代码是我正在尝试做的示例(注意注释):

  ...
register long ip asm("r8");
register long buf asm("r9");
register long op asm("r10");
...
fetch:
asm("mov (%r8), %r9");
asm("add $8, %r8");
control:
asm("test %r9, %r9");
asm("jz fetch"); // undefined reference to `fetch'
asm("shr $4, %r9");
asm("mov %r9, %r10");
asm("and $0xf, %r10");
switch (op) {
...
}
goto control;

最佳答案

请注意 gcc 内联 asm 文档中的以下注释:

Speaking of labels, jumps from one `asm' to another are not supported. The compiler's optimizers do not know about these jumps, and therefore they cannot take account of them when deciding how to optimize.

您也不能依赖在一个 asm 中设置的标志在下一个中可用,因为编译器可能会在它们之间插入一些东西

对于 gcc 4.5 及更高版本,您可以使用 asm goto 来执行您想要的操作:

fetch:
asm("mov (%r8), %r9");
asm("add $8, %r8");
control:
asm goto("test %r9, %r9\n\t"
"jz %l[fetch]" : : : : fetch);

请注意,您的所有其余 asm 都是完全不安全的,因为它直接使用寄存器而不在其读/写/破坏列表中声明它们,因此编译器可能会决定在其中放置其他内容(尽管变量带有 asm 对它们的声明——它可能会认为它们已经死了,因为它们从未被使用过)。因此,如果您希望这实际上适用于 -O1 或更高版本,则需要将其写为:

  ...
long ip;
long buf;
long op;
...
fetch:
asm("mov (%1), %0" : "=r"(buf) : "r"(ip));
asm("add $8, %0" : "=r"(ip) : "0"(ip));
control:
asm goto("test %0, %0\n\t"
"jz %l[fetch]" : : "r"(buf) : : fetch);
asm("shr $4, %0" : "=r"(buf) : "0"(buf));
asm("mov %1, %0" : "=r"(op) : "r"(buf));
asm("and $0xf, %0" : "=r"(op) : "r"(op));

此时,将其编写为 C 代码会容易得多:

long *ip, buf, op;

fetch:
do {
buf = *op++;
control:
} while (!buf);
op = (buf >>= 4) & 0xf;
switch(op) {
:
}
goto control;

关于c++ - 在内联汇编中使用函数范围的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12730468/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com