0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

「30日でできる!OS自作入門」五日目(harib02a〜harib02i)をUbuntu18.04/NASMで作る

Posted at

#はじめに
「30日でできる!OS自作入門」四日目の続きです。

#環境

$ uname -a
Linux furble 5.3.0-45-generic #37~18.04.1-Ubuntu SMP Fri Mar 27 15:58:10 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

$ nasm -v
NASM version 2.13.02

$ qemu-system-i386 --version
QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.23)

$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

#harib02a〜harib02d
新しく変える必要のある箇所無し。

#harib02e
元ファイルでは、hankaku.txtの内容を一行が1バイトになるよう、makefont.exeを使って変換していますが、ubuntuでは使えないので代わりを作ります。
hankaku.txtから以下のhankaku.cを生成します。

hankaku.c
char hankaku[4096] =  {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x38, 0x44, 0x82, 0xaa, 0xaa, 0x82, 0x82, 0xaa, 0x92, 0x44, 0x38, 0x00, 0x00, 0x00, 
... //16バイトx256行
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

OS自作入門 5日目-1 【Linux】 | サラリーマンがハッカーを真剣に目指す
からコードをお借りしました。

conv-hankakuTxt.c
#include <stdio.h>
#include <string.h>
 
int main() {
    FILE *infp;
    FILE *outfp;
    char s1[] = "char hankaku[4096] =  {\n\t";
    char s2[] = "\n};\n\n";
    char buf[256] = {0};
    char wbuf[256] = {0};
    int d;
 
    if ((infp = fopen("hankaku.txt","r")) == NULL) {
        printf("input file open error\n");
        return 0;
    }
 
    if ((outfp = fopen("hankaku.c","w")) == NULL) {
        printf("output file open error\n");
        return 0;
    }
 
    fwrite(s1, sizeof(char), strlen(s1), outfp);
 
    fgets(buf, sizeof(buf), infp);
    for(int k = 0; k < 256; k++) {
      // 2行読み飛ばす
        for(int i = 0; i < 2; i++) {
          fgets(buf, sizeof(buf), infp);
        }
        for(int i = 0; i < 16; i++) {
            d = 0;
            fgets(buf, sizeof(buf), infp);
            for(int j = 0; j < 8; j++) {
                if(buf[j] == '*') d |= (1 << (7-j));
            }
            sprintf(wbuf, "0x%02x, ", d); //0詰めの2桁16進数で表示
            if(k == 255 && i == 15) {
              //256文字分すべてを読み終わったとき
              fwrite(wbuf, 1, 4, outfp); //一番最後は", "は出力しない
            } else {
              fwrite(wbuf, 1, 6, outfp); // "0x00, "の6byte分
            }
        }
        fwrite("\n\t", 1, 2, outfp); //16B分書き込んだら改行を入れる
    }

    fwrite(s2, sizeof(char), strlen(s2), outfp);
    fclose(infp);
    fclose(outfp);
}

このconv-hankakuTxt.cをコンパイル、実行すればhankaku.cに先程の配列が入ることになります。
あとはMakefileに書いてある通りです。

Makefile
...
conv-hankakuTxt : conv-hankakuTxt.c Makefile
	gcc conv-hankakuTxt.c -o conv-hankakuTxt

hankaku.c : hankaku.txt conv-hankakuTxt Makefile
	./conv-hankakuTxt

hankaku.o : hankaku.c Makefile
	gcc -m32 -c hankaku.c -o hankaku.o

bootpack.hrb : bootpack.c har.ld nasmfunc.o hankaku.o Makefile
	gcc -fno-pie -no-pie -march=i486 -m32 -nostdlib -T har.ld bootpack.c hankaku.o nasmfunc.o -o bootpack.hrb
...

hankaku.cをコンパイルする際には、-m32オプションを入れてください。入れないと

gcc -c hankaku.c -o hankaku.o
gcc -fno-pie -no-pie -march=i486 -m32 -nostdlib -T har.ld bootpack.c hankaku.o nasmfunc.o -o bootpack.hrb
/usr/bin/ld: i386:x86-64 アーキテクチャ (入力ファイル`hankaku.o') は i386 出力と互換性がありません
collect2: error: ld returned 1 exit status

とエラーが出ます。

#harib02f
新しく変える必要のある箇所無し。

#harib02g
元ファイルの通りにbootpack.cを変更すると、下のように#include <stdio.h>の箇所でエラーが出ます。

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>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

そこで再びこちらのサイトからsprintf関数を作ります。
sprintfを実装する | OS自作入門 5日目-2 【Linux】 | サラリーマンがハッカーを真剣に目指す

mprintf.c
#include <stdarg.h>
 
//10進数からASCIIコードに変換
int dec2asc (char *str, int dec) {
    int len = 0, len_buf; //桁数
    int buf[10];
    while (1) { //10で割れた回数(つまり桁数)をlenに、各桁をbufに格納
        buf[len++] = dec % 10;
        if (dec < 10) break;
        dec /= 10;
    }
    len_buf = len;
    while (len) {
        *(str++) = buf[--len] + 0x30;
    }
    return len_buf;
}
 
//16進数からASCIIコードに変換
int hex2asc (char *str, int dec) { 
    int len = 0, len_buf; //桁数
    int buf[10];
    while (1) {//16で割れた回数(つまり桁数)をlenに、各桁をbufに格納
        buf[len++] = dec % 16;
        if (dec < 16) break;
        dec /= 16;
    }
    len_buf = len;
    while (len) {
        len --;
        *(str++) = (buf[len]<10)?(buf[len] + 0x30):(buf[len] - 9 + 0x60);
    }
    return len_buf;
}
 
void msprintf (char *str, char *fmt, ...) {
    va_list list;
    int i, len;
    va_start (list, fmt);
 
    while (*fmt) {
        if(*fmt=='%') {
            fmt++;
            switch(*fmt){
                case 'd':
                    len = dec2asc(str, va_arg (list, int));
                    break;
                case 'x':
                    len = hex2asc(str, va_arg (list, int));
                    break;
            }
            str += len; fmt++;
        } else {
            *(str++) = *(fmt++);
        }   
    }
    *str = 0x00; //最後にNULLを追加
    va_end (list);
}

一箇所だけ、下の警告が出ていたので、
va_start (list, fmt);
に直したら警告が消えました。可変個引数の前の最後の引数名を指定すると良いようです。

msprintf.c
m-sprintf.c: In function msprintf:
m-sprintf.c:39:5: warning: second parameter of va_start not last named argument [-Wvarargs]
     va_start (list, 2);
     ^~~~~~~~

自分は何となく不安なので関数名をmsprintfにしましたが、stdio.hをインクルードしない限りsprintfのままで問題無いと思います。
あとは、bootpack.cの頭のstdio.hのインクルードを消し、代わりに
void msprintf (char *str, char *fmt, ...);
を追加、Makefileは下のように変更しました。

Makefile
MAKE     = make -r
NASM     = nasm
CFLAGS	= -m32 -march=i486 -nostdlib
...
msprintf.o : msprintf.c Makefile
	gcc -fno-pie $(CFLAGS) -c msprintf.c -o msprintf.o

bootpack.hrb : bootpack.c har.ld nasmfunc.o hankaku.o msprintf.o Makefile
	gcc -fno-pie -no-pie $(CFLAGS) -T har.ld bootpack.c hankaku.o nasmfunc.o msprintf.o -o bootpack.hrb
...

#harib02h、harib02i
新しく変える必要のある箇所無し。
ただし、asmファイルに追加する関数名の頭に_(アンダーバー)は付けないよう注意してください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?