3

基本的に、C 関数から返されたときに void* ポインターが配置されるレジスターを知る必要があります。私はこのコードを持っています:

void* kmalloc(unsigned int size)
{
    asm("mov %[size], %%esi"
    : /* no outputs */
    : [size] "m" (size)
    : "esi");
    asm("movl $9, %eax");
    asm("int $0x80");

}

アドレスをEAXに入れる必要があります。Cの戻り値はEAXに保存されていると思っていましたが、どうやらそうではありませんでした(ああ、私はGCC BTWを使用しています)。コンパイラの設定が原因で、EAX を返す方法が必要です。レジスタ int も機能しません。ポインタを返すために使用されるレジスタはありますか? それとも、スタックにプッシュされたようなものですか?

4

3 に答える 3

7

これは、インライン asm を記述する有効な方法ではありません。戻り値を正しいレジスターに入れても、コンパイラーは任意のエピローグ・コードを追加できるため、関数が実際に戻るまでに失われたり、上書きされたりする可能性があります。returnインライン asm の結果を返すには、出力制約とステートメントを使用する必要があります。

void* kmalloc(unsigned int size)
{
    void *p;
    asm("int $0x80" : "=a"(p) : "S"(size), "a"(9));
    return p;
}
于 2013-01-21T21:01:25.140 に答える
4

テストコード:

void * myfunc(void) { return (void *) 0x20341022; }

gcc --save-temps -O2 -c test.c( を使用して)コンパイルすると、次のようになります。

myfunc:
.LFB0:
    .cfi_startproc
    movl    $540282914, %eax
    ret
    .cfi_endproc

答えは明らかです。

于 2013-01-21T20:24:12.947 に答える
1

次のように、インライン アセンブリ コードが出力制約を使用して結果を返す方法を宣言する必要があります。

void* kmalloc(unsigned int size)
{
   void *result;
   asm("mov %[size], %%esi\n"
       "movl $9, %%eax\n"
       "int $0x80"
   : "=a" (result)
   : [size] "m" (size)
   : "esi");

   return result;
}

は、の内容を結果変数"=a"に移動するようにコンパイラに指示します。EAX

また、すべての asm ステートメントを 1 つのブロックにグループ化したことに注意してください。この方法では、各ステートメント自体ではなく、このブロックの入力/出力を指定するだけで済みます。

これをコンパイルするとgcc -O3 x.cpp -S、結果としてコンパイルされたコードが表示されます。

_kmalloc:
Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl    %edi, -4(%rbp)
    ## InlineAsm Start
    mov -4(%rbp), %esi
    movl $9, %eax
    int $0x80
    ## InlineAsm End
    popq    %rbp
    ret
Leh_func_end1:

オプティマイザは、result変数が に等しいEAXと判断するため、スタックに割り当てる必要がないことに注意してください。

于 2013-01-21T21:11:02.947 に答える