Practice1 Explanation - GawinGowin/libasm GitHub Wiki
Practice1: Hello World プログラムの詳細解説
課題文
目標: x86-64アセンブリ言語を使って「Hello, World!」を標準出力に表示するプログラムを作成する
要件:
- NASMアセンブラを使用してx86-64アセンブリで実装
- システムコールを使用して標準出力に文字列を出力
- プログラムは正常に終了すること
- 出力する文字列は「Hello, World!」+ 改行文字
ファイル名: practice1.s
コンパイル・実行手順:
nasm -f elf64 practice1.s -o practice1.o
ld practice1.o -o practice1
./practice1
期待する出力:
Hello, World!
なぜこの練習を行うのか
学習目的
-
アセンブリの基本構造理解
- セクション(.data, .text)の概念
- プログラムエントリポイント(_start)の理解
- 基本的なアセンブリファイル構造の習得
-
システムコールの基礎
- Linux システムコールの呼び出し方法
- レジスタを使った引数渡し
- システムコール番号の理解
-
開発環境の確認
- NASM アセンブラの使用方法
- リンカの動作確認
- 実行可能ファイルの生成プロセス
コード詳細解析
; practice1.s - Hello World
section .data
msg db 'Hello, World!', 0xA
len equ $ - msg
section .text
global _start
_start:
; write システムコール
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
; exit システムコール
mov rax, 60
mov rdi, 0
syscall
セクション構造の解説
.data セクション
section .data
msg db 'Hello, World!', 0xA ; 文字列データ + 改行文字
len equ $ - msg ; 文字列の長さを計算
重要なポイント:
db
(define byte): 1バイトずつデータを定義0xA
: 改行文字(LF: Line Feed)$
: 現在の位置を示すシンボル(アセンブラが現在のメモリアドレスを表す)equ
: 定数定義(アセンブル時に計算される)
$ - msg
の詳細説明:
$
: 現在の位置(この行の位置)のアドレスmsg
: 文字列の開始アドレス$ - msg
: 現在位置から文字列開始位置を引く = 文字列の長さ(バイト数)
なぜ長さが計算できるのか:
db
は1バイトずつデータを定義するため、文字列の各文字が順番にメモリに配置されます:
アドレス データ 説明
0x1000 'H' msg のアドレス (開始位置)
0x1001 'e'
0x1002 'l'
... ...
0x100D 0xA 改行文字
0x100E ← $ (len行の現在位置)
結果: $ - msg = 0x100E - 0x1000 = 14
バイト = 文字列の長さ
.text セクション
section .text
global _start
役割:
- 実行可能コードを格納
global _start
: リンカに_start
ラベルを公開_start
: プログラムのエントリポイント
システムコール詳細
writeシステムコール
mov rax, 1 ; システムコール番号 (sys_write)
mov rdi, 1 ; ファイルディスクリプタ (stdout)
mov rsi, msg ; バッファのアドレス
mov rdx, len ; 書き込むバイト数
syscall ; システムコール実行
レジスタの役割:
rax
: システムコール番号(1 = sys_write)rdi
: 第1引数(ファイルディスクリプタ)rsi
: 第2引数(バッファポインタ)rdx
: 第3引数(バイト数)
exitシステムコール
mov rax, 60 ; システムコール番号 (sys_exit)
mov rdi, 0 ; 終了ステータス (0 = 正常終了)
syscall ; システムコール実行
学習効果
この練習で身につくスキル
-
基本的なアセンブリ構文
- セクション分け
- ラベルの使用
- 命令の書き方
-
システムプログラミングの基礎
- システムコールインターフェース
- ファイルディスクリプタの概念
- 標準出力への書き込み
-
開発フロー
- アセンブル → リンク → 実行の流れ
- デバッグの基本手順
よくある間違いと対処法
1. リンクエラー
# 間違い: global _start が未定義
ld: warning: cannot find entry symbol _start
対処法: global _start
を必ず記述
2. セグメンテーションフォルト
# 原因: exit システムコールの省略
Segmentation fault (core dumped)
対処法: プログラム終了時に必ずexitシステムコールを呼ぶ
3. 出力されない
# 原因: 長さ計算の間違い
len equ msg - $ ; これは間違い
len equ $ - msg ; これが正しい
次のステップへの準備
この練習を完了すると:
- アセンブリファイルの基本構造が理解できる
- システムコールの呼び出し方法がわかる
- 開発環境が正しく設定されていることが確認できる
これらの基礎知識は、次のPractice2(数値計算)で必要となります。