コンテンツにスキップ

X86アセンブラ/NASM構文

出典: フリー教科書『ウィキブックス(Wikibooks)』

NASM(Netwide Assembler)は、x86およびx86-64アーキテクチャ向けのアセンブラです。C言語の構文に似た文法を使用し、低レベルの機械語を生成するためのツールです。

NASMは、様々なオペレーティングシステムで動作し、主にLinuxやWindowsの開発で利用されます。NASMはアセンブリ言語でプログラムを書くための道具であり、コンパイルやリンクのステップを含むプログラムのビルドプロセスにおいて重要な役割を果たします。

NASMは標準的なアセンブリ言語の機能に加えて、マクロ、条件付きアセンブリ、リープマクロなど、高度な機能を提供しています。これにより、複雑なアセンブリコードを効率的に記述できます。

NASMはAT&T構文ではなく、Intelアセンブリ構文の変種を使用しています。また、MASMおよび互換性のあるアセンブラで使用されるセグメントオーバーライドの自動生成などの機能を避けています。

ここでは簡単な例として、いくつかのプロセッサ/プラットフォーム向けにHello WorldプログラムをNASMで書いてみます。

インストール方法

[編集]

NASM(Netwide Assembler)をインストールする方法は、OSやプラットフォームによって異なります。一般的な方法を以下に示します。

Microsoft Windows

[編集]

WindowsでNASMをインストールする手順は次の通りです。

  1. 公式サイトからダウンロード: NASMの公式サイト からWindows用のインストーラーをダウンロードします。
  2. インストール: ダウンロードしたインストーラーを実行し、インストールウィザードに従ってNASMをインストールします。デフォルトの設定を選択することで、NASMが適切にWindowsにインストールされます。
  3. 環境変数の設定 (オプション): インストール後、NASMの実行ファイルがどこにインストールされたか確認し、そのパスを環境変数 PATH に追加することで、コマンドラインからNASMを実行できるようになります。

FreeBSD

[編集]

FreeBSDでNASMをインストールする手順は以下の通りです。 pkgコマンドを使用してインストール: FreeBSDの場合、pkgコマンドを使用してNASMをインストールできます。ターミナルを開いて以下のコマンドを実行します。

doas pkg install nasm

Portsコレクションを使用する: PortsコレクションからNASMをインストールすることもできます。Portsツリーを最新の状態に更新してから、NASMをインストールします。

doas git clone https://github.com/freebsd/freebsd-ports.git /usr/ports
doas make -C /usr/ports/devel/nasm install clean

これらの手順を実行することで、FreeBSDシステムにNASMをインストールできます。

NetBSD

[編集]

NetBSDでは、pkgsrcを使ってNASMをインストールすることができます。以下は、その手順です: pkgsrcのセットアップ:

doas git clone https://github.com/NetBSD/pkgsrc.git /usr/pkgsrc

NASMのインストール:

doas make -C /usr/pkgfsrc/cross/nasm install clean

これにより、pkgsrcからNASMがダウンロードされ、ビルドされ、インストールされます。 上記の手順を実行することで、NetBSDシステムにNASMをインストールできます。pkgsrcはBSD系システムで一般的に使用されるパッケージ管理システムです。パッケージを管理し、インストールするのに便利なツールとして利用されています。

OpenBSD

[編集]

OpenBSDでNASMをインストールするには、以下の手順を試してみてください:

  1. pkg_addを使用: OpenBSDのpkg_addコマンドを使用してNASMをインストールすることができます。ターミナルで以下のコマンドを実行してみてください。
  2. ソースからのビルド: ソースコードからNASMをビルドする方法もあります。NASMのソースコードを入手して、OpenBSD環境でビルドすることができます。以下は手順の一例です。

pkg_addでNASMをインストールする方法が最も簡単で、一般的に推奨されます。もしそれがうまくいかない場合は、ソースからのビルドを試してみてください。

GNU/Linuxのディストリビューション

[編集]

NASMをインストールする方法は、Linuxディストリビューションによって異なりますが、一般的な手順は次のとおりです。

Debianベースのディストリビューション
$ sudo apt-get update
$ sudo apt-get install nasm
Fedoraベースのディストリビューション
$ sudo dnf install nasm
RHELベースのディストリビューション
$ sudo yum install nasm
Arch Linux
$ sudo pacman -S nasm

ディストリビューションによっては、パッケージ名が異なることがあります。上記のコマンドが動作しない場合は、ディストリビューション固有のパッケージマネージャーで 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に設定され、引数はebxecxedxに設定されます。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 は必要なく、リンクローダのプロセスも必要ありません。