gccのオプションに-cと-m32を入れて、C言語の簡単なテストプログラムをブートモニターへ組み込んで、オブジェクトを作成したのだが、アセンブラのオブジェクトとldでリンクすると、i386:x86-64と互換性がない、というエラーとなった。いろいろ調べてみたが、32bitプロテクトモードでコンパイルすると何をやってもエラーになるようだ。確かに今はもう64bitが当たり前の世の中なので、32bitモードなどに拘る必要はないのだが、私のように初心者が学習の第一段階で正しくCPUモードを切り替えられるか確認しながら、プログラミングを進める時には必要だと思う。それに、私のやり方はバイナリでターゲットを作成するので、リンカーで無用にシンボルやコードのチェックをしてもらう必要もない。gccはあらゆるCPUのあらゆるモードに対応してきたため、古い仕様はメンテナンスされず、今回のような不整合が起こっているのだろうか?(後になって分かったことだが、この問題はManjaro Linux(64bit)の標準gccツールチェーンをそのまま利用していたためで、標準gccは64bitのアプリケーションプログラムを作成することに最適化されている。組み込み開発では、基本的にgccやbinutilなどのソースをダウンロードしてクロスコンパイル環境を構築しなければならない)何にしても、きちんと標準化された開発環境が整ってないと、初心者にはハードルが高い。しかし、これ以上拘っても時間の無駄なので、アセンブラで64bitロングモードに切り替えてからC言語の関数を呼ぶことにした。そのためには、仮想メモリをMMUで使うため、パージングのセットアップをしなければならなかった。
ネット上の情報やサンプルプログラムを真似て、ページテーブルを設定してみたが、結局、数えきれないくらい失敗し、その理由さえ分からず、64bitロングモードはあきらめざるを得なかった。32bitモードでなぜリンクできないのか、いろいろ調べて、標準gccツールチェーンだからではないか、と思い付き、Manjaro Linuxのパッケージマネージャでi686で検索すると、i686-elf-binutilとi686-elf-gccがAURリポジトリにあり、ダメ元でビルドしてみた。PGP鍵エラーになったが、何かわからないが、誰かの鍵を信用しますか? とメッセージが出て、信用する、にしたら、コンパイルとビルドが行われた。一時間程ビルドが続いたが、/usr/bin/に実行プログラムが作られていて、Makefileでi686用のアセンブラやリンカ、コンパイラーを使うよう修正し、改めて32bitプロテクトモードでC言語関数を呼び出したが、リンクエラーとなった。リンカースクリプトを修正するのを忘れていた。OUTPUT_FILEをi386:x86-64からi386(i686では駄目だった)へ修正すると、makeに成功した。FDディスクイメージをVirtualBoxで実行すると、見事、C言語の内部から文字列を画面に表示してくれた。この問題の解決に一週間もかかってしまった。まあ、これも勉強だと思うしかない。
ページングの設定は、マルチタスクOSを作るレベルになったら、改めて挑戦することにして、しばらくはベタなシステムで開発を続けるつもりだ。C言語が使えるようになったので、フリーで公開されているモジュールの移植もできるだろうし、開発効率が上がるはずだ。これからは画面モードの切り替えとスクリーン表示、キーボード入力のルーチンを作っていって、コマンド入力画面っぽい体裁を整えようと思っている。