Linux0.11 カーネルのソース コード解析 - 起動コード bootsect.s(1)

序文:

前回Linux0.11版のカーネル解析を書いてからずいぶん経ちましたが、一つは主に地球上で友達が遭遇した疑問に答えたいから、もう一つは自分でアセンブリ言語を学び再訪するためです. 実は復習ではなく、基礎が貧弱で体系的に勉強したことがないだけです!実際、アセンブルは今でも非常に便利です. たとえば、一部の高級言語でエラーをデバッグする場合は、アセンブルを逆アセンブルできます. これは非常に役立ちます!

ここで突然アセンブリについて学んだ主な理由は、ブート ディレクトリにあるアセンブリ ソース コードを解析して、カーネルが読み込まれて実行されるまでの動作を確認したかったからです。実はこれ、ubootなどの組み込み開発をしている友人ならよく知っているはずです(実行過程や機能については繰り返しません!)。 . 詳しい内容はわかりません!

今日は、最近学んだことのいくつかをまとめたいと思います. この記事は、主に、カーネル バージョン linux0.11 のブート ディレクトリの下にある bootsect.s のコンパイル ソース コードの分析を分析することです。

7bcd33e47293042008b2e50f03ec50b2.png
Linux カーネル バージョン 0.11 ブート ディレクトリ

スタートアップ プロセスの分析を開始する前に、いくつかの優れた学習教材をお勧めします。

アセンブリ言語の学習では、最初にステーション b でこの教師のアセンブリの説明を読むことができます。これは非常に優れています。次に、それを Wang Shuang 先生の本と組み合わせて統合することができます。

b82c919411b27b059875ed76c69ed62d.png

コースアドレス:

https://www.bilibili.com/video/BV1pi4y1P76P?p=23&vd_source=6b552449c88698b9b658a83fbe4cde84

これを読んだ後に時間があれば、この本をもう一度勉強できます (リアル モードからプロテクト モードまでの X86 アセンブリ言語):

bcd4c9a​​42c5321f0bcc4aef2a556cf42.png

同時に、Linux カーネル バージョン 0.11 の実験環境については、ハルビン工科大学の Li Zhijun 氏が教えるオペレーティング システム コースから理論的な知識を学ぶことができます。

b6f6ae91ac82aa8cb16fce313605d00d.png

コースアドレス:

https://www.icourse163.org/learn/HIT-1002531008?tid=1450346461#/learn/content

実験したい場合は、このシミュレートされた環境で行うことができます。

38b06cf27a902e248b932a89722599d1.png

環境アドレス:

https://www.lanqiao.cn/courses/115/learning/?id=374

