Windows 11 上に WSL2 + BSVC による 68000 アセンブラ演習環境を構築するガイド

1. 本ガイドの構成

本手順は,Windows 11 上に 68000 アセンブラの環境を構築する.

作業ディレクトリは ~/src,インストール先 prefix は /usr/local

2. 基礎編

2.1 WSL2 (Ubuntu 24.04) の導入

  1. Windows のコマンドプロンプトを管理者権限で起動し,次を実行する.

    wsl --install -d Ubuntu-24.04

    このコマンドの実行により,Ubuntu のシェルが起動する. 初回起動時に UNIX ユーザ名とパスワードを設定する.なお,画面にパスワードが表示されないのは正常動作である.

  2. Ubuntu シェルで WSLg(GUI サブシステム)の有効化を確認する.

    echo $DISPLAY

    :0 が表示されることを確認する.表示されない場合,Windows を再起動する.

2.2 ビルド依存パッケージのインストール

Ubuntu のシェルで次のコマンドを実行する.このときに,先ほど設定したパスワードが必要.

sudo apt update
sudo apt upgrade -y
sudo apt install -y \
    build-essential git cmake pkg-config \
    flex bison texinfo \
    tcl-dev tk-dev libx11-dev \
    libgmp-dev libmpfr-dev libmpc-dev libisl-dev zlib1g-dev \
    wget xz-utils file gdb

2.3 インストール先とパスの準備

Ubuntu のシェルで次のコマンドを実行する.

mkdir -p ~/src
cd ~/src

export PREFIX=/usr/local
export TARGET=m68k-elf
export PATH=$PREFIX/bin:$PATH

m68k-elf-* コマンドにパスを通すために ~/.bashrc を設定する.

Ubuntu のシェルで次のコマンドを実行する.

cat >> ~/.bashrc <<'EOF'
export PATH=/usr/local/bin:$PATH
EOF

2.4 binutils (m68k-elf) のインストール

binutils のインストールにより,アセンブラ m68k-elf-as,リンカ m68k-elf-ld,オブジェクト変換 m68k-elf-objcopy,逆アセンブラ m68k-elf-objdump 等のコマンドが使えるようになる.

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
wget https://ftp.gnu.org/gnu/binutils/binutils-2.44.tar.xz
tar xf binutils-2.44.tar.xz

rm -rf build
mkdir build
cd build
export PREFIX=/usr/local
export TARGET=m68k-elf
../binutils-2.44/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --disable-nls \
    --disable-werror \
    --with-sysroot
make -j $(nproc)
sudo env PATH="$PATH" make install
cd ~/src

Ubuntu のシェルで次のコマンドを実行し,インストールを確認する.

ls -la /usr/local/bin
m68k-elf-as --version
m68k-elf-ld --version
m68k-elf-objdump --version

2.5 m68k-elf-gdb のインストール

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
wget https://ftp.gnu.org/gnu/gdb/gdb-15.2.tar.xz
tar xf gdb-15.2.tar.xz

rm -rf build
mkdir build
cd build
export PREFIX=/usr/local
export TARGET=m68k-elf
../gdb-15.2/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --disable-nls \
    --disable-werror
make -j $(nproc)
sudo env PATH="$PATH" make install
cd ~/src

Ubuntu のシェルで次のコマンドを実行し,インストールを確認する.

m68k-elf-gdb --version

2.6 BSVC (68000 エミュレータ) のビルド

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
git clone https://github.com/BSVC/bsvc.git
cd bsvc
cd src
make -f Makefile.Linux all
sudo make -f Makefile.Linux install

Ubuntu のシェルで次のコマンドを実行し,起動を確認する.

bsvc &

WSLg 経由で Windows デスクトップに BSVC のウィンドウが表示されれば成功である.表示されない場合は次を確認する.

2.7 リンカスクリプトと起動コードの準備

Ubuntu のシェルで m68k.ldリンカスクリプト)を作成する.

OUTPUT_FORMAT("elf32-m68k")
OUTPUT_ARCH(m68k)
ENTRY(_start)

MEMORY
{
    ram (rwx) : ORIGIN = 0x00000000, LENGTH = 1M
}

