ねこめもmkII(マークツー)

本家ねこめも (http://nekomemo2.site)の補助用。 主に勉強ネタ。

1stステップ(動作確認の環境構築)

まだ「30日でできる!OS自作入門」を進めているので具体的なところには手を出してないが、知りたい事があって書籍を購入後、結局周辺機器も購入した。
最初にやったことだけ記載しておく。 

購入したのは秋月電子で、半田付けが必要なキット版。
 http://akizukidenshi.com/catalog/g/gK-00209/

上記を動かすためのACアダプタも同時に購入。
 http://akizukidenshi.com/catalog/g/gM-06096/ 

PCと接続するためのRS-232C用ケーブルのみヨドバシカメラで購入。
エレコムのUC-SGT1。 

購入したボードがキットだったため、正しく部品が付いてるか気になり、とりあえず動作確認をするために環境だけは整えた。
参考にしたのは以下。ほぼこの通り。
 https://qiita.com/Shohei_miyasako/items/6e0e1a9f298bd8db3369 
一応やったことを下に書いていく。 

Windows10にRS-232C用ケーブルのドライバをメーカーホームページからダウンロードしてインストール。
開発環境はCygwin32bitをインストール。(setup-x86.exe)
インストール時に必要なソフトウェアにチェックを入れておく。上記ページの画像参照。
 binutils: 2.29-1
 gcc:7.3.0-3
 make: 4.2.1-2
 patch:0.3.4-1

必要なファイルをダウンロードしておく。
圧縮ファイルは末尾がbz2だったとしてもgzと同じコマンドで解凍できるので、とにかく同じバージョンを探す。 

 binutils-2.19.1( http://www.ring.gr.jp/pub/GNU/binutils/ ) 
 gcc-3.4.6( http://www.ring.gr.jp/pub/GNU/gcc/ )
 

ダウンロードしたファイルはC:\cygwin\home\ユーザ名の下に置く。
それぞれをインストール。時間がかかる。

 $ tar xvf binutils-2.19.1.tar.bz2
 $ cd binutils-2.19.1 $ mkdir build
 $ cd build
 $ ../configure --target=h8300-elf --disable-nls --disable-werror
 $ make
 $ make install

 $ tar xvf gcc-3.4.6.tar.gz
 $ cd gcc-3.4.6

本書のパッチファイルをダウンロード。
 http://kozos.jp/books/makeos/patch-gcc-3.4.6-x64-h8300.txt
同じフォルダに上記ファイルをpatch.txtとリネームしたものを置く。

gcc\collect2.cの1537行目を本書を参照して修正。
パッチを当てる。

 $ patch -p0 < patch.txt
 $ ../configure --target=h8300-elf --disable-nls --disable-threads --disable-shared --enable-languages=c --disable-werror
 $ make
 $ make install

準備ができたら、本書のソースコードをダウンロード。
 http://kozos.jp/kozos/osbook/osbook_03.zip
解凍し、フォルダ構成を編集。
最初のHelllo Worldのフォルダの場合、
 C:¥cygwin¥home¥ユーザ名¥osbook¥src¥01¥bootload¥

書き込みツールのkz_h8writeをダウンロード。
 https://ja.osdn.net/projects/kz-h8write/
これも配置を編集。
 C:¥cygwin¥home¥ユーザ名¥osbook¥src¥tools¥kz_h8write.exe
これに合わせてbootloadフォルダにあるMakefile内のフォルダ構成も編集。

Makefileのあるフォルダでmakeを実行。
 $ make
 $ make image

ボードを接続し、ポートを確認。
Makefile
 H8WRITE_SERDEV = comXX
のところを編集。自分の場合はcom3になった。

ボードのスイッチを書き込み用にして、
 $ make write
で、書き込み。

Teraterm
 https://ja.osdn.net/projects/ttssh2/releases/
からダウンロードし、インストール。
起動後「設定」「シリアルポート」にし本書の通りに設定。
今度はフラッシュROMからの起動用にボードのスイッチを変更。

接続後、リセットボタンを押すとTeratermの画面に
 Hello World!
と、出てくるはず。(リセットボタンを押すたびに増える)

これでハードウェアの動作は確認できた。
でも本書の内容はまだ読み込んでないので、引き続き学習する。

6日目(bootpack.cとMakefileの整理)

Makefileは独自のルールでやってきたので、いざbootpack.cを分割すると言われると対応に混乱するが、手順は本書の通りに進める。

とにかくbootpack.cを分ける。
bootpack.h:ヘッダファイル
graphic.c : 画面表示
dsctbl.c: descriptor table関係 
bootpack.c: それ以外

しかしmake runするとどうしてもgccでエラーが出る。

 dsctbl.o: 関数 `init_gdtidt' 内:
 dsctbl.c:(.text+0x8c): `load_gdtr' に対する定義されていない参照です
 dsctbl.c:(.text+0xd5): `load_idtr' に対する定義されていない参照です

というような感じ。関数のところはいろいろ。

他の方のMakefileを見ながら、改めて整理。
結局原因はMakefileやdsctbl.cではなく、nasmfunc.nasに増えた関数を記載忘れ&ミスタイプしてただけだった。
nasmfunc.nasの一部抜粋。
section .textのところに追加。

 GLOBAL load_gdtr
 GLOBAL load_idtr
 GLOBAL asm_inthandler21
 GLOBAL asm_inthandler27
 GLOBAL asm_inthandler2c
 EXTERN inthandler21
 EXTERN inthandler27
 EXTERN inthandler2c
(以下略) 

関数は上記だけでなく、かなり行が増えているのに注意。

ついでに以下、現状のMakefileの内容。ファイル名も一部変更。

---

# 6日目終了 現在のファイル
# Makefile (このファイル)
# bootpack.c (分割後)
# dsctbl.c
# graphic.c
# bootpack.h (Makefileに記載はない) 

# har.ld (リンカファイル)
# hankaku.c (半角フォント)
# my_sprintf.c (sprintf関数)

# haribote.nas
# nasmfunc.nas
# nasmhead.nas
# ipl.nas
# int.c

# デフォルト動作

default:
   make img

# ファイル生成規則

nasmhead.bin : nasmhead.nas
    nasm nasmhead.nas -o nasmhead.bin -l nasmhead.lst

nasmfunc.o : nasmfunc.nas          # nasmfunc.nasのバイナリファイル
    nasm -g -f elf nasmfunc.nas -o nasmfunc.o

bootpack.bin: bootpack.o hankaku.o nasmfunc.o my_sprintf.o dsctbl.o graphic.o int.o
   ld -m elf_i386 -e HariMain -o bootpack.bin -T har.ld bootpack.o graphic.o dsctbl.o hankaku.o nasmfunc.o my_sprintf.o int.o

haribote.sys : nasmhead.bin bootpack.bin
    cat nasmhead.bin bootpack.bin > haribote.sys

ipl.bin : ipl.nas Makefile
   nasm ipl.nas -o ipl.bin -l ipl.lst

haribote.img : ipl.bin haribote.sys #最終的なimgファイル
   mformat -f 1440 -C -B ipl.bin -i haribote.img ::
   mcopy haribote.sys -i haribote.img ::

# bootpack.hrb : bootpack.c har.ld  nasmfunc.o Makefile # リンカスクリプト使用
#   gcc -march=i486 -m32 -nostdlib -T har.ld -fno-pic bootpack.c hankaku.c nasmfunc.o -o bootpack.hrb 

%.o: %.c
    gcc -c -m32 -fno-pic -nostdlib -o $*.o $*.c

# コマンド

hankaku :   # conv_hankaku.cでhankaku.cを作る
    gcc -o conv_hankaku conv_hankaku.c
   ./conv_hankaku

asm :
    make -r ipl.bin 

img :
    make -r haribote.img 

run :
    make img
   qemu-system-i386 -fda haribote.img  # -fda追加

clean :
    rm *.lst *.bin *.sys *.img *.hrb *.o

---

これは他の方のブログでまとめられた内容がとても役にたった。
「%.o: %.c」のところが最初わからなかったが、調べたところ、
---
サフィックスルール
また,C言語では必ず.cから.oファイルが作られる,ということを利用し, これをルール化したのがサフィックスルールである.サフィックスとは拡張子のことです..c.o: というターゲットは,.oというファイルが必要になれば,これを.cからつくる というルールである.自動変数である $< をつかっている.
---
と、いうことだった。 

Ubuntu上で作業していると、Makefileは本書とは多少離れて対応する必要がある。
無理せず、自分が解りやすい範囲の記述でまとめた。

make runには成功したが、肝心の6日目後半の内容は正直全く理解できなかったので、少し進めてまた戻って読むのを繰り返すことにする。

 


 今回参照させて頂いたサイト:
https://qiita.com/lrf141/items/9ba070a2a1c3e5faf71c
http://www.jsk.t.u-tokyo.ac.jp/~k-okada/makefile
https://github.com/harrybotter30/haribote/blob/master/doc/chapter6.md
https://inakadeikinaosu.com/shumi/os_nyumon_13/
http://bttb.s1.valueserver.jp/wordpress/blog/2017/12/21/makeos-6-1/

5日目(sprintf対策)

今回はharib02fから。
その前に、このところmake runすると普通に画面は出るけどワーニングが多かった。
よく見ると、intt_screenやputfont8など、あとで追加した関数が最初のところ(void)で宣言されてなかった。
(このミスは最後まで尾を引いた)
bootpack.cを見直した上で、harib02fのものを参照して写経。
エラーが出るので見直していたら、最後に追加されているvoid putfonts8_ascのところを忘れていた。
追加してここまでは成功。

次に#include <stdio.h>を追加して、sprintf(s, "scrnx = %d", binfo->scrnx);を追加。
他にもchar s[40];が増えてたりと、よく見ると違いがある。
最初のエラーが出る。

 gcc -march=i486 -m32 -nostdlib -T har.ld -fno-pic bootpack.c hankaku.c nasmfunc.o -o bootpack.hrb
 In file included from bootpack.c:1:0:
 /usr/include/stdio.h:27:10: fatal error: bits/libc-header-start.h: そのようなファイルやディレクトリはありません
 #include <bits/libc-header-start.h>
         ^~~~~~~~~~~~~~~~~~~~~~~~~~

これは必要なファイルをインストール。
 $ sudo apt install gcc-multilib g++-multilib

もう一度make run。今度は、

 /tmp/ccJ9cdjO.o: 関数 `HariMain' 内:
 bootpack.c:(.text+0xc3): `sprintf' に対する定義されていない参照です
 collect2: error: ld returned 1 exit status

これがubuntuで開発している人には有名な、sprintfの問題。

わからないところはとりあえず保留し、まずはエラーを除くことに尽力したいので、他の方が作っているsprintf関数をコピペしmy_sprintf.cとして保存。
Makefilegccのところに以下のように追加。 

 bootpack.hrb : bootpack.c har.ld  hankaku.c my_sprintf.c nasmfunc.o Makefile       # リンカスクリプト使用
  gcc -march=i486 -m32 -nostdlib -T har.ld -fno-pic bootpack.c hankaku.c my_sprintf.c nasmfunc.o -o bootpack.hrb

これでワーニングはあるものの、成功した。

しかしharib02hでトラップ。
「init_screen」がいつの間にか「init_screen8」になっていて、違いに気づかずしばらく苦労した。
関数名を修正して、成功。

5日目最後のharib02iは変更点を追記したと思ったのだが、どこかでタイプミスをしたらしく、何度直してもエラーになった。 
なので公式のharib02iのbootpack.cをそのまま持ってきてしまった。
するとエラーもなく、ワーニングも減って無事に実行できた。(出てくる画面に変化はない)
ずっとどこかで間違えたままになっていたようなので、以後はこれを使う。

 


 今回参照させて頂いたサイト:
https://thinline196.hatenablog.com/entry/2018/07/05/234715
http://bttb.s1.valueserver.jp/wordpress/blog/2017/12/17/makeos-5-2/