1

次の IA32 アセンブラー コードを解釈し、同等の効果を持つ関数を C で記述しようとしています。

parametersおよびがa、オフセットおよびregister 内のアドレスに関連するメモリ位置に格納されており、C の適切な関数プロトタイプが次のようになるとします。bc81216%ebpequivFunction(int a, int b, int c);

movl 12(%ebp), %edx // store b into %edx
subl 16(%ebp), %edx // %edx = b - c
movl %edx, %eax     // store b - c into %eax
sall $31, %eax      // multiply (b-c) * 2^31
sarl $31, %eax      // divide ((b-c)*2^31)) / 2^31
imull 8(%ebp), %edx // multiply a * (b - c) into %edx
xorl %edx, %eax     // exclusive or? %edx or %eax ?  what is going on here?

まず、アセンブリを正しく解釈しましたか? もしそうなら、これをCに翻訳するにはどうすればよいですか?

4

2 に答える 2

1

sall/コンボには、eaxのsarlすべてのビットを 0 番目のビットの値に設定する効果があります。まず、sal0 番目のビットを 31 番目の位置に移動し、符号ビットにします。次にsar、それを元に戻し、残りのレジスターをそのコピーで埋めます。それを除算/乗算と考えないでください。実際には「s」が表すビットごとのシフトと考えてください。

したがって、bc が奇数の場合、eax は 0xffffffff (-1) になり、偶数の場合は 0 になります。したがって、imullコマンドは edx に a の負数またはゼロを配置します。最後xorの は、 のすべてのビットを反転するかa(これxorは 1 の場合です)、ゼロ値のままにします。

このスニペット全体には人工的な雰囲気があります。これは宿題ですか?

于 2013-11-06T19:32:21.697 に答える
1

シフトは、乗算/除算ではなく、符号ビットを直接操作するため、コードは大まかに

int eqivFunction(int a, int b, int c) {
    int t1 = b - c;
    unsigned t2 = t1 < 0 ? ~0U : 0;
    return (a * t1) ^ t2;
}

別の方法:

int eqivFunction(int a, int b, int c) {
    int t1 = b - c;
    int t2 = a * t1;
    if (t1 < 0) t2 = -t2 - 1;
    return t2;
}

もちろん、C コードは整数オーバーフローに対して未定義の動作をしますが、アセンブリ コードは明確に定義されているため、C コードはすべての場合で同じことを行うとは限りません (特に、別のアーキテクチャでコンパイルする場合)。

于 2013-11-06T19:34:17.093 に答える