OS
# HELLO-OS
`hello.img` という名のファイルを作ります。
まずはじめに、`4096 byte` を `0埋め` します。
~~~
$ vim hello.img
$ sudo dd if=/dev/zero of=hello.img bs=4096 count=16
~~~
`vim` の `binary` モードで開きます。
~~~
$ vim -b hello.img
:%!xxd
~~~
そして、以下のように改変します。
~~~
0000000: eb4e 9048 454c 4c4f 4950 4c00 0201 0100 .N.HELLOIPL.....
0000010: 02e0 0040 0bf0 0900 1200 0200 0000 0000 ...@............
0000020: 400b 0000 0000 29ff ffff ff48 454c 4c4f @.....)....HELLO
0000030: 2d4f 5320 2020 4641 5431 3220 2020 0000 -OS FAT12 ..
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000050: b800 008e d0bc 007c 8ed8 8ec0 be74 7c8a .......|.....t|.
0000060: 0483 c601 3c00 7409 b40e bb0f 00cd 10eb ....<.t.........
0000070: eef4 ebfd 0a0a 6865 6c6c 6f2c 2077 6f72 ......hello, wor
0000080: 6c64 0a00 0000 0000 0000 0000 0000 0000 ld..............
0000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
...
00001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
0000200: f0ff ff00 0000 0000 0000 0000 0000 0000 ................
...
0001400: f0ff ff00 0000 0000 0000 0000 0000 0000 ................
~~~
書き込みます。
~~~
:%!xxd -r
:wq!
~~~
macOS の場合は、`diskutil` を使用し、デバイスを確認の上、`USB` 記憶装置に書き込みます。
~~~
# diskutil list
(check mount devices)
# dd if=hello.img of=/dev/disk1 bs=4096
~~~
これで、OS 1日目終了です。
`USB` を BIOS から起動してください。
# Assembler DAY02
今度はアセンブラをみていこう
nask : developped nasm
* A : accumulator : 累積演算機
* C : counter register: 数える
* D : data register :
* B : base register : 配列のベースアドレスなどを格納
* SP : stack pointer :
- スタック用に確保されたメモリ領域のコールスタック位置のアドレスを格納
- `push` 時にアドレスをひとつ手前にもどす
- `pop` 時にインクリメントする
* BP : starck base pointer :
* SI : source index :
* DI : destination index :
HELLOOS.img (ONLY DISPLAY "HELLO,WORLD!")
~~~
0000000: eb4e 9048 454c 4c4f 4950 4c00 0201 0100 .N.HELLOIPL.....
0000010: 02e0 0040 0bf0 0900 1200 0200 0000 0000 ...@............
0000020: 400b 0000 0000 29ff ffff ff48 454c 4c4f @.....)....HELLO
0000030: 2d4f 5320 2020 4641 5431 3220 2020 0000 -OS FAT12 ..
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000050: b800 008e d0bc 007c 8ed8 8ec0 be74 7c8a .......|.....t|.
0000060: 0483 c601 3c00 7409 b40e bb0f 00cd 10eb ....<.t.........
0000070: eef4 ebfd 0a0a 4845 4c4c 4f2c 574f 524c ......HELLO,WORL
0000080: 4421 0a00 D!..
~~~
HELLOOS.nas (nasm assembler code)
~~~
; hello-os
; TAB=4
; Begin MasterBootRecord
;
ORG 0x7c00 ; このプログラムがメモリのどこに読み込まれるのか
;
; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述
;
JMP entry
DB 0x90
DB "HELLOIPL" ; ブートセクタの名前を自由に書いてよい(8バイト)
DW 512 ; 1セクタの大きさ(512にしなければいけない)
DB 1 ; クラスタの大きさ(1セクタにしなければいけない)
DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする)
DB 2 ; FATの個数(2にしなければいけない)
DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする)
DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない)
DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない)
DW 9 ; FAT領域の長さ(9セクタにしなければいけない)
DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない)
DW 2 ; ヘッドの数(2にしなければいけない)
DD 0 ; パーティションを使ってないのでここは必ず0
DD 2880 ; このドライブ大きさをもう一度書く
DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい
DD 0xffffffff ; たぶんボリュームシリアル番号
DB "HELLO-OS " ; ディスクの名前(11バイト)
DB "FAT12 " ; フォーマットの名前(8バイト)
resb 18 ; とりあえず18バイトあけておく
;
; プログラム本体
;
entry:
MOV AX,0 ; b80000 レジスタ初期化
MOV SS,AX ; 8ed0
MOV SP,0x7c00 ; bc007c
MOV DS,AX ; 8ed8
MOV ES,AX ; 8ec0
;
MOV SI,msg ; be747c
;
;
putloop:
MOV AL,[SI] ; 8a0483
ADD SI,1 ; c601 SIに1を足す
CMP AL,0 ; 3c00
JE fin ; 7409
MOV AH,0x0e ; b40e 一文字表示ファンクション
MOV BX,15 ; bb0f00 カラーコード
INT 0x10 ; cd10 ビデオBIOS呼び出し
JMP putloop ; ebee
;
;
fin:
HLT ; f4 何かあるまでCPUを停止させる
JMP fin ; ebfd 無限ループ
;
0a0a 6865 6c6c 6f2c 2077 6f72 6c64 0a00
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "hello, world"
DB 0x0a ; 改行
DB 0
resb 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
;
; End MasterBootRecord
; 以下はブートセクタ以外の部分の記述
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
resb 4600
DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
;
resb 1469432
~~~
## FAT12
*************************************************************************************
* *
* *
* 0 -------- *
* MBP(512B) *
* 200 -------- .---------------------------------------------. *
* | | *
* | attribute(1) | *
* | | | *
* | +-------------------+-------.|.---------+ | *
* 2600 -------- | | file name(8 byte) |type(3)| | (10| | *
* Root Dir -->| +-------------------+----+--+-+---------+ | *
* | |) | | | size(4) | | *
* | +-------------------+-|--+-|--+---------+ | *
* | | | | *
* 4200 -------- | | storedSector(2) | *
* DataArea | updatedTime(2) | *
* (sector 02) | | *
* 4400 -------- '---------------------------------------------' *
* (sector 03) 32 byte per 1 file information *
* 4600 -------- *
* .. *
* *
* 5200 -------- *
* (sector 0A) *
* -------- *
* .. *
* until 2848 *
*************************************************************************************
## MEMORYMAP OF BIOS
Low Memory (the first MiB)
~~~
0x00000000 0x000003FF 1 KiB RAM - partially unusable (see above) Real Mode IVT (Interrupt Vector Table)
0x00000400 0x000004FF 256 bytes RAM - partially unusable (see above) BDA (BIOS data area)
0x00000500 0x00007BFF almost 30 KiB RAM (guaranteed free for use) Conventional memory
0x00007C00 0x00007DFF 512 bytes RAM - partially unusable (see above) Your OS BootSector
0x00007E00 0x0007FFFF 480.5 KiB RAM (guaranteed free for use) Conventional memory
0x00080000 0x0009FBFF approximately 120 KiB, depending on EBDA size RAM (free for use, if it exists) Conventional memory
0x0009FC00 0x0009FFFF 1 KiB RAM (unusable) EBDA (Extended BIOS Data Area)
0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area
~~~
BIOS Data Area (BDA)
~~~
0x0400 (4 words) IO ports for COM1-COM4 serial (each address is 1 word, zero if none)
0x0408 (3 words) IO ports for LPT1-LPT3 parallel (each address is 1 word, zero if none)
0x040E (word) EBDA base address >> 4 (usually!)
0x0410 (word) packed bit flags for detected hardware
0x0417 (word) keyboard state flags
0x041E (32 bytes) keyboard buffer
0x0449 (byte) Display Mode
0x044A (word) number of columns in text mode
0x0463 (2 bytes, taken as a word) base IO port for video
0x046C (word) # of IRQ0 timer ticks since boot
0x0475 (byte) # of hard disk drives detected
0x0480 (word) keyboard buffer start
0x0482 (word) keyboard buffer end
0x0497 (byte) last keyboard LED/Shift key state
~~~
Extended BIOS Data Area (EBDA)
~~~
0x000A0000 0x000BFFFF 128 KiB video RAM VGA display memory
0x000C0000 0x000C7FFF 32 KiB (typically) ROM Video BIOS
0x000C8000 0x000EFFFF 160 KiB (typically) ROMs and unusable space Mapped hardware & Misc.
0x000F0000 0x000FFFFF 64 KiB ROM Motherboard BIOS
~~~
## Makefile
~~~
Makefile
----------
opt: component01 component02 ..
shellScript
~~~
then type
~~~
$ make opt
~~~
## edimg
bin コマンドの `edimg` が使いにくそうなのでつくってみる
~~~c
#include
#include
#define READNUM 1024
FILE *fpr,*fpw;
char *input,*output,*addsrc;
int len,from,to;
char buf[1024];
void usage(){printf("\
*********\n\
* usage *\n\
*********\n\
\n\
******************************************\n\
$ edimg -i input \n\
-o output \n\
--addsrc src\n\
startpoint-of-input\n\
startpoint-of-srcfile\n\
length\n\
******************************************\n");exit(1);
}
void configure_args(int argc, char** argv)
{
if(argc==1) usage();
int i=1;
while(i < argc)
{
if (argv[i][0]=='-')
switch(argv[i][1])
{
case 'i':
input=argv[i+1];
i+=2;break;
case 'o':
output=argv[i+1];
i+=2;break;
case '-':
if (strcmp(&argv[i][2],"addsrc")!=0) usage();
addsrc=argv[i+1];
from=atoi(argv[i+2]);
to=atoi(argv[i+3]);
len=atoi(argv[i+4]);
i+=5;;break;
default:
usage();
}
else usage();
}
}
void copyonestep(FILE * fpr, FILE * fpw, int bufnum)
{
int r = fread(buf,1,bufnum,fpr);
int w = fwrite(buf,1,r,fpw);
if(r!=READNUM)
printf("Skipped some %d bytes.\n",READNUM - r);
}
void copy(char * read,long start, long end)
{
FILE * fpr = fopen(read, "rb");
FILE * fpw = fopen(output, "ab");
if (end-EOF==0)
{
fseek(fpr,start,SEEK_SET);
while(1){
copyonestep(fpr,fpw,READNUM);
if (feof(fpr)) break;
}
}
else
{
int i = (end-start) / READNUM;
int rest = (end-start) % READNUM;
while ( i > 0 )
{
copyonestep(fpr,fpw,READNUM);
--i;
}
copyonestep(fpr,fpw,rest);
}
fclose(fpr);
fclose(fpw);
}
int main(int argc, char** argv)
{
configure_args(argc, argv);
fpw = fopen(output,"w");
fclose(fpw);
copy(input,0,from);
copy(addsrc,from,from+len);
copy(input,from+len,EOF);
return 0;
}
~~~
# LOAD DISK DAY03
## `INT 0x13` - READ , WRITE , VERIFY ,or SEEK disk
~~~
AH = 0x02 -> READ
AH = 0x03 -> WRITE
AH = 0x04 -> VERIFY
AH = 0x0c -> SEEK
AL = length of sectors
CH = $Cylinder & 0xff (0..79)
CL = $Sector (1..18)
DH = $Header (0,1)
DL = $Drive
ES:BX = buffer address (only when READ & WRITE)
RETURN VALUE
FLAGS.CF == 0 : no err AH = 0
== 1 : error AH = err code
~~~
![](/image/hard-disk.gif)
from [here ](http://www.computableminds.com/post/Hard-disk/HDD/HD/partition/good/bad/track/sector/cylinder/head)
## MEMORY ADDRESS
******************************************************
* *
* [BX] ~0xffff *
* | *
* | enlarge *
* v *
* [ES:BX] := [ES*16 + BX] ~0xfffff *
* | *
* | *
* v *
* [EBX] ~0xfffffff *
* *
******************************************************
Being the Old System,
BIOS couldn't use EBX .
So,
`[ES:BX]` was needed .
you have to initialise with
~~~
DS = 0;
~~~
because
~~~
[1234] := [DS * 16 + 1234]
~~~
## Into the C program world
******************************************************
* *
* bootpack.c *
* | *
* v cc *
* bootpack.gas *
* | *
* v gas2nask *
* bootpack.nas *
* | *
* v nasm(nask) *
* bootpack.obj *
* | *
* v obj2bim (linker) *
* bootpack.bim *
* | *
* v +header +zip *
* bootpack.hrb *
* | *
* v $ cat asmhead bootpack.hrb *
* os.img *
* *
******************************************************
# read & write memory on c
operate register1
~~~
char c;
volatile char *reg1 = (char *)0x10000000;
c = *reg1; // read from reg1
*reg1 = 0x01; // write to reg1
~~~