-1

次の C コードをアセンブリに変換しようとしています。

void write (int bitpos, unsigned short sample)
{
    int pos = bitpos / 16;
    int posA = bitpos - pos * 16;
    unsigned short write1 = sample >> posA;
}

シフト操作でエラーが発生し続けます。本でいくつかの例を見ましたが、何が問題なのかわかりません。シフトしたい量が変数だからかもしれないと思います。これを達成する正しい方法は何だろうと思っていましたか?

これが私が試したことです:

//int pos = bitpos / 16;
mov eax, 0
mov eax, [bitpos] // eax= bitpos
cdq
mov ecx, 16         
idiv ecx        //ecx = pos

//int posA = bitpos - pos * 16;
mov ebx, ecx    //ebx = pos
imul ebx, 16    // ebx = pos*16
sub eax, ebx    // eax = posA

//unsigned short write1 = sample >> posA;
mov bx, [sample]
shr bx, eax // This is the part that is not working.

エラーの内容: オペランドの型が正しくありません。エラー コード: C2415

4

1 に答える 1

2

write()関数には戻り値も副作用もありません (グローバル変数への書き込み、システム呼び出しはなく、関数が戻るときに破棄されるいくつかのローカル変数のみを設定します) 。gcc と同じように、空の関数に最適化することができますし、そうするべきです。

global write
write:
    ret

関数が変数を返すと仮定して、write1変数を計算する必要があります。

gcc -Og(デバッグ用に最適化)常にメモリに保存/再ロードしない、読みやすいasmを作成します。 gcc -m32 -Og -fverbose-asm -masm=intelを放出します:

# see the godbolt link for colour-coded mapping of source lines to asm lines
write(int, unsigned short):
    mov edx, DWORD PTR [esp+4]  # bitpos, bitpos
    lea eax, [edx+15]   # tmp98,
    test    edx, edx    # bitpos
    cmovns  eax, edx    # tmp98,, bitpos, bitpos
    sar eax, 4  # tmp99,
    neg eax # tmp101
    sal eax, 4  # tmp102,
    mov ecx, eax    # tmp102, tmp102
    add ecx, edx    # posA, bitpos
    movzx   eax, WORD PTR [esp+8]   # D.2591, sample
    sar eax, cl # D.2591, posA
    ret

関数パラメーターはグローバルではなく関数パラメーターであるため、スタックから関数パラメーターをロードする方法に注意してください。(あなたのコード[bitpos]は、戻りアドレスの後のスタックの最初の位置ではなく、グローバルを参照します[esp+4]。) 64 ビット ABI はレジスタで引数を渡すので、よりクリーンなコードが得られます。

条件付き移動コードが存在するのは、負の数の整数除算の C セマンティクスが、算術右シフトとは異なる結果をもたらす (四捨五入が異なる) ためです。シフトに比べて非常にコストがかかるためidiv、追加の命令を使用してシフトを設定する価値があります。bitpos署名されていない場合は、 shr.

完全な最適化をオンにすると、gcc はより効率的な方法を見つけて、演算の一部をまとめます。(つまり、最も近い 16 の倍数に丸めるために 16 で割ってから 16 を掛けることは、andこれらのビットをマスクするために single で実装されます。)

話の教訓:何かを行う方法についてのインスピレーションを得るためにコンパイラの出力をいつでも見ることができ、最初は思いもよらなかったトリックがよく見られます。

于 2015-11-13T22:48:43.657 に答える