アセンブラディレクティブ

ysd@KLab > PowerPC > ディレクティブ
.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