SECTIONS
{
    .vectors 0x00000000 : {
        LONG(0x00010000)   /* 初期スタックポインタ */
        LONG(_start)       /* 初期プログラムカウンタ */
    } > ram

    .text 0x00000400 : {
        *(.text*)
        *(.rodata*)
    } > ram

    .data : {
        *(.data*)
    } > ram

    .bss : {
        _bss_start = .;
        *(.bss*)
        *(COMMON)
        _bss_end = .;
    } > ram
}

作成したら次のコマンドでコピーする.

sudo cp m68k.ld /usr/local/bin

3. 演習編(68000 アセンブラ)

3.1 サンプルアセンブリソース

sample.s を次のとおり作成する.

    .title  "sample.s"
    .global _start

    .text
_start:
    move.w  #3, a       | a に 3 を格納
    move.w  #4, b       | b に 4 を格納
    move.w  a, %d0      | d0 = a
    add.w   b, %d0      | d0 = d0 + b
    move.w  %d0, c      | c = d0
    stop    #0x2700     | 停止

    .data
a:  .word   0
b:  .word   0
c:  .word   0

3.2 ビルド(アセンブル・リンク・S レコード生成)

m68k-elf-as -g -o sample.o sample.s
m68k-elf-ld -T m68k.ld -o sample.elf sample.o
m68k-elf-objcopy -O srec --srec-forceS3 sample.elf sample.s19

-g オプションは GDB 用のデバッグ情報を生成する.あとの演習で使用する.

3.3 逆アセンブル結果の確認

生成されたマシン語を確認する.

m68k-elf-objdump -d sample.elf

各命令のオペコード(16 進バイト列)ニーモニックを確認できる.

3.4 BSVC 上での実行

  1. Ubuntu シェルで bsvc & を実行する.
  2. BSVC のセットアップを行う.BSVC のメニューから File → New Setup... を選び,sim68000 を設定する.その後,メモリのアタッチを行う.まず RAM をクリックし,Attach をクリック.ベースアドレス(Base Address)を 0,サイズ(Size)を 10000 に設定する.
  3. BSVC のメニューから File → Load Program を選び,先ほど作成した sample.s19 を指定する.
  4. PC の値を,プログラムの先頭アドレスである 00000400 に設定する.
  5. 画面下の Reset をクリックする.
  6. Single Step を複数回クリックし,実行の様子を確認する.
  7. メモリビューワ(BSVC のメニューから Window → Memory Viewer)で変数 c の位置に 0x0007 が格納されていることを確認する.
  8. 変数アドレスは次のコマンドで得られる.

    m68k-elf-nm sample.elf

演習

4. 発展編(C 言語から 68000 マシン語への変換)

本章はアセンブラ演習が一通り完了した後の発展学習である.GCCNewlib を追加導入し,C ソースから 68000 マシン語を生成する.

4.1 GCC 第一段(C コンパイラ本体)のビルド

Newlib を後段でビルドするため,まず C 言語のみ・ライブラリなしで GCC をビルドする.

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
wget https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz
tar xf gcc-14.2.0.tar.xz
cd gcc-14.2.0
./contrib/download_prerequisites
cd ~/src

rm -rf build-gcc-stage1
mkdir build-gcc-stage1
cd build-gcc-stage1
export PREFIX=/usr/local
export TARGET=m68k-elf
../gcc-14.2.0/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --enable-languages=c \
    --without-headers \
    --disable-nls \
    --disable-libssp \
    --disable-libquadmath \
    --disable-threads \
    --disable-shared \
    --with-newlib
make -j $(nproc) all-gcc
sudo env PATH="$PATH" make install-gcc
make -j $(nproc) all-target-libgcc
sudo env PATH="$PATH" make install-target-libgcc
cd ~/src

4.2 Newlib(組込用標準 C ライブラリ)のビルド

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
wget https://sourceware.org/pub/newlib/newlib-4.5.0.20241231.tar.gz
tar xf newlib-4.5.0.20241231.tar.gz

