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

fastcall

Intel 386では、fastcall属性により、コンパイラはレジスタECXの最初の引数(積分型の場合)とレジスタEDXの2番目の引数(積分型の場合)を渡します。後続およびその他の型指定された引数は、スタックに渡されます。呼び出された関数は、引数をスタックからポップします。引数の数が可変の場合、すべての引数がスタックにプッシュされます。

次のサンプルコードで使用します。

__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 に答える