フリースタンディング環境

フリースタンディング環境（フリースタンディングかんきょう、）はC言語およびC++の実行環境の一種である。対義語はホスト環境。
概要.
フリースタンディング環境は、OSなしでプログラムを実行しなければいけない環境を指すCおよびC++の用語である。これはCの規格書およびC++の規格書に記載されている。OSなしで実行するプログラムとは組み込み用のプログラムであったりOSそのものである。ホスト環境は逆にOSが存在することを想定しており一般的なアプリケーションソフトウェアやミドルウェアを指す。ただし、フリースタンディング環境用としてつくられたプログラムはOSなしで動作する必要はない。OS上で動くフリースタンディング環境のプログラムとしてはデモシーン用のプログラムが代表的である。
実行環境を指定しない場合は、ホスト環境を対象にしていることがある。組み込みシステムではフリースタンディング環境を対象にすることもある。μITRONはオペレーティングシステムの一種であるが、フリースタンディング環境を選択しているシステムとして提供していることがある。TOPPERSプロジェクトのTRON系、OSEK系などで、模擬環境でないものは、フリースタンディング環境での利用を想定してソースコードを提供している。
ホスト環境との違い.
フリースタンディング環境はOSから提供される機能が無いこと、プログラムを書き込む記憶領域が狭いことを想定し標準Cライブラリとしてホスト環境で要求する関数はCでは一切、C++では言語機能を実装するに最低限しか要求しない。Cにおいては定義を書いたヘッダーファイルのみを要求する(詳細は制限参照)。このため、Cにおいてはホスト環境で必要とされるランタイムライブラリを必要としない。
ホスト環境におけるcodice_1関数は、プログラムを呼び出した親プログラム(OS等)の存在を想定しておりフリースタンディング環境のエントリーポイントとしては過剰である。またcodice_1という名前が、codice_1関数を呼び出すスタートアップコードを用意する上で邪魔になる(codice_1関数を呼び出す関数がcodice_1では他にcodice_1を定義できない)ため、エントリーポイントはcodice_1関数とは名前も形式も異る関数にできるようになっている。
制限.
フリースタンディング環境では言語仕様に以下の制限を受ける。
例.
この Hello world は GCC と Linux の組み合わせで動作する。codice_29 でコンパイルする。codice_26 は各種終了処理を行う codice_31 の関数のためフリースタンディング環境では使えないが、codice_32 は codice_33 で定義されたシステムコールを呼び出すだけの POSIX の関数のため GCC の Linux 用フリースタンディング環境でも使える。
void _start (void)
 char msg [] = "Hello, world!\n" ;
 write (1, msg, sizeof msg) ;
 _exit (0) ;
標準Cライブラリなし.
類似概念として、コンパイラによっては標準Cライブラリなしでコンパイルすることも可能。例えば GCC の場合、codice_34 オプションを指定することにより、標準Cライブラリを使わなくなる。さらに制限は厳しくなる。フリースタンディング環境同様、終了処理すら行わないため、コンパイル結果を Linux で動作させる場合、エントリーポイントの最後などで OS のシステムコールの codice_26 を呼び出してプロセスを殺す必要があり、フリースタンディング環境の場合は、GCC と Linux の組み合わせの場合、codice_36 で終了させられるが、標準Cライブラリがないため、そのコードは OS と CPU 種別依存のアセンブラで書かないといけない。スタックに関しては、Linux の場合、codice_37 システムコールがスタックを準備するため、スタックは正しく準備された状態でエントリーポイントが呼び出される。
例.
この標準Cライブラリ未使用の Hello world は GCC、Linux、x86-64 の組み合わせで動作する。codice_38 でコンパイルする。
static void write (long fd, const void *buf, unsigned long count)
 __asm__ volatile
 "movq %0, %%rax \n\t"
 "movq %1, %%rdi \n\t"
 "movq %2, %%rsi \n\t"
 "movq %3, %%rdx \n\t"
 "syscall \n\t"
 : "i" (1), "r" (fd), "r" (buf), "r" (count)
 : "%rax", "%rdi", "%rsi", "%rdx"
static void _exit (long status)
 __asm__ volatile (
 "movq %0, %%rax \n\t"
 "movq %1, %%rdi \n\t"
 "syscall \n\t" 
 : "i" (60), "r" (status)
 : "%rax", "%rdi") ;
void _start (void)
 write (1, "Hello, world!\n", 14) ;
 _exit (0) ;