目次

ニュース

日記カテゴリ

書庫

2008年3月25日

アセンブラ言語は、コンピュータの命令を直接(と言っても機械語でもありませんが、ほぼ1対1で対応するってことで)記述する言語です。

ですが、この言語を使ってプログラミングを行うと、メモリの値を直接のデータアドレスで指定しないといけません。

もともとアセンブラには変数っていう概念はないのでアドレスを計算してあげなければいけないんですけど。

そこで、Visual C++のインラインアセンブラを使うと、C++コードの途中にアセンブラ言語を混ぜることができます。

こうすることで、必要最低限の作業量でMMXやSSEなど、通常のコンパイラが吐いてくれないアセンブラ命令を使うことができたり、CPUIDなどの特殊命令も実行することができます。

インラインアセンブラは次のような記述で使えます。

001 __asm {
002     // インラインアセンブラコードをここに記述
003 }
004 
こんな感じ。

まずは、C++で変数を定義して、そこにアセンブラでデータを突っ込んでみましょう。

データのロードにはmov命令を使います。たぶんアセンブラで最も使う命令と思われます。

001 #include <iostream>
002 void main()
003 {
004     int a;
005     __asm {
006         mov a, 256;
007     }
008     std::cout << "a = " << a << std::endl;    // a = 256 と出力される
009 }

 

MOV命令は

mov dest, src

dest レジスタ,メモリ

src レジスタ,メモリ,即値

となっています。ですので、

001 {
002     int a,b;
003     b = 256;
004     __asm {
005         mov a, b;
006     }
007 }
008 

というのは動きません。

次に、足し算命令を使ってみましょう。

足し算命令はaddを使います。

add dest, src

flag OF, SF, ZF, AF, CF, PF

dest レジスタ,メモリ

src レジスタ,メモリ,即値

これをインラインアセンブラで記述してみます。

001#include <iostream>
002void main()
003{
004    int a;
005    __asm {
006        mov a, 256;
007        add a, 128;
008    }
009    std::cout << "a = " << a << std::endl;    // a = 384 と出力される
010}

このときに、MOV命令と違って演算を行うとフラグが立ちます。これは、算術演算を行った時の結果に対して出てくるものです。

CF(キャリーフラグ)

算術命令を行った際に、最上位ビットが繰り上げもしくは繰り下げを行ったときにセットされます。

PF(パリティーフラグ)

演算結果のパリティビット。二進数で1の数が偶数のときに1になる。使ったことがないw

AF(補助フラグ)

あまり使わない…かも。調べて分かったら書く。

ZF(ゼロフラグ)

演算結果が0になった場合に1になる。とても使う。

SF(サインフラグ)

演算結果がマイナスになったときに1になる。signedコードなので基本的には最上位ビットと同じ。

OF(オーバーフローフラグ)

ビットが越えたときに1になる。たとえば、

mov AX, 65530;
add AX, 100;

とすると、AXレジスタは16ビットなのでオーバーフローとなり、ビットが立ちます。

符号付き演算で、符号が変化したときに1になります。

この値をチェックすることもあります。たとえば、INT 21Hなんかは異常時にCFが1になってくるので、関数の戻り値みたいに使う人もいたり。

 

といことで、次回はCPUID命令で。

posted @ 18:18 | Feedback (280)

Blog 利用状況

コミュニティ

プロファイル