Windows 11 上に WSL2 + BSVC による 68000 アセンブラ演習環境を構築するガイド
1. 本ガイドの構成
本手順は,Windows 11 上に 68000 アセンブラの環境を構築する.
- 導入:WSL2 (Ubuntu 24.04) の導入,binutils による 68000 アセンブラのインストール,BSVC エミュレータの導入,アセンブリ言語プログラムのテスト実行.
- 演習:アセンブリプログラムの記述,BSVC 上での実行.
- 発展:GCC と Newlib のインストール,C 言語から 68000 アセンブリ言語への変換.
作業ディレクトリは ~/src,インストール先 prefix は /usr/local.
2. 基礎編
2.1 WSL2 (Ubuntu 24.04) の導入
- Windows のコマンドプロンプトを管理者権限で起動し,次を実行する.
wsl --install -d Ubuntu-24.04
このコマンドの実行により,Ubuntu のシェルが起動する. 初回起動時に UNIX ユーザ名とパスワードを設定する.なお,画面にパスワードが表示されないのは正常動作である.
- 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
-
build-essentialは gcc, make, glibc-dev などである. -
tcl-dev/tk-devは BSVC のビルドに使用する. -
libgmp-dev/libmpfr-dev/libmpc-dev/libisl-devは GCC(クロスコンパイラ)のインストールに使用する.
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 のウィンドウが表示されれば成功である.表示されない場合は次を確認する.
- 1.
echo $DISPLAYが空でないこと. - 2.コマンドプロンプトを管理者権限で起動し
wsl --updateを実行して WSL2 カーネルを最新化していること. - 3.
apt install -y x11-apps && xeyesで xeyes の画面が開くかを確認.
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 上での実行
- Ubuntu シェルで
bsvc &を実行する. - BSVC のセットアップを行う.BSVC のメニューから
File → New Setup...を選び,sim68000を設定する.その後,メモリのアタッチを行う.まずRAMをクリックし,Attachをクリック.ベースアドレス(Base Address)を 0,サイズ(Size)を 10000 に設定する. - BSVC のメニューから
File → Load Programを選び,先ほど作成したsample.s19を指定する. PCの値を,プログラムの先頭アドレスである 00000400 に設定する.- 画面下の
Resetをクリックする. Single Stepを複数回クリックし,実行の様子を確認する.- メモリビューワ(BSVC のメニューから
Window → Memory Viewer)で変数cの位置に0x0007が格納されていることを確認する.








変数アドレスは次のコマンドで得られる.
m68k-elf-nm sample.elf

演習
- 演習 1.
sample.sの即値#3,#4を変更し,cの値が期待どおり更新されることを BSVC で確認する. - 演習 2.
add.wをsub.wに書き換え,減算結果を確認する. - 演習 3.
move.wをmove.lに変更した場合,a,b,cの宣言.wordをどのように変更する必要があるか記述し,実行結果を確認する. - 演習 4.ループ命令
dbraを用いて 1 から 10 までの総和を求めるプログラムを作成し,ステップ実行で観測する.
4. 発展編(C 言語から 68000 マシン語への変換)
本章はアセンブラ演習が一通り完了した後の発展学習である.GCC と Newlib を追加導入し,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

各オプションの意味は次のとおりである.
-
-m68000:純正 68000 命令のみを生成する. -
-ffreestanding:ホスト OS を前提としないコード生成を指示する. -
-nostdlib:標準ライブラリの自動リンクを抑止する. -
-O0:デバッグ時は最適化を無効化する.リリース時は-O2を用いる. -
--srec-forceS3:32 ビットアドレスの S3 レコードで出力する.
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
step は C ソース行単位,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