アセンブラディレクティブ
.sファイルを書くにあたって必要なディレクティブの解説。
.section
.sectionに類するディレクティブ。
- .const
- .section __TEXT, __constに同じ。
この領域に書かれたデータやジャンプテーブルは定数と見なされる。
- .cstring
- .section __TEXT, __cstring, cstring_literalsに同じ。
C用の文字列(終端に必ず\0が置かれているもの)を書く領域。
- .data
- .section __DATA, __dataに同じ。
非定数データはこの領域中に宣言する。
- .lazy_symbol_ptr
- .section __DATA, __la_symbol_ptr,lazy_symbol_pointersに同じ。
この領域には、外部に宣言された関数や変数のシンボルを定義する。リンク時に、シンボルが指すアドレスがこの領域にセットされる。このディレクティブの使い方の例は、最後のHello World参照。
- .picsymbol_stub
- .section __TEXT, __picsymbol_stub, symbol_stubs, pure_instructions NBYTESに同じ。(NBYTESはその時のアライン)
この領域には、このファイル内では未定義の関数へアクセスするための処理を記述する。OS Xでは呼び出し位置に依存しない関数呼び出しを行う必要があるので、symbol_stubではなく、こちらを使わなければならない。このディレクティブの使い方の例は、最後のHello World参照。
- .text
- .section __TEXT, __text, regular, pure_instructionsに同じ。
命令を記述する部分であると宣言する。ここには定数もデータも置くことはできない。
マクロ/条件分岐
マクロの宣言や、条件による処理切りかえ用のディレクティブ。
- .else
- .ifや.elseiifの条件を満たさない場合に実行される処理を記述する。
- .elseif expression
- .ifや.elseifの条件を満たさない場合に、さらに別の条件expressionが満たされる実行される処理を記述する。.elseifや.endifで終了する。
- .endif
- .ifで開始したマクロ分岐を終了する。
- .endmacro
- .macroで開始したマクロ記述を終了する。
- .if expression
- expressionに入力した式の条件に見合う場合、.ifから.elseか.elseifまたは.endifが来るまでの記述を有効にする。
- .macro macro_name
- macro_nameという名前の疑似命令を作成する。このディレクティブを使って生成した疑似命令は引数をいくらでも受け付けることができる。$0が第一引数で、以降、$1、$2...と続く。また、受け取った引数の個数を得るには$nと書く。引数には基本的にはなんでも入るし、アセンブラの文法に沿っている限り、引数として受け取ったものは何にでも使える。.endmacroでマクロの記述は終了する。
その他のディレクティブ
- .align align_expression
- align_expressionに与えられた値分だけの2の乗数境界に、アセンブラデータを配置していくように指示する。これを使わないと、コンパイラはバイト境界を無視してしまうので、必ず指定すること。
例えば、命令や整数データは4byte領域(.align 2)に配置する。倍精度浮動小数は8byte領域(.align 3)。ベクトルデータは16byte領域(.align 4)である。
- .byte(.short/.long/.quad) expression [, expression ...]
- .byteは1byte、.shortは2byte、.longは4byte、.quadは8byteのサイズのデータ領域にexpressionで指定した値を入れて作成する。,で区切ることで、まとめて作成することもできる。
- .comm name, size
- nameというシンボル名で、size分の大きさのデータを作成する。
- .globl symbol_name
- symbol_nameには外部に公開するラベル名か、.setにより作成したラベル名を書く。symbol_nameは外部に公開される。
- .include "file_name"
- file_nameに与えられたファイル名のアセンブラファイルの中身を、このディレクティブを使った位置に展開する。
- .indirect_symbol symbol_name
- symbol_nameはラベル名。
外部に公開する変数や、外部に公開されている変数や関数のアドレスをセットするのに使う。このセクションは、必ずsymbol_stub, lazy_symbol_pointers, non_lazy_symbol_pointersのうちのどれかのセクション内で使うこと。使用例はHello World参照。
- .lcomm name, size
- commとほぼ同じであるが、このディレクトリブを使って作成したデータはファイル内のみで参照可能である。また、このディレクティブで生成したデータは0初期化される。
- .single(double) number [, number ...]
- singleは単精度、doubleは倍精度の浮動小数値の領域に、numberで指定した値を入れて作成する。,で区切ることで、まとめて作成することもできる。
書き方は以下の通り
.data
.single 3.33333333e-01
.double 1.000001000000e-00
.single +Infinity
.double -Infinity
.single NaN
PowerPCアセンブラ版Hello World
.data
.align 2
_hw: .ascii "Hello World\n\0" ;printfで表示する文字列
.text
.align 2
.globl _main
_main: mflr r0
bl L1$pb ;この位置のアドレスを、リンクレジスタを利用して取得する
L1$pb: mflr r10
stw r0, 8(r1) ;スタックフレームの構築
stwu r1, -64(r1) ; (24 + 32 + x) % 16 == 0 ... 64(スタックフレームの最小サイズ)
addis r10, r10, ha16(_hw - L1$pb) ;Hello Worldのポインタを得て引数に渡す
la r3, lo16(_hw - L1$pb)(r10)
bl L_printf$stub ; printf("hello world!");関数呼び出し
lwz r0, 72(r1) ;
addi r1, r1, 64 ;スタックフレームの破棄
mtlr r0 ;
blr ;終了
.text ;リンク領域
.picsymbol_stub
.align 2
L_printf$stub: ;printf呼び出しルーチン
.indirect_symbol_printf
mflr r0
bl L0$_printf
L0$_printf:
mflr r11
addis r11, r11, ha16(L_printf$lazy_ptr - L0$_printf)
mtlr r0
lwz r12, lo16(L_printf$lazy_ptr - L0$_printf)(r11)
mtctr r12
addi r11, r11, lo16(L_printf$lazy_ptr - L0$_printf)
bctr
.data ;printfのアドレスリンク
.lazy_symbol_pointer
L_printf$lazy_ptr:
.indirect_symbol _printf
.longdyld_stub_binding_helper