11

在 gcc 中,您可以使用以下语法声明应将局部变量放入寄存器中。

register int arg asm("eax");

在我在互联网上找到的一些旧代码中,此语法用于声明函数的参数应在寄存器中传递:

void foo(register int arg asm("eax"))

但是当我尝试这个例子时:

/*
   Program to demonstrate usage of asm keyword to allocate register for a variable.
*/
#include <stdio.h>

/* Function with argument passed in register */
void foo(register int arg asm("eax") )
{
    register int loc asm("ebx");
    loc = arg;
    printf("foo() local var: %d\n", loc);
}

int main(void)
{
    foo(42);
    return 0;
}

并用 gcc 编译我得到一个错误:

gcc main.c -o test-asm.exe
main.c:7:27: error: expected ';', ',' or ')' before 'asm'

现在我的问题是:
上面的 asm 语法是否正确,在 gcc 中,即对于函数的形式参数?
gcc曾经支持过这个吗?
如果这不是正确的语法,那么如何实现呢?

谢谢,
//jk

4

1 回答 1

2

我知道的唯一方法是使用 fastcall 属性:

(GCC 手册第 6.30 节)http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#Function-Attributes

快速呼叫

在 Intel 386 上,fastcall 属性使编译器在寄存器 ECX 中传递第一个参数(如果是整数类型),在寄存器 EDX 中传递第二个参数(如果是整数类型)。随后的和其他类型的参数在堆栈上传递。被调用的函数将从堆栈中弹出参数。如果参数的数量是可变的,则所有参数都被压入堆栈。

在以下示例代码中使用它:

__attribute__((fastcall,noinline)) int add (int a, int b)
{
  return a + b;
}

int main () {
  return add (1, 2);
}

将导致:

    .file   "main.c"
    .text
.globl add
    .type   add, @function
add:
    pushl   %ebp
    movl    %esp, %ebp
    leal    (%edx,%ecx), %eax
    popl    %ebp
    ret
    .size   add, .-add
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    movl    $2, %edx
    movl    $1, %ecx
    call    add
    popl    %ebp
    ret
    .size   main, .-main

不要忘记在其他翻译单元的任何声明中提及 fastcall 属性,否则可能会发生相当奇怪的事情。

于 2013-03-04T20:23:01.463 回答