マシンの電源がオンになったら、最初にCPUのCS:IPをCS = 0xF000、IP = 0xFFF0に設定します。これは、CPU開発者とBIOS開発者の間で締結された合意であり、システム全体を実行するための論理的な開始点です。
0xFFFF0は、BIOSコードが配置されているROM領域の先頭です。CS:IPがこれをポイントすると、BIOSの基本的なIOデバイスチェックが実行されます。BIOSチェックが完了すると、ブートデバイス(ディスクなど)が実行されます。 、CD-ROM、フロッピーディスクなど)ディスク0のトラック0の最初のセクターは、0x07C00でメモリにロードされます。最後に、BIOSは0x07C00にジャンプし、オペレーティングシステムのブートプログラムに制御を移します。この0x07C00はBIOSの合意であり、オペレーティングシステムのブート領域をディスクからその場所にコピーすることを自由に選択できることに注意してください。たとえば、Seabiosのソースコードhttps://git.seabios.org/cgit/seabios.git/tree/src/boot.cでは、このアドレスは直接ハードコードされています。
そして、この0ディスクサーフェス0トラック1セクターはブート領域であり、このセクターの512バイトのコンテンツは、bootsect.sアセンブリコードのコンパイル後に取得されます。
次に、このコードが何をするか見てみましょう:
1つ目は、いくつかのセグメントのセグメントベース
アドレスを定義することです。BOOTSEG:BOOTセグメントアドレス
INITSEG:初期化アドレス。将来的には、ブート領域のコードがここで
SETUPSEG:セットアップ開始セグメントベースアドレス
SYSSEG:SYSセグメントベースにコピーされます。住所
.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text
SETUPLEN = 4 ! nr of setup-sectors
BOOTSEG = 0x07c0 ! original address of boot-sector
INITSEG = 0x9000 ! we move boot here - out of the way
SETUPSEG = 0x9020 ! setup starts here
SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).
ENDSEG = SYSSEG + SYSSIZE ! where to stop loading
! ROOT_DEV: 0x000 - same type of floppy as boot.
! 0x301 - first partition on first drive etc
ROOT_DEV = 0x306
次に、startと入力します。
entry _start
_start:
mov ax,#BOOTSEG
mov ds,ax
mov ax,#INITSEG
mov es,ax
mov cx,#256
sub si,si
sub di,di
rep
movw
jmpi go,INITSEG
go: ···
このコードは主に、BOOTSEGセグメントの512バイトのブートコードをINITSEGが配置されているセグメントにコピーするためのものです。movw命令は一度に2バイトの内容をコピーするため、cxの初期値は256であることに注意してください。
そして最後にjmpi go,INITSEG
。INITSEGの値はCSに与えられ、goのオフセットはIPに与えられます。これは、上記でブートをセグメント0x9000にコピーする作業が完了したためです。2つのセグメント0x07c0と0x9000には2つの同一のブートコードがあります。CSセグメントへのINITSEGは0x9000の先頭に転送され、実行したい量をコンパイルしてIPに移動することは、CPUを直接作成し、その後jmpi go,INITSEG
に続行するように指示することです。
go: mov ax,cs
mov ds,ax
mov es,ax
! put stack at 0x9ff00.
mov ss,ax
mov sp,#0xFF00 ! arbitrary value >>512
! load the setup-sectors directly after the bootblock.
! Note that 'es' is already set up.
CSが0x9000セグメントになった後、ds、es、ssの3つのセグメントレジスタを次々に設定し、同時にspレジスタの値を設定し、スタックの最上位を0x9FF00に設定します。
load_setup:
mov dx,#0x0000 ! drive 0, head 0
mov cx,#0x0002 ! sector 2, track 0
mov bx,#0x0200 ! address = 512, in INITSEG
mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors
int 0x13 ! read it
jnc ok_load_setup ! ok - continue
mov dx,#0x0000
mov ax,#0x0000 ! reset the diskette
int 0x13
j load_setup
その後すぐに、0x13割り込みを使用して、ブートディスクの2番目のセクターを開始し、合計SETUPLEN(4)セクターの内容をes:0x020(つまり、0x90200)のアドレスに読み取ります。
読み取りが正しい場合は、にジャンプしますok_load_setup
。そうでない場合は、dx、axをリセットし、load_setupをループで実行します。
ok_load_setup:
! Get disk drive parameters, specifically nr of sectors/track
mov dl,#0x00
mov ax,#0x0800 ! AH=8 is get drive parameters
int 0x13
mov ch,#0x00
seg cs
mov sectors,cx
mov ax,#INITSEG
mov es,ax
! Print some inane message
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10
mov cx,#24
mov bx,#0x0007 ! page 0, attribute 7 (normal)
mov bp,#msg1
mov ax,#0x1301 ! write string, move cursor
int 0x10
! ok, we've written the message, now
! we want to load the system (at 0x10000)
mov ax,#SYSSEG
mov es,ax ! segment of 0x010000
call read_it
call kill_motor
次のステップは、SYSTEMパーツをロードすることです。これも、0x13割り込みを使用して実行され、0x10000から始まるセグメントにSYSTEMパーツをロードします。同時に、0x10を使用して「Loadingsystem ...」のプロンプト文字列を出力します。
msg1:
.byte 13,10
.ascii "Loading system ..."
.byte 13,10,13,10
システムを読み取った後、ルートファイルシステムなどのマシンデータを準備する必要があります。この部分は重要ではありません。
! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently.
seg cs
mov ax,root_dev
cmp ax,#0
jne root_defined
seg cs
mov bx,sectors
mov ax,#0x0208 ! /dev/ps0 - 1.2Mb
cmp bx,#15
je root_defined
mov ax,#0x021c ! /dev/PS0 - 1.44Mb
cmp bx,#18
je root_defined
undef_root:
jmp undef_root
root_defined:
seg cs
mov root_dev,ax
最後に、を使用しjmpi 0,SETUPSEG
て、セットアップが配置されているコードセグメント、つまりCS = 0x90200、IP = 0にジャンプします。また、0x90200は、ブートディスクの最初のセクターから5番目のセクターまでです。
! after that (everyting loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:
jmpi 0,SETUPSEG