X86アセンブラ/NASM構文
NASM(Netwide Assembler)は、x86およびx86-64アーキテクチャ向けのアセンブラです。C言語の構文に似た文法を使用し、低レベルの機械語を生成するためのツールです。
NASMは、様々なオペレーティングシステムで動作し、主にLinuxやWindowsの開発で利用されます。NASMはアセンブリ言語でプログラムを書くための道具であり、コンパイルやリンクのステップを含むプログラムのビルドプロセスにおいて重要な役割を果たします。
NASMは標準的なアセンブリ言語の機能に加えて、マクロ、条件付きアセンブリ、リープマクロなど、高度な機能を提供しています。これにより、複雑なアセンブリコードを効率的に記述できます。
NASMはAT&T構文ではなく、Intelアセンブリ構文の変種を使用しています。また、MASMおよび互換性のあるアセンブラで使用されるセグメントオーバーライドの自動生成などの機能を避けています。
ここでは簡単な例として、いくつかのプロセッサ/プラットフォーム向けにHello WorldプログラムをNASMで書いてみます。
インストール方法
編集NASM(Netwide Assembler)をインストールする方法は、OSやプラットフォームによって異なります。一般的な方法を以下に示します。
GNU/Linuxのディストリビューション
編集NASMをインストールする方法は、Linuxディストリビューションによって異なりますが、一般的な手順は次のとおりです。
- Ubuntu / Debianベースのディストリビューション
$ sudo apt-get update $ sudo apt-get install nasm
- Fedoraベースのディストリビューション
$ sudo dnf install nasm
- CentOS / RHELベースのディストリビューション
$ sudo yum install nasm
- Arch Linux
$ sudo pacman -S nasm
ディストリビューションによっては、パッケージ名が異なることがあります。上記のコマンドが動作しない場合は、ディストリビューション固有のパッケージマネージャーで nasm を検索してインストールすることができます。
Microsoft Windows
編集WindowsでNASMをインストールする手順は次の通りです。
- 公式サイトからダウンロード: NASMの公式サイト からWindows用のインストーラーをダウンロードします。
- インストール: ダウンロードしたインストーラーを実行し、インストールウィザードに従ってNASMをインストールします。デフォルトの設定を選択することで、NASMが適切にWindowsにインストールされます。
- 環境変数の設定 (オプション): インストール後、NASMの実行ファイルがどこにインストールされたか確認し、そのパスを環境変数
PATH
に追加することで、コマンドラインからNASMを実行できるようになります。
FreeBSD
編集FreeBSDでNASMをインストールする手順は以下の通りです。 pkgコマンドを使用してインストール: FreeBSDの場合、pkgコマンドを使用してNASMをインストールできます。ターミナルを開いて以下のコマンドを実行します。
% sudo pkg install nasm
Portsコレクションを使用する: もしpkgが利用できない場合は、PortsコレクションからNASMをインストールすることもできます。Portsツリーを最新の状態に更新してから、NASMをインストールします。
% sudo portsnap fetch % sudo portsnap extract % cd /usr/ports/devel/nasm % sudo make install clean
これらの手順を実行することで、FreeBSDシステムにNASMをインストールできます。
NetBSD
編集NetBSDでは、pkgsrcを使ってNASMをインストールすることができます。以下は、その手順です: pkgsrcのセットアップ:
% cd /usr/ % sudo git clone https://github.com/NetBSD/pkgsrc.git % cd pkgsrc
NASMのインストール:
% cd cross/nasm % sudo make install clean
これにより、pkgsrcからNASMがダウンロードされ、ビルドされ、インストールされます。 上記の手順を実行することで、NetBSDシステムにNASMをインストールできます。pkgsrcはBSD系システムで一般的に使用されるパッケージ管理システムです。パッケージを管理し、インストールするのに便利なツールとして利用されています。
OpenBSD
編集OpenBSDでNASMをインストールするには、以下の手順を試してみてください:
- pkg_addを使用: OpenBSDのpkg_addコマンドを使用してNASMをインストールすることができます。ターミナルで以下のコマンドを実行してみてください。
- ソースからのビルド: ソースコードからNASMをビルドする方法もあります。NASMのソースコードを入手して、OpenBSD環境でビルドすることができます。以下は手順の一例です。
- NASMの公式サイト(https://www.nasm.us/)からソースコードをダウンロードします。
- ダウンロードしたファイルを展開し、ソースディレクトリに移動します。
./configure
を実行してNASMを設定し、make
コマンドを使用してNASMをビルドします。その後、make install
でNASMをインストールします。
pkg_addでNASMをインストールする方法が最も簡単で、一般的に推奨されます。もしそれがうまくいかない場合は、ソースからのビルドを試してみてください。
プロセッサ/プラットフォーム別のアセンブル
編集NASM(Netwide Assembler)は、インテルx86アーキテクチャ向けのアセンブラ(およびディスアセンブラ)です。16ビット、32ビット(IA-32)、64ビット(x86-64)プログラムを記述するために使用できます。Linuxおよびx86チップ向けの最も人気のあるアセンブラの1つとされています。
NASMはCOFF、OMF、a.out、ELF(Executable and Linkable Format)、Mach-O、バイナリファイル(.bin、オペレーティングシステムをコンパイルするためのバイナリディスクイメージ)など、複数のバイナリフォーマットに出力できます。ただし、位置に依存しないコードはELFオブジェクトファイルにのみ対応しています。RDOFFというNASM独自のバイナリ形式も持っています。
さまざまな出力フォーマットの存在により、プログラムをほぼすべてのx86オペレーティングシステム(OS)にリターゲティングできます。また、ブートローダーや読み取り専用メモリ(ROM)イメージ、OS開発の様々な側面で利用可能なフラットバイナリファイルを作成することも可能です。また、PowerPCやSPARCなどの非x86プラットフォーム上でクロスアセンブラとして実行できますが、それらのマシンで利用可能なプログラムを生成することはできません。
x86-64/Linux でのアセンブル
編集64ビットLinuxシステムで、x86_64アセンブリコードを使用して"Hello, World!"を出力する方法の例です。
- hello.asm
section .data hello db 'Hello, World!',0xA ; 0xAは改行文字 hello_len equ $ - hello ; 文字列の長さを計算 section .text global _start ; ELF実行可能ファイルのエントリポイント _start: mov rax, 1 ; sys_writeのシステムコール番号 mov rdi, 1 ; ファイルディスクリプタ1: 標準出力 mov rsi, hello ; 出力する文字列へのポインタ mov rdx, hello_len ; 文字列の長さ syscall ; システムコールの実行 mov rax, 60 ; sys_exitのシステムコール番号 xor rdi, rdi ; 戻り値0 syscall ; プログラムの終了
このコードは、sys_write
システムコールを使用して"Hello, World!"を標準出力(ファイルディスクリプタ1)に出力し、sys_exit
システムコールを使用して戻りコード0でプログラムを終了します。
このアセンブリコードをNASMでアセンブルすることができます。
$ nasm -f elf64 hello.asm -o hello.o
そしてリンクします。
$ ld hello.o -o hello
実行してみましょう。
$ ./hello Hello, World!
i386/Linux でのアセンブル
編集64ビットシステム用のコードを32ビットのi386/Linux向けに変更します。
- hello32.asm
section .data hello db 'Hello, World!',0xA ; 0xAは改行文字 hello_len equ $ - hello ; 文字列の長さを計算 section .text global _start ; ELF実行可能ファイルのエントリポイント _start: mov eax, 4 ; sys_writeのシステムコール番号 mov ebx, 1 ; ファイルディスクリプタ1: 標準出力 mov ecx, hello ; 出力する文字列へのポインタ mov edx, hello_len ; 文字列の長さ int 0x80 ; システムコールの実行 mov eax, 1 ; sys_exitのシステムコール番号 xor ebx, ebx ; 戻り値0 int 0x80 ; プログラムの終了
このコードは32ビットx86アーキテクチャ向けに書き換えられています。システムコール番号はeax
に設定され、引数はebx
、ecx
、edx
に設定されます。int 0x80
はシステムコールを実行します。
x86-64/Windows でのアセンブル
編集Windows向けのコンソールアプリをNASMで書く場合は、以下のようなアセンブリコードを使用できます。Windows APIの呼び出しには、Win64向けの呼び出し規約を使っています。
- hello-win64.asm
section .data HelloWorld db 'Hello, World!', 0 section .text global main extern GetStdHandle, WriteConsoleA, ExitProcess main: ; Get stdout handle mov rcx, -11 call GetStdHandle ; Prepare parameters for WriteConsoleA mov rdx, HelloWorld ; Message to display mov r8, dword 13 ; Message length mov r9, 0 ; Unused ; Call WriteConsoleA mov rcx, rax ; stdout handle call WriteConsoleA ; Exit the process mov ecx, 0 call ExitProcess
このコードは、WindowsのAPIを使用して標準出力に"Hello, World!"を出力し、プロセスを終了します。NASMで書かれており、Win64の呼び出し規約に従っています。このコードをコンパイルして実行すると、コンソールに"Hello, World!"が表示されます。
8086/MS-DOS でのアセンブル
編集8086アーキテクチャでDOS上で動作するプログラムを作成する場合、NASMを使用してアセンブリ言語で書くことができます。以下は、8086アーキテクチャでDOS上で動作するHello Worldプログラムの例です。
- hello16.asm
org 0x100 ; プログラムの開始アドレスを0x100に設定 section .text mov ah, 09h ; メッセージを表示するためのDOS割り込み番号 mov dx, msg ; メッセージのアドレスをDXにロード int 21h ; DOS割り込みを呼び出してメッセージを表示 mov ax, 4C00h ; DOSの終了割り込みを呼び出すためのコード int 21h ; DOS割り込みを呼び出してプログラムを終了する section .data msg db 'Hello, World!', 0 ; メッセージを定義
このコードは、8086プロセッサ上で動作するDOSのアプリケーションを作成します。メッセージを表示し、プログラムを終了するシンプルな構造です。
$ nasm hello16.asm -o hello16.com $ file hello16.com hello16.com: COM executable for DOS
このプログラムでは、ソースコードでORIGINを切っているのでロードアドレスは固定されているので -f XXX は必要なく、リンクローダのプロセスも必要ありません。