アセンブラ言語は、コンピュータの命令を直接(と言っても機械語でもありませんが、ほぼ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命令で。
投稿日時 : 2008年3月25日 18:18