rm -rf build-newlib
mkdir build-newlib
cd build-newlib
export PREFIX=/usr/local
export TARGET=m68k-elf
../newlib-4.5.0.20241231/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --disable-newlib-supplied-syscalls \
    --disable-nls \
    CFLAGS_FOR_TARGET="-O2 -g -Wno-implicit-function-declaration -Wno-incompatible-pointer-types -Wno-int-conversion -Wno-implicit-int"
make all
sudo env PATH="$PATH" make install
cd ~/src

4.3 GCC 第二段(Newlib と統合)のビルド

Ubuntu のシェルで次のコマンドを実行する.

cd ~/src
mkdir build-gcc-stage2
cd build-gcc-stage2
export PREFIX=/usr/local
export TARGET=m68k-elf
../gcc-14.2.0/configure \
    --prefix=$PREFIX \
    --target=$TARGET \
    --enable-languages=c \
    --with-newlib \
    --disable-nls \
    --disable-libssp \
    --disable-libquadmath \
    --disable-threads \
    --disable-shared
make -j $(nproc)
sudo env PATH="$PATH" make install
cd ~/src

Ubuntu のシェルで次のコマンドを実行し,インストールを確認する.

m68k-elf-gcc --version
m68k-elf-gcc -print-search-dirs | head
ls $PREFIX/m68k-elf/lib

libc.a, libg.a, libm.a, crt0.o 等が存在することを確認する.

4.4 C ランタイム起動コード

Ubuntu のシェルで crt0.s を次のとおり作成する.

    .title  "crt0.s"
    .global _start
    .extern main

    .text
_start:
    move.l  #0x00010000, %sp     | スタック初期化
    lea     _bss_start, %a0      | BSS ゼロクリア開始
    lea     _bss_end,   %a1
1:  cmp.l   %a0, %a1
    beq     2f
    clr.b   (%a0)+
    bra     1b
2:  jsr     main                 | main 呼出し
    stop    #0x2700              | 終了

4.5 サンプル C ソースコード

add.c

volatile short a, b, c;

int main(void)
{
    a = 3;
    b = 4;
    c = a + b;
    return 0;
}

4.6 ビルド

m68k-elf-as  -g -o crt0.o crt0.s
m68k-elf-gcc -g -O0 -m68000 -ffreestanding -nostdlib -c -o add.o add.c
m68k-elf-ld  -T m68k.ld -o add.elf crt0.o add.o
m68k-elf-objcopy -O srec --srec-forceS3 add.elf add.s19

各オプションの意味は次のとおりである.

4.7 C ソースと生成マシン語の対応観察

m68k-elf-objdump -S add.elf

-S オプションは C ソース行と逆アセンブル結果を交互表示する.C の代入・算術式が 68000 の move, add 命令列にどのように翻訳されるかを観察する.

4.8 GDB による C レベル・アセンブラレベルの両側デバッグ

m68k-elf-gdb add.elf
(gdb) load
(gdb) break main
(gdb) run
(gdb) step                | C ソース行単位のステップ
(gdb) stepi               | 命令単位のステップ
(gdb) info registers
(gdb) print a
(gdb) print b
(gdb) print c
(gdb) x/1hx &c
(gdb) continue
(gdb) quit

stepC ソース行単位stepiマシン命令単位のステップ実行である.C の 1 行がアセンブラ言語の何になるか確認できる.

4.9 Makefile のサンプル

Makefile

CROSS   = m68k-elf-
CC      = $(CROSS)gcc
AS      = $(CROSS)as
LD      = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump

CFLAGS  = -g -O0 -m68000 -ffreestanding -nostdlib -Wall
ASFLAGS = -g
LDFLAGS = -T m68k.ld

TARGET  = add
OBJS    = crt0.o add.o

all: $(TARGET).s19 $(TARGET).lst

$(TARGET).elf: $(OBJS)
	$(LD) $(LDFLAGS) -o $@ $^

$(TARGET).s19: $(TARGET).elf
	$(OBJCOPY) -O srec --srec-forceS3 $< $@

$(TARGET).lst: $(TARGET).elf
	$(OBJDUMP) -S $< > $@

%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

%.o: %.s
	$(AS) $(ASFLAGS) -o $@ $<

clean:
	rm -f *.o *.elf *.s19 *.lst