構造特有の命令を使えるようにするためのコード・ブロック
構文:
Asm 構造に依存する命令
記述:
Asm ブロックは、プログラムに特定の機械コード命令を挿入するために、使用されます。
目的は、言語の特徴を使って実現できない操作を実行するため、あるいは、性能敏感なコードのセクションを手で最適化するためです。
現在の FreeBASIC コンパイラは、現在、インテルの
80x86-ベースのマシンのためのコードを、生成するだけです。
しかし、将来、同じ命令セットをサポートしないプラットホームに、コンパイラを移植するかもしれません。
したがって、
Asm ブロックは、必要最小限で使用すべきです。そして、できれば、FreeBASIC だけでの代替手段を活用すべきです。
関数の戻り値は、下の例に示すように、角括弧の中で
Function キーワードを使って、設定します。
Asm ブロックのコメントは、通常の FreeBASIC の
コメント と、同じ構文です。
FreeBASIC のように、"
' " コメント とします。通常の ASM のような、"
; " ではありません。
x86 特定:
構文
インライン・アセンブラの構文は、インテル構文の簡易形式です。
インテル構文は、MASM、TASM、NASM、YASM、FASM などの x86 アセンブラの大部分で、使われます。
一般に、命令の行き先は、最初に、置かれます。その後ろに、ソースを続けます。
プログラムで定義された変数と関数は、Asm ブロックで、参照をつけられます。
FreeBASIC で使われるアセンブラは、GAS で、.intel_syntax noprefix 命令型を使います。そして、ASM ブロックは、スタック・フレーム参照のための局所変数名の代替以外は、変更せずに渡されます。コメントは、取り除かれます。
命令構文は、FASM 使用と、ほとんど同じです。1つの重要な違いは、GAS は、"ptr"という言葉を、サイズ設定の後ろに付ける必要がある点です。
' "n" と仮定するのは、FB の、グローバルまたはローカルの ULONG 変数です
mov eax, [n] ' OK: サイズは eax から明らかです。
inc [n] ' Not OK: サイズは与えられていません。
inc dword [n] ' Not OK: サイズは与えられましたが、GAS でまだ受け取られていません。
inc dword Ptr [n] ' OK: "ptr" は、ここで GAS によって必要です。
レジスタを保存する
ASM ブロックが開かれるとき、レジスタの
ebx,
esi,
edi は、スタックに押されます。ブロックが閉じられるとき、これらのレジスタは、スタックから元に戻ります。
これは、これらのレジスタが、x86 CPU を使用する、大部分、またはすべての OS で、保存される必要があるからです。
したがって、これらのレジスタを、自分で明示的に保存しなくても、使用できます。
esp と
ebp は、通常、局所変数を記述するのに使われるので、
esp と
ebp を変えるべきではありません。
注意: Naked 手続き内では、このようなレジスタの保存は行われません。
レジスタ名
x86 構造のためのレジスタの名前は、下の通り
Asm ブロックに書かれています:
- 4バイトの整数レジスタ:
eax, ebx, ecx, edx, ebp, esp, edi, esi
- 2バイトの整数レジスタ:
ax, bx, cx, dx, bp, sp, di, si
(4-byte e- レジスタの下位ワード)
- 1バイトの整数レジスタ:
al, ah, bl, bh, cl, ch, dl, dh
(2-byte -x レジスタの、下位と上位のバイト)
- 浮動小数点レジスタ:
st(0), st(1), st(2), st(3), st(4), st(5), st(6), st(7)
- MMX レジスタ (浮動小数点レジスタの別名):
mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7
- SSE レジスタ:
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
命令セット
以下の外部リンクを参照ください:
危険な指示
FreeBASIC コンパイラは、通常、非特権ユーザレベルで実行する x86 のために、32ビットのプロテクト・モード・コードを生成することに、注意してください。
したがって、特権があって敏感な命令は、アッセンブルできても、正しく動かないかもしれません。あるいは、実行時に、「一般保護違反」、「違法命令」、SIGILL エラーを引き起こすかもしれません。
下は、インテルPentium 4 と Xeon で、特権があって敏感な命令です:
- cli *1
- clts
- hlt
- in *1
- ins *1
- int *1
- into *1
- invd
- invlpg
- lgdt
- lidt
- lldt
- lmsw
- ltr
- mov to/from CRn, DRn, TRn
- out *1
- outs *1
- rdmsr
- rdpmc *2
- rdtsc *2
- sti *1
- str
- wbinvd
- wrmsr
- すべての SSE2 と、より高い命令 *2
*1:IOPL に敏感で、DOS でうまく行きます。
*2:CR4 で許可ビットに敏感です。下を参照下さい。
特権命令は、DOSで、Ring 0 DPMI カーネルで動くとき、「正しく」働くでしょう。これは、CWSDPMIか、WDOSXか、D3Xの(非デフォルト) Ring 0 バージョンと似ています。それにもかかわらず、DPMIコードから実行される場合、特権命令の大部分は、実際に役に立たなくて、危険です。
RDTSC (タイム・スタンプ・カウンターを読む)は、大部分、あるいは、すべての OS によって許容されて、見ることができます。
しかし、RDTSC の有用性は、マルチコアで、休止(ハイバーネイト)する CPU の出現によって、減少しました。
SSE2 と、より高い命令は、通常、CPU初期化後、「デフォルトで」障害があります。Windows と Linux は、それらを可能にします。DOSでは、それは、DPMI ホストの仕事です:
HDPMI32 は、それらを可能にして、CWSDPMIは、そうしないでしょう。
INT 命令は、DOSバージョン/目標だけで使用可能です。INT 命令は、リアルモードの DOS とわずかに異なった動きをする点に、注意して下さい。
FaqDOS を参照下さい。
セグメント・レジスタ(
cs,
ds,
es,
fs,
gs)を、Asm ブロックから変えるべきではありません。DOS ポートのあるケースを除いて(これらが、リアルモード DOS と同じように働いていないことに、注意してください。
FaqDOS を参照下さい。)。
オペレーティング・システムや、DPMI ホストは、メモリ管理に責任があります。
プロテクト・モードにおけるセグメント(セレクタ)の意味は、リアルモード・メモリ・アドレッシングと、極めて異なっています。
これらの「危険な」命令は、不十分な特権で走らせた場合でも、必ず「目に見える」クラッシュを起こすとは限らないことに注意して下さい。 - OS か DPMI ホストは、それらを、機能的に(HDPMI32の下で働く、いくらかの CRx から読む)か、ダミー(何も起こらないで、命令は黙って渡されます。NOP のように)として、「模倣する」と決めることができます。
例:
'' これは x86構造 のための例です。
Function AddFive(ByVal num As Long) As Long
Asm
mov eax, [num]
add eax, 5
mov [Function], eax
End Asm
End Function
Dim i As Long = 4
Print "4 + 5 ="; AddFive(i)
Sleep
FreeBASIC の Assembler は、AS / GAS、GCC のアセンブラで、外部プログラムです。
若干の癖が、あてはまります:
-
ASM ブロックのための、FBC によって返されるエラー行は、FB ソース・ファイルと関連しません。
FBC が、単純に、AS によって返されたエラーを表示するとき、行は、アセンブリ・ファイルに関連します。
FreeBASIC にエラーを保存させるようにするためには、コンパイラは、-R オプション(ASM ファイルを削除しない)で呼び出さなければなりません。
-
ラベル名は、ASM ブロックの中で、大文字と小文字を区別しています。
方言差:
-
別名 __Asm と共に参照をつけないと、-lang qb 方言で利用できません。
QBからの違い:
参照: