OS自作入門18日目 【Linux】 | 自作strcmp関数とコマンド名の変更

30日でできる!OS自作入門の18日目の記事です。
こんかいはメモリの使用量を確認するためのmemコマンド、
コンソールを綺麗にするclsコマンド、
ファイルの中身をみるためのdirコマンドを実装します。

書籍の内容自体はそこまで難しくはないのですが、
strcmpがうまくリンクできなかったので
strcmpを自作しました。
 



 
 


使用環境

$ uname -a
Linux ***-E200HA 4.10.0-37-generic #41-Ubuntu SMP Fri Oct 6 20:20:37 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ nasm -version
NASM version 2.13.01
$ qemu-system-i386 --version
QEMU emulator version 2.10.1(Debian 1:2.10+dfsg-0ubuntu13)
$ gcc --version
gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413

 
 
 


strcmpを自作する

ソースコード

int strcmp(char *str1, char *str2) {
    int i;
    for (i = 0; i < 20; i++) {
        if (str1[i] == 0x00 && str2[i] == 0x00) return 0;
        if (str1[i] == 0x00) return 1;
        if (str2[i] == 0x00) return 1;
        if (str1[i] != str2[i]) return 1;
    }
    return -1;
}


長いコマンド名は登場しなさそうなので
ループ回数は20回の固定にしました。

str1とstr2が同時にNULLになった時のみ0を返し、
どちらかが先にNULLになったり、
文字列が異なれば1を返します。

また20文字を超えるようであれば-1を返すようにしました。
 
 
 


コマンド名を変えてみる

せっかくlinuxでやってるんだから
dirじゃなくてlsでしょ!
ってことでコマンド名を変更してみました。

/* bootpack.c */
//} else if (strcmp(cmdline, "cls") == 0) {
} else if (strcmp(cmdline, "clear") == 0) {
	for (y = 28; y < 28 + 128; y++) {
		for (x = 8; x < 8 + 240; x++) {
			sheet->buf[x + y * sheet->bxsize] = COL8_000000;
		}
	}
	sheet_refresh(sheet, 8, 28, 8 + 240, 28 + 128);
	cursor_y = 28;
//} else if (strcmp(cmdline, "dir") == 0) {
} else if (strcmp(cmdline, "ls") == 0) {
	for (x = 0; x < 224; x++) {
		if (finfo[x].name[0] == 0x00) {
			break;
		}
		if (finfo[x].name[0] != 0xe5) {
			if ((finfo[x].type & 0x18) == 0) {
				sprintf(s, "filename.ext   %7d", finfo[x].size);
				for (y = 0; y < 8; y++) {
					s[y] = finfo[x].name[y];
				}
				s[ 9] = finfo[x].ext[0];
				s[10] = finfo[x].ext[1];
				s[11] = finfo[x].ext[2];
				putfonts8_asc_sht(sheet, 8, cursor_y, COL8_FFFFFF, COL8_000000, s, 30);
				cursor_y = cons_newline(cursor_y, sheet);
			}
		}
	}
	cursor_y = cons_newline(cursor_y, sheet);
}


コメントアウトした2行を変更するだけです。

 
 
 


dir(ls)コマンドで実験

最後にすこし実験をしてみました。
私はosのイメージを生成するために
mformat → mcopy
で作っています。

詳細はこの記事を参考にしてください。

ここに適当なファイルをmcopyしてみます。
【変更前】

os.img: ipl.bin os.sys
	mformat -f 1440 -C -B ipl.bin -i os.img ::
	mcopy -i os.img os.sys ::

【変更後】

os.img: ipl.bin os.sys
	mformat -f 1440 -C -B ipl.bin -i os.img ::
	mcopy -i os.img os.sys ::
	mcopy -i os.img mysprintf.c ::


ちなみに適当にmysprintf.cをimgファイル中に保存してみます。
 
 
make runのあとdir(ls)コマンドを実行してみると

こんな感じで表示されるようになります。
mysprintf.cの文字が途切れているように見えますが、
これはFAT12フォーマットによるものです。

FAT12フォーマットではファイル名の規則として
ファイル名8文字+拡張子3文字という情報に置き換えられます。

今回のmysprintf.cの場合、
ファイル名が8文字をオーバーしているので、切り捨てられ、
また拡張子は3文字に満たないため、空白が入ります。
※実際は切り捨てられるというよりは、
命名規則に従って変換され、本来のファイル名は別の場所に記録されます。

結果として画像のような名前を出力したわけです。

 
 
 


mcopyコマンドってなに?

今回の場合、fat12にフォーマットされたファイルに
書き込む用途で使っています。

mcopy -i os.img mysprintf.c

このコマンドによってos.imgにmysprintf.cを書き込んでいます。

過去にも掲載しましたが、FAT12フォーマットは
下図のような構造をしています。

mysprintf.cのファイル名やタイムスタンプなどのヘッダ情報が
ルートディレクトリに書き込まれ、
ファイルの内容がファイル領域に書き込まれ、
そしてその記録順がFAT領域に書き込まれます。

 
 
今のところ環境の違いも無事乗りきれています。
次は待望の(個人的に)アプリケーションです。
どのようにアプリケーション側に制御が移って、
また戻るのか。
そのあたりが気になるところです。
 
 
【関連記事】
OS自作入門 1日目
OS自作入門 3日目-1
OS自作入門17日目
OS自作入門19日目
30日でできる!OS自作入門 まとめ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です