🏇

Smaller CでFreeDOS用プログラムの作成

2021/12/26に公開

はじめに

Smaller Cを使用して
FreeDOSのプログラムの作成をしてみます。

Smaller Cについて

詳細は以下
https://github.com/alexfru/SmallerC

プリプロセッサ、コンパイラ、リンカが提供されているようです。
アセンブラは別途用意する必要があります(nasmなど)

Smaller のビルド

ドキュメントを見ると、

How do I compile Smaller C on/for x86?
With 32-bit gcc in Linux:

gcc -Wall -Wextra -O2 smlrc.c -o smlrc

と、あるのでgccでビルドができるようです。
ver9.3.0でビルドができました。(Ubuntu上で実行)

$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

make時の出力は以下。

$ make
gcc -pipe -Wall -O2 -DPATH_PREFIX='"/usr/local"' -DHOST_LINUX    /home/USERNAME/freedos/SmallerC/v0100/smlrc.c   -o smlrc
gcc -pipe -Wall -O2 -DPATH_PREFIX='"/usr/local"' -DHOST_LINUX    /home/USERNAME/freedos/SmallerC/v0100/smlrl.c   -o smlrl
/home/USERNAME/freedos/SmallerC/v0100/smlrl.c: In function ‘RwPe’:
/home/USERNAME/freedos/SmallerC/v0100/smlrl.c:3134:105: warning: suggest parentheses around ‘-’ in operand of ‘&’ [-Wparentheses]
 3134 |             ((pSectDescrs[textSectCnt + roDataSectCnt + impDataSectCnt - 1].Stop + 0xFFF) & 0xFFFFF000) -
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
 3135 |             pSectDescrs[textSectCnt + roDataSectCnt].Start & 0xFFFFF000;
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                               
/home/USERNAME/freedos/SmallerC/v0100/smlrl.c:3262:20: warning: variable ‘sectNameLen’ set but not used [-Wunused-but-set-variable]
 3262 |             size_t sectNameLen;
      |                    ^~~~~~~~~~~
gcc -pipe -Wall -O2 -DPATH_PREFIX='"/usr/local"' -DHOST_LINUX    /home/USERNAME/freedos/SmallerC/v0100/smlrcc.c   -o smlrcc
/home/USERNAME/freedos/SmallerC/v0100/smlrcc.c: In function ‘Archive’:
/home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:1029:15: warning: ‘%lu’ directive writing between 2 and 19 bytes into a region of size 13 [-Wformat-overflow=]
 1029 |       fh.name[sprintf(fh.name, "#1/%lu", l)] = ' '; // Use BSD(in-place) format for long names
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:1029:15: note: directive argument in the range [16, 9223372036854775805]
In file included from /usr/include/stdio.h:867,
                 from /home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:69:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:10: note: ‘__builtin___sprintf_chk’ output between 6 and 23 bytes into a destination of size 16
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:1044:15: warning: ‘%lu’ directive writing between 2 and 19 bytes into a region of size 10 [-Wformat-overflow=]
 1044 |       fh.size[sprintf(fh.size, "%lu", l)] = ' ';
      |               ^~~~~~~~~~~~~~~~~~~~~~~~~~
/home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:1044:15: note: directive argument in the range [16, 9223372037391646717]
In file included from /usr/include/stdio.h:867,
                 from /home/USERNAME/freedos/SmallerC/v0100/smlrcc.c:69:
/usr/include/x86_64-linux-gnu/bits/stdio2.h:36:10: note: ‘__builtin___sprintf_chk’ output between 3 and 20 bytes into a destination of size 10
   36 |   return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   37 |       __bos (__s), __fmt, __va_arg_pack ());
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc -pipe -Wall -O2 -DPATH_PREFIX='"/usr/local"' -DHOST_LINUX -o smlrpp -DSTAND_ALONE -DUCPP_CONFIG \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/arith.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/assert.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/cpp.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/eval.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/lexer.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/macro.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/mem.c \
/home/USERNAME/freedos/SmallerC/v0100/ucpp/nhash.c
gcc -pipe -Wall -O2 -DPATH_PREFIX='"/usr/local"' -DHOST_LINUX    /home/USERNAME/freedos/SmallerC/v0100/n2f.c   -o n2f
/usr/bin/ld: /tmp/ccowDKSK.o: in function `convert':
n2f.c:(.text+0xcb3): 警告: the use of `tmpnam' is dangerous, better use `mkstemp'
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcdh.txt > lcdh.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcdh.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcdu.txt > lcdu.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcdu.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcds.txt > lcds.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcds.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcw.txt > lcw.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcw.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcl.txt > lcl.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcl.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcdp.txt > lcdp.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcdp.op
awk -v l=/home/USERNAME/freedos/SmallerC/v0100/srclib/ '/[.](c|asm)$/{$0=l$0}{print}' /home/USERNAME/freedos/SmallerC/v0100/srclib/lcm.txt > lcm.op
./smlrcc -SI /home/USERNAME/freedos/SmallerC/v0100/include -I /home/USERNAME/freedos/SmallerC/v0100/srclib @lcm.op
./smlrcc -small /home/USERNAME/freedos/SmallerC/v0100/srclib/dpstub.asm -o dpstub.exe
rm lcl.op lcds.op lcw.op lcdh.op lcdp.op lcdu.op lcm.op

FreeDOS版Hello world

以下のようなファイルを用意します。

hello.c
#include <stdio.h>

int main(){
    printf("Hello FreeDOS\n");
    return 0;
}

先程ビルドしたコンパイラドライバ(smlrcc)で
ビルドしてみます。
オプションの詳細はドキュメントを参照してください。

$ smlrcc -v -dost -o hello.com hello.c
smlrpp -U __STDC_VERSION__ -zI -D _DOS -D __SMALLER_C__ -D __SMALLER_C_16__ -D __SMALLER_C_SCHAR__ -D __SMALLER_C_UWCHAR__ -D __SMALLER_C_WCHAR16__ -D __SMALLER_PP__ -o hello.i hello.c
hello.c: line 1: file 'stdio.h' not found

Executed command failed

ヘッダが無いよ、と言われてしまいました。
-I オプションを指定してヘッダファイルのパスを指定する必要があります。
インクルードファイルのパスを追加してもう一度ビルドしてみます。

$ smlrcc -v -dost -IPATH/SmallerC/v0100/include -o hello.com hello.c
smlrpp -U __STDC_VERSION__ -zI -D _DOS -I PATH/SmallerC/v0100/include -D __SMALLER_C__ -D __SMALLER_C_16__ -D __SMALLER_C_SCHAR__ -D __SMALLER_C_UWCHAR__ -D __SMALLER_C_WCHAR16__ -D __SMALLER_PP__ -o hello.i hello.c
smlrc -seg16 -nopp hello.i hello.asm
nasm -f elf hello.asm -o hello.o
smlrl -tiny hello.o -o hello.com

Symbol '__start' not found

Executed command failed

今度はリンクで失敗しました。
-SLオプションでライブラリのパスを設定する必要があります。

$ smlrcc -v -dost -IPATH/SmallerC/v0100/include -SLPATH/SmallerC/v0100/lib -o hello.com hello.c
smlrpp -U __STDC_VERSION__ -zI -D _DOS -I PATH/SmallerC/v0100/include -D __SMALLER_C__ -D __SMALLER_C_16__ -D __SMALLER_C_SCHAR__ -D __SMALLER_C_UWCHAR__ -D __SMALLER_C_WCHAR16__ -D __SMALLER_PP__ -o hello.i hello.c
smlrc -seg16 -nopp hello.i hello.asm
nasm -f elf hello.asm -o hello.o
smlrl -tiny hello.o PATH/SmallerC/v0100/lib/lcds.a -o hello.com

これでhello.comが作成されました。

$ file hello.com 
hello.com: DOS executable (COM)

FreeDOSで実行

Linux(Ubuntu)上でhello.comが作成できたので、
FreeDOSにhello.comファイルを持っていって実行すると、実行できました。

C:\>hello
Hello FreeDOS

まとめ

今回は、Linux上でFreeDOS用のプログラムのビルドをしてみました。
gccもあるのですが、
ちょっと違うコンパイラを使うのも楽しいかなと思い書いてみました。

補足:ファイルをlinux環境からFreeDOS環境に移動

今回は Linux(Virtual box)上でFreeDOS用のプログラムの作成、
作成したプログラムを
FreeDOS(Virtual box)上で実行、ということをしました。

ファイルのコピーが面倒です。今回はこのようにしました。

Linux(Virtual box)からホスト(win)にコピー

Virtual boxの共有の設定で適当なフォルダを設定します。

これで、linux上からホスト側にファイルのコピーができます。
コピー例は以下。

$ sudo cp hello.com /media/sf_VirtualBox_share

ホスト(win)からFreeDOS(Virtual box)にコピー

ディスクの管理からVHDの接続を選択して、
FreeDOSをインストールしたディスクイメージ(*.VHD)を選択します。

そうすると、エクスプローラーからディスクの中が見れるので、
先程Linuxからコピーしたファイルをコピーします。

Discussion