1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

アセンブリ入門

Last updated at Posted at 2025-12-13

初めに

assemblyを読めるようになりたい、ということで入門してみた。

コメントアウト

;でコメントアウトを開始する

mov eax, ebx    ;eax を ebx に格納

メモリ構成

メモリは以下の領域からなる

  1. プログラム領域: 実行命令を機械語に変換したものが格納される
  2. データ領域: データが格納されるint x = 3;のような
  3. ヒープ領域: 動的確保領域
  4. スタック領域: 関数呼び出し時の引数、戻り値アドレス、ローカル変数など

レジスタ

変数に相当するもの。CPUごとに個数が制限されている。
CPUの内部にあり、メモリよりも高速に動作する。
データの記憶だけでなく、制御にも使用する。
以下はx86の場合、

  • EAX:主に演算結果や返り値
  • EBX:汎用レジスタ(特定の用途に固定されていない)
  • ECX:rep命令などループ回数で使われやすい
  • EDX:割り込み・I/Oや乗算/除算の一部で利用
  • ESI/EDI:文字列操作系(rep movsb)で使われる
  • EBP:関数のスタックフレーム基準
  • ESP:スタックポインタ

フラグ

CPUが算術演算や論理演算の結果を記憶しておくための特殊なビット。
以下の様なものがある。

  • ZF:計算結果が0の場合に立つ
  • CF:桁溢れのときに立つ
  • SF:計算結果がマイナスの場合に立つ
  • OF:オーバーフロー時に立つ

CF と ZFの違い
CF は2進数で見たときに、桁があふれる場合
ZF は10進数で見たときに、桁があふれる場合

桁溢れ

基本文法

_start:
    mov ebx, 0
    mov ecx, 1 

プログラムは_startラベルから始める
ほかにもラベルを定義できる

loop:

_startは慣例的にエントリポイントとして使われる

ニーモック

アセンブリの各命令をニーモックと呼ぶ。

オペラント

ニーモックの引数、対象を指定する。
x86では主に次の3種類がある。

  1. 即値(Immediate)
    その場に書かれた数値
    例:mov eax, 10

  2. レジスタ(Register)
    レジスタを指定
    例:add eax, ebx

  • メモリ参照(Memory Operand)
    メモリアドレスを指定
    例:mov eax, [ebx]

[] はメモリアドレスを表す

mnemonic operand1 operand2 ...

各命令はニーモックと0個以上のオペラントを記述する。

基礎ニーモック

データ転送

  • mov o1, o2
    o1 に o2 を代入する
    例:

    mov eax, ebx
    
  • lea o1, [o2]
    o2 が指すメモリアドレスを計算し、そのアドレスを o1 に格納する
    メモリを読まずにアドレス計算のみ行う
    例:

    lea eax, [ebx + ecx*4]
    

    eax に ebx + ecx * 4の計算結果が格納される

  • push/pop o1
    スタックに値を積む、読む
    例:

    push eax   ; ESP -= 4, [ESP] = EAX
    pop ebx    ; EBX = [ESP], ESP += 4
    

算術系

  • add o1, o2
    o1にo2を加算する
    例:

    add eax, 3
    add eax, [ebx]
    
  • sub o1 o2
    o1にo2を減算する

    sub eax, 3
    
  • mul/imul o1, (o2)
    乗算する
    オペラントが2つの場合
    o1 = o1 * o2
    オペラントが1つの場合
    eax = eax * o1
    mul は符号なし、imul は符号あり
    例:

    imul ebx      ;eax = eax * ebx
    imul eax, ebx
    
  • div/idiv o1
    除算する
    div は符号なし、idiv は符号あり
    0除算のときは#DE例外が発生
    例:

    div ebx         ;eax = eax / ebx
    
  • inc/dec o1
    インクリメント/デクリメント

    inc eax
    

論理演算

  • and o1, o2
    論理積、結果はo1に格納される
    例:

    and eax, ebx
    
  • or o1, o2
    論理和、結果はo1に格納される
    例:

    or eax
    
  • xor o1,o2
    論理的排除和、結果はo1に格納される
    例:

    xor eax, ebx
    
  • not o1
    ビット反転
    例:

    not eax
    
  • shl/shr o1, 02
    ビットシフト(左/右)
    例:

    shl eax, 1
    
  • sal/sar o1, o2
    ビットシフト(左/右)
    ただし符号ビットを維持する

    sar eax, 1    ; 負数ならMSBを保持
    

比較、分岐

  • cmp o1, o2
    o1-o2を計算しフラグを立てる

    • 符号なし

      条件 フラグ
      a > b CF = 0 & ZF = 0
      a == b ZF = 1
      a < b CF = 1
    • 符号あり

      条件 フラグ
      a > b SF = OF & ZF = 0
      a == b ZF = 1
      a < b SF != OF

    例:

    cmp eax, ebx
    
  • test o1, o2
    o1 & o2を計算しフラグを立てる

    条件 フラグ
    共通ビットなし ZF = 1
    最上位ビットが1 SF = 1
    下位8bit の1の数が偶数 PF = 1
  • jmp o1
    命令o1に移動する
    例:

    jmp loop
    
  • je/jne o1
    ZFが1/0の時ならばジャンプする

    je label
    
  • jg/jl/jge/jle o1
    フラグをもとにo1へジャンプする

    • jg
      ZF = 0 かつ SF = OF(o1 > o2)
    • jl
      SF != OF (o1 < o2)
    • jge
      SF = OF (o1 >= o2)
    • jle
      ZF = 1 かつ SF != OF(o1 <= o2)

その他

  • call o1
    サブルーチン呼び出し
    現在のアドレスはスタックに保存
  • ret
    スタックに保存されたアドレスに戻る

システムコール

syscall
または
int 

OS の提供している機能を利用する。
EAXの値で機能を指定する。
例:

eax システムコール名 説明
1 exit プロセス終了 
2 fork 子プロセス生成
3 read FD から読み込む
4 write FD に書き込む
5 open ファイルを開く
6 close ファイルを閉じる
8 creat ファイルを作る(open の簡易版)
19 lseek ファイル位置を移動

出力

EAX: write を指定
EBX: ファイルでスクリプターを指定
0-stdin
1-stdout
2-stderr
ECX: 出力する文字列を指定
EDX: 出力する文字列の長さを指定

mov eax, 4    ;システムコール
mov ebx, 1    ;標準出力
mov ecx, msg  ;文字列
mov edx, len  ;長さ
syscall

Hello, World!

section .data
    msg db "Hello, world!", 10  ;
    msglen equ $ - msg

section .text
    global _start

_start:
    mov eax, 4
    mov ebi, 1
    mov eci, msg
    mov edx, msglen
    syscall                    ; Call the kernel

    mov eax, 1                ; Exit システムコール
    mov ebi, 0                 ; 終了コード
    syscall                    ; Call the kernel

section .data解説

データ領域にバイト列を置く

msg db "Hello, World!", 10

msg: ラベル(文字列の先頭アドレス)
db: バイト列を定義
"Hello World!": 文字列
10: 改行コード

msg:
  48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 0A

のようになる。

msglen equ $ - msg

equ: 定数定義
$: 現在のアドレス
msg: 先のラベルアドレス

実行方法

nasm -f elf32 xxx.asm -o xxx.o
ld -m elf_i386 xxx.o -o xxx
./xxx

参考文献

札幌学院大学-アセンブリ言語入門

終わりに

次は実際に書いてみる。
~Thank you for rading~

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?