在内联程序集中使用函数范围的标签 我在C++中使用内嵌程序集,使用GCC-4.7,在Eclipse CDT和GDB上的64位小EndiaUbuntu 12.04 LTS上。我尝试做的主要方向是为一些深奥的基于堆栈的编程语言制作某种字节码解释器

在内联程序集中使用函数范围的标签 我在C++中使用内嵌程序集,使用GCC-4.7,在Eclipse CDT和GDB上的64位小EndiaUbuntu 12.04 LTS上。我尝试做的主要方向是为一些深奥的基于堆栈的编程语言制作某种字节码解释器,c++,gcc,assembly,label,C++,Gcc,Assembly,Label,在本例中,我一次处理4位指令(实际上这取决于指令),当不再有非零指令(因为0将是nop)时,我读取下一个64位字 但是我想问,如何在内联程序集中使用函数作用域标签? 似乎汇编中的标签是全局的,这是不利的,我无法找到从汇编语句跳转到C++函数范围标签的方法。 下面的代码是我尝试执行的一个示例(请注意注释): 您应该能够做到这一点: fetch: asm("afetch: mov(%r8), %r9"); ... asm("jz afetch"); 或者,将标签放在单独的asm(“af

在本例中,我一次处理4位指令(实际上这取决于指令),当不再有非零指令(因为0将是nop)时,我读取下一个64位字

但是我想问,如何在内联程序集中使用函数作用域标签?

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

下面的代码是我尝试执行的一个示例(请注意注释):


您应该能够做到这一点:

fetch:
  asm("afetch: mov(%r8), %r9");
  ...
  asm("jz afetch");

或者,将标签放在单独的
asm(“afetch:”)中也应该起作用。注意不同的名称以避免冲突-我不完全确定这是否必要,但我怀疑是这样。

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

说到标签,不支持从一个“asm”跳到另一个。 编译器的优化器不知道这些跳转,因此 在决定如何优化时,他们不能考虑这些因素

您也不能依赖在一个
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;

但是如果我有另一个具有相同标签名的函数呢
void foo(){asm(“label:”)}void bar(){asm(“label:”)}
无效。请使用本地标签,即
格式的标签,并使用
f
b
确认引用-
asm(“0:nop”);asm(“jmp 0b”)
long *ip, buf, op;

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