x86インラインアセンブラ (2)

x86インラインアセンブラ - 滴了庵日録 のつづき。

メモ

  • 配列もC言語の変数名がそのまま使える。
  • ただし、アドレスのスケーリングは明示する必要がある。
  • 32ビット整数ならスケーリングは *4 (任意の数を指定できるわけではない)。
  • ブロック転送には、esiとediをセットで使う。
  • 8086のころは ds:[si] と es:[di]がセットだったが、今はセグメントレジスタ(dsやes)は使わない。
  • ストリング命令(movsbなど)はリピートプリフィックス命令(repなど)とセットで使う。

配列の総和を求めるコード

#include <stdio.h>

int main(void)
{
    int a[5] = {1, 2, 3, 4, 5};
    int sum;

    __asm{
        xor eax, eax
        xor ecx, ecx
    _LOOP:
        add eax, a[ecx * 4] // 32ビット整数なら*4 
        inc ecx
        cmp ecx, 5
        jl _LOOP
        mov sum, eax
    }
    printf("%d\n", sum);
    return 0;
}

スタックを使う

#include <stdio.h>

int main(void)
{
    int a, b, c;
    __asm{
        push 1
        push 2
        push 3
        pop a // a に 3 が入る
        pop b // b に 2 が入る
        pop c // c に 1 が入る
    }
    printf("%d %d %d\n", a, b, c);

    return 0;
}

文字列のコピー

int main(void)
{
    char a[] = "hello, world!\0";
    char b[14];

    __asm{
        mov ecx, 14 // カウントレジスタ
        lea esi, a  // ソースインデックス
        lea edi, b  // デスティネーションインデックス
        cld         // アドレスはインクリメント sldならデクリメント
        rep movsb   // ecxぶんだけ1バイトずつコピー
    }
    printf("%s\n", b);
    return 0;
}