macOS で『はじめて読む486』の環境構築

# はじめに
macOS で『はじめて読む486』のサンプルプログラムを動かすための環境構築についてまとめました。
末尾の参考リンクの記事と重複する部分がありますが、以下が本記事の特徴です。

- FreeDOS 1.2 のインストール手順を詳細に記載されている (※ YouTube 動画もあります)
- macOS での環境構築方法となっている
- ソースコードのコンパイル方法まで記載されている



# [FreeDOS 1.2](http://www.freedos.org/download/) のインストール
```
$ brew install wget
$ brew install qemu
$ wget https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.2/FD12CD.iso
$ qemu-img create -f raw freedos.img 200M
$ qemu-system-x86_64 -cpu 486 -drive file=freedos.img,format=raw -cdrom FD12CD.iso -boot d
```
**テキストだけだとわかりにくいので、[YouTube 動画 (How to install FreeDOS)](https://youtu.be/EbOGT2fVz3U) として残しておきました。**

1. "Welcome to FreeDOS 1.2" で [Install to harddisk] を選択
1. "What is your preferred language?" で [English] を選択
1. "Do you want to proceed?" で [Yes - Continue with the installation] を選択
1. "Do you want to partition your drive?" で [Yes - Partition drive C:] を選択
1. "Do you want to use large disk (FAT32) support (Y/N)?" で [Y] を選択
1. "Enter choice" で [1] を選択 (Create DOS partition or Logical DOS Drive)
1. "Enter choice" で [1] を選択 (Create Primary DOS Partition)
1. "Do you wish to use the maximum available size for a Primary DOS Partition and make the partition active (Y/N)?" で [Y] を選択
1. Esc を 3 回押下
1. "Do you want to reboot now?" で [Yes - Please reboot now] を選択
1. "Welcome to FreeDOS 1.2" で [Install to harddisk now] を選択
1. "What is your preferred language?" で [English] を選択
1. "Welcome to the FreeDOS 1.2 installation program" で [Yes 1. Continue with the installation] を選択
1. "Drive C: does not appear to be formated." で [Yes - Please erase and format drive C:] を選択
1. "Formatting drive C:..." で Enter を押下
1. "Please select your keyboard layout." で [US English (Default)] を選択
1. "What FreeDOS packages do you want to install?" で [Full installation] を選択
1. "Do you want to install now?" で [Yes - Please install FreeDOS 1.2] を選択
1. "Installation of FreeDOS 1.2 is now complete." が出ればインストール成功
1. 一旦、ウィンドウを閉じる (マウスカーソルが表示されていなくなっていたら、Ctrl + Alt + G で復活します。)
1. FreeDOS を起動

```
$ qemu-system-x86_64 -cpu 486 -drive file=freedos.img,format=raw
```

しばらく待って "C:\>" が表示されれば OK (次回以降も同じコマンドで起動できる)



# [Open Watcom C Compiler](http://www.openwatcom.org/download.php) のインストール
C コンパイラを Open Watcom からインストールする。

```
$ hdiutil attach freedos.img
/dev/disk2          	FDisk_partition_scheme         	
/dev/disk2s1        	DOS_FAT_16                     	/Volumes/FREEDOS2016
$ wget ftp://ftp.openwatcom.org/install/open-watcom-c-dos-1.9.exe
$ cp open-watcom-c-dos-1.9.exe /Volumes/FREEDOS2016/owcc.exe
$ hdiutil detach /dev/disk2
$ qemu-system-x86_64 -cpu 486 -drive file=freedos.img,format=raw
```

```
> owcc
```
**同じくテキストだけだとわかりにくいので [YouTube 動画 (How to install Open Watcom C/C++ compiler on FreeDOS)](https://youtu.be/2xAwLFsPGBQ) も作りましたので、参考にしてください。**

1. "Open Watcom C/C++" の規約画面で [I Agree] を選択 (Tab 2 回、Enter 1 回)
1. "Install Open Watcom C/C++ in: C:\WATCOM" で [Next] を選択 (Tab 1 回、Enter 1 回)
1. "Open Watcom C/C++ will be installed in 'C:\WATCOM'" で [Selective Installation] を選択 (Enter 1 回)
1. "Select components to install" で [Include 16-bit compilers] を選択 (B 1 回)
1. "Select the 16-bit memory models you wish to use" で [Huge] を追加 (U 1 回、Enter 1 回)
1. "Select components to install" で [Toolkits and other components] を選択 (E 1 回)
1. "Select other options" で [Include C++ compiler components] と [Sample programs] を無効化 (I 1 回、P 1 回、Enter 1 回)
1. "Select components to install" で [Next] を選択 (N 1 回)
1. "Setup will now copy any selected files" で [Next] を選択 (N 1 回)
1. "Copying Files..." でひたすら待つ
1. "Setup needs to modify AUTOEXEC.BAT and CONFIG.SYS." で [Let you make the modifications later] を選択 (下キー 1 回、Tab 1 回、Enter 1 回)
1. "Setup Can not find the following file:" で "OK" を選択 (Tab 2 回、Enter 1 回)
1. "Setup will save the changes ..." で [OK] を選択 (Enter 1 回)
1. "Setup has completed successfully." で [Enter 1 回]

`C:\AUTOEXEC.BAT` の最後の行に、以下の行を追加する。
テキストエディタは edit が利用できます。

```
call C:\WATCOM\OWSETENV.BAT
```



# ソースコードの実行
## ソースコードのダウンロード
```
$ brew install git
$ git clone https://github.com/tkmc/486
$ hdiutil attach freedos.img
/dev/disk2          	FDisk_partition_scheme         	
/dev/disk2s1        	DOS_FAT_16                     	/Volumes/FREEDOS2016
$ cp -r 486/SOURCE /Volumes/FREEDOS2016/
$ hdiutil detach /dev/disk2
$ qemu-system-x86_64 -cpu 486 -rtc base=localtime -drive file=freedos.img,format=raw
```

起動時のオプションで「3 - Load FreeDOS without drivers (Emergency Mode)」を選択する。

```
> cd SOURCE
> rename MAKEFILE.OW MAKEFILE
```


## コンパイルと実行
### エラトステネスのふるい
```
> wmake sieve_c.exe
> sieve_c 61701
...
6208 prime numbers in 2..61701
> sieve_c 64000
Can't alloc memory
```


## リアルモードとプロテクトモード間の遷移
```
> wmake testprot.exe
> testprot
Now going to Protected mode...
Returned from Protected mode.
```


## リアルモードのセグメントの確認
```
> wmake rmseg.exe
> rmseg
cs:1690 ds:188a es:1680 ss:188a
```


## プロテクトモードのセグメントの確認
```
> wmake pmseg.exe
> pmseg
Before ***********
0008: Base=00016900 Lim=023FF         P dpl:0 seg ER-Code
0010: Base=00018D00 Lim=0FFFF         P dpl:0 seg RW-Data
0018: Base=00018D00 Lim=00000         P dpl:0 seg RW-Stack
0020: Base=00016900 Lim=0FFFF         P dpl:0 seg ER-Code
0028: Base=00018D00 Lim=0FFFF         P dpl:0 seg RW-Data
0030: Base=00000000 Lim=FFFFF G       P dpl:3 seg RW-Data
val:0
After  ***********
val:1
0008: Base=00016900 Lim=023FF         P dpl:0 seg ER-Code
0010: Base=00018D00 Lim=0FFFF         P dpl:0 seg RW-Data  A
0018: Base=00018D00 Lim=00000         P dpl:0 seg RW-Stack A
0020: Base=00016900 Lim=0FFFF         P dpl:0 seg ER-Code
0028: Base=00018D00 Lim=0FFFF         P dpl:0 seg RW-Data  A
0030: Base=00000000 Lim=FFFFF G       P dpl:3 seg RW-Data
```


## 32 ビットのアドレスサイズを使った例題プログラム
```
> wmake sieve32.exe
> wmake putpmem.exe
> wmake getpmem.exe
> sieve32 64000 > sieve.txt
> putpmem sieve.txt
> getpmem
...
6413 prime numbers in 2..64000
```

(残りのプログラムについても、順次更新予定)


# おまけ
## DEBUG コマンドの使い方
- `A [address]` (Assemble): アセンブリコードを入力する
- `D [address] [address]` (Dump): メモリの内容をダンプする
- `E address [list]` (Edit): メモリの内容を編集する
- `G[=address] [address]` (Go): プログラムを実行する
- `N` (Name): ファイル名を指定する
- `Q` (Quit): 終了する
- `R [register]` (Register): レジスタを表示もしくは設定する
- `T [address]`: 指定したメモリのプログラムを 1 命令実行し、全レジスタの内容と次に実行する命令を表示する
- `U [address] [address]` (Unassemble): 逆アセンブルを行う
- `W` (Write): メモリ内容をファイルに出力する
- `?` (Help): ヘルプ画面を表示する


## Open Watcom C Compiler の使い方
※ [FreeDOS を QEMU で動かす](https://blog.tiqwab.com/2018/10/01/freedos.html) と同一の内容です。

- コンパイル: `wcc -ecc -ms a.c`
	- `-ecc`: 呼び出し規約として cdecl を使用
	- `-ms`: small memory model
- アセンブル: `wasm -ms b.asm`
- コンパイルとリンク: `wcl -ecc -fe=c.exe b.obj c.c`
	- `-fe`: 出力実行ファイル名
- ディスアセンブル: `wdis -l=d.lst d.obj`
	- `-l`: 出力ファイル名



# 参考リンク
- [FreeDOS を QEMU で動かす](https://blog.tiqwab.com/2018/10/01/freedos.html)
- [「はじめて読む486」の実行環境を、FreeDOS+QEMU+OpenWatcomでつくる - tomoyukim's blog](https://tomoyukim.hatenablog.com/entry/2019/10/18/131607)
- [GitHub - tkmc/486: 『はじめて読む486』のサンプルプログラム集です。](https://github.com/tkmc/486)