もちろん、もっと時間があれば、自分でオペレーティング システムの実装について考えることができます. この本を参照して、学習と実践を行うことができます (Orange's an operating system implementation):

bcd602ddd23e5863dee8a470da948c18.png e7b68a54b3d6dd398ec7f0e2720186fb.png

この記事の後半で、個人的な学習ノートを共有します。

わかりました、ここでこれらについて話しましょう。bootsect.s のソース コードの分析を始めましょう!

1. Bootsect.s ソースコード分析:

しかし、これについて話す前に、まず x86 レジスタを要約してから、ソース コードの分析を開始します。

x86 には 14 個のレジスタがあり、次のとおりです。

  • 1. 汎用レジスタ: AX、BX、CX、DX

  • 2.インデックスレジスタ:SI、DI

  • 3. ポインタレジスタ:SP、BP

  • 4.命令ポインタレジスタ:IP

  • 5. セグメント レジスタ: CS、SS、DS、ES

  • 6. フラグレジスタ: psw

特定の名前は、次の図で確認できます (画像ソースのネットワーク配置)。

4fdf0e888ad57173cf481e5e1baea6f8.png

ここでの目的は主に待つことです. ソースコードを解析するときはこれを参照してください. 他のアセンブリ手順はここでは要約しません!

通常、Windows システムまたは Linux システムを開くと、起動時にプロセスがあり、このプロセス中に起動ロゴが表示され、実際のアプリケーション デスクトップに入ることができます。

実はこちらの方が実用的で、例えば普段私たちが作っている組み込み製品もこんな感じで、電源を入れるとロゴが表示され、インターフェースに入ります!

しかし、この過程で自分が何をしたか考えたことはありますか? 組み込みの観点から見ると、プロセスは次のようになります。

uboot でカーネルを起動し、次にルート ファイル システムを起動し、最後に実際のアプリケーションを起動します。

今日は別の角度から見てみましょう (原理は同じです): X86 PC の電源を入れたときの動作

  • 1. x86 PC に最初に電源を入れたとき、CPU はリアル モードになっています。ここでの簡単な理解は、実際のアドレスアクセスモード、具体的な詳細です。これについて学ぶことができます! たとえば、CPUはどのようにアドレス指定しますか! 上記おすすめのまとめ本はこんな知識ポイントも!ここでは主に、CPU が実際の物理アドレスを見つける方法について説明します。ここでは、物理アドレス = セグメント アドレス x 16 (つまり、4 ビットを左にシフト) + オフセット アドレスを覚えておいてください。

  • 2. 同時起動時、メモリ cs=0xffff, ip=0x0000

  • 3. アドレス 0xffff0 (ROM BIOS の暗黙的な領域)、ここでの 0xffff0 は cs から 4 ビット左にシフトすることによって取得されることに注意してください。次に、このアドレス 0xffff0 からアドレッシングを開始する ip を追加します。このアドレスのコードは ROM です。バイオ!

  • 4. RAM、キーボード、モニター、ソフト、ハードディスクをチェックして、ここのチェックで問題が無ければ、そのまま実行できます!ここで問題が発生すると、カーネルをロードする操作がまったくダウンできなくなります。

  • 5. ディスクとトラック 0 セクタ (つまり、ブート セクタ) を 0x7c00 に読み込みます。つまり、bootsect.s を絶対メモリ アドレス 0x7C00 に読み込みます。

  • 6. cs=0x07c0、ip=0x0000 を設定します。

注: ロケーション 0x7c00 に格納されているコードは、ブート セクタから読み取られた 512 バイトであり、ブート セクタはブート デバイスの最初のセクタであり、ブート後に実行される最初のプログラム、つまり、上記の bootsect.s が格納されます。 .

上から。BIOS の主な仕事は、ハードウェアが正常かどうか (もちろん、割り込みベクトルの初期化を含む) をチェックし、bootsect.s を絶対アドレス 0x7c00 に追加して、一連の処理を開始することであることがわかります。特定の初期化操作について説明します。次に、アセンブリのソース コードを見てみましょう。ここでは、当面はその一部のみを示します。

ecfc6623686e7ad165e11f1e051db2bf.png
.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

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: 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.

コード分​​析:

  • .globl begtext、begdata、begbss、endtext、enddata、endbss: 6 つのグローバル識別子が定義されています

  • 次に、コード セグメント、データ セグメント、bss セグメント、およびテキスト セグメント:

.text      ###文本段
begtext:
.data      ###数据段 
begdata:
.bss       ###未初始化数据段 
begbss:
.text      ###文本段

上記はコンパイラが実行する命令である疑似命令であり、コンパイラは疑似命令に従って関連するコンパイル作業を行います。

  • 次に、関連するパラメーターが導入されます。

!也就是setup程序的扇区数为4块
SETUPLEN = 4    ! nr of setup-sectors 
!bootset的段地址为0x07c0
BOOTSEG  = 0x07c0   ! original address of boot-sector
#!把bootset移到这个地址0x9000上来
INITSEG  = 0x9000   ! we move boot here - out of the way
!setup程序就是从0x9020开始执行
SETUPSEG = 0x9020   ! setup starts here
!把system模块加载到0x10000这个地方来
SYSSEG   = 0x1000   ! system loaded at 0x10000 (65536).
!停止加载
ENDSEG   = SYSSEG + SYSSIZE  ! where to stop loading
  • ROOT_DEV = 0x306 は ROOT_DEV = 0x306 を意味します。これには、ハードディスクの命名方法が含まれます。自分で情報を確認して学習できます。

  • entry start: キーワード entry は、start がプログラムのエントリであることをリンカに伝えます。

メインコードから始めましょう:

start:
!把数据段器存器设置为0x7c00
 mov ax,#BOOTSEG 
 mov ds,ax  
!把es段器存器设置为0x9000
 mov ax,#INITSEG
 mov es,ax
 mov cx,#256 !把cx设置成256
!源地址为ds:si= 0x07c0:0x0000 这里写主要是为了形成偏移地址,这里为0,也就是形成了物理地址,下面的同理  
 sub si,si 
 sub di,di !目的地址为es:di = 0x9000:0x0000
 rep !重复执行,直到cx为0
 movw !移动一个字,这里w的意思是word,一个字,这里的意思也就是
  把0x07c0:0x0000处的256个字移动到 0x9000:0x0000
!这里的意思是0x7c0处的bootset程序跳转到0x9000:0x0000处去执行  
 jmpi go,INITSEG 
go: mov ax,cs !cs=0x90000
 mov ds,ax
 mov es,ax 
!这里的话把ds、cs、ss都设置成0x9000
! put stack at 0x9ff00. !将堆栈指针sp指向0x9ff00(0x9000:0xff00)
 mov ss,ax
 mov sp,#0xFF00  ! arbitrary value >>512

OK、ここに簡単な要約があります。このコードは主に、ブートセクトを 0x9000 の位置に移動することです! 後ろにもう一つ重要な部分があります.まず写真をあげさせてください.

eb608905a540d3ecd1af400d456ea0b8.png

2. まとめ:

今日のbootsect.sのソースコード解析はこれで終わりです。次号でソースコードの解析を続けます!

関連資料:

  • オペレーティング システム教師 Li Zhijun、ハルビン工科大学

  • Linux カーネルには完全に注釈が付けられています

https://www.bilibili.com/video/BV1iW411Y73K?p=3&vd_source=6b552449c88698b9b658a83fbe4cde84

ところで、個人的な友達の輪が開かれていて、ピットは限られています. 私は技術以外のことを共有することがよくあります. 興味があれば, チャットして友達を作ることができます. 技術的な側面も利用できます.お互いから離れて一緒に進んでいく:3人組、私の先生がいるに違いない!

f140d8bb8bae23561a701bc4e2a3c1f4.png
私はあなたを一掃しますか、それともあなたは私を一掃しますか?

おすすめ

転載: blog.csdn.net/Dada_ping/article/details/125955057
おすすめ