1

関数の引数がターゲットの単語サイズに埋め込まれていることは知っていますが、何を使用しますか?

特にx86LinuxGNUツールチェーンのコンテキストでは、これらの関数は何を返しますか?

int iMysteryMeat(short x)
{
    return *((int *)&x);
}
unsigned uMysteryMeat(unsigned short x)
{
    return *((unsigned *)&x);
}

問題は、アセンブリで関数を手動でコーディングするときに、「大きな」コンテキストで使用する前に、「小さな」引数をマスクまたは符号拡張して滅菌する必要があるかどうかです(andlimull)。

この場合、より一般的な標準またはクロスプラットフォームの標準があるかどうかにも興味があります。

4

3 に答える 3

2

これはABIによって異なります。ABIは、小さな引数を呼び出し元または呼び出し先(およびその方法)によって拡張するという選択を指定する必要があります。残念ながら、ABIのこの部分は多くの場合、指定が不十分であり、コンパイラーによって選択が異なります。gccしたがって、異なるレガシーコンパイラでコンパイルされたコード間の非互換性を防ぐために、ほとんどの最新のコンパイラ(特にonについて知ってi386います)は注意を怠り、両方を実行します。

int a(short x) {
  return x;
}
int b(int x);
int c(short x) {
  b(x);
}

gcc -m32 -O3 -S tmp.c -o tmp.s

_a:
pushl   %ebp
movl    %esp, %ebp
movswl  8(%ebp),%eax
leave
ret

_c:
pushl   %ebp
movl    %esp, %ebp
movswl  8(%ebp),%eax
movl    %eax, 8(%ebp)
leave
jmp _b

aは、その引数について拡張ルールを想定していませんが、それ自体を拡張していることに注意してください。同様に、c引数をb(末尾呼び出しを介して)渡す前に必ず拡張してください。

于 2012-09-05T22:26:29.540 に答える
0

キースの答えは私の質問の精神に沿ったものですが、アレックスの要求に従って、私はこれを自分で試してみようと思いました。

興味深いことに、この場合、私の例に対するより文字通りの答えは「ゴミ」です。

#include <stdio.h>

int iMysteryMeat(short x)
{
    return *((int *)&x);
}
unsigned uMysteryMeat(unsigned short x)
{
    return *((unsigned *)&x);
}
int main()
{
    printf("iMeat: 0x%08x\n", iMysteryMeat(-23));
    printf("uMeat: 0x%08x\n", uMysteryMeat(-23));
    return 0;
}

gcc -m32 -S meat.c

iMysteryMeat:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movw    %ax, -4(%ebp)
    leal    -4(%ebp), %eax
    movl    (%eax), %eax
    leave
    ret
uMysteryMeat:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movw    %ax, -4(%ebp)
    leal    -4(%ebp), %eax
    movl    (%eax), %eax
    leave
    ret

./a.out
iMeat: 0x0804ffe9
uMeat: 0x0043ffe9

ご覧のとおり、通常の符号拡張プロトコルがオーバーライドされるだけでなく(つまり、Keithのものと比較してa())、実際にはxが初期化されていないスタックスペースに移動されmovw、戻り値の上半分が何main()を与えてもガベージになります。

したがって、繰り返しになりますが、ouahが言ったように、これをCで行うことは決してなく、アセンブリ(または一般的には実際)では、常に入力を滅菌してください

于 2012-09-05T23:08:17.557 に答える
0
int iMysteryMeat(short x)
{
    return *((int *)&x);
}

これはCでの未定義の動作であり、エイリアシングルールに違反し、アライメント要件にも違反する可能性があります。これshortをしないでください。

于 2012-09-05T22:10:20.190 に答える