日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

《30天自制操作系统》前言、目录、样章欢迎阅读!

發布時間:2024/4/11 windows 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《30天自制操作系统》前言、目录、样章欢迎阅读! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
編著推薦:
只需30天從零開始編寫一個五臟俱全的圖形操作系統 如果肯堅持,沒有什么不可以!祝所有讀到這篇文章的人都能寫出好的操作系統!

?

內容簡介:?
  自己編寫一個操作系統,是許多程序員的夢想。也許有人曾經挑戰過,但因為太難而放棄了。其實你錯了,你的失敗并不是因為編寫操作系統太難,而是因為沒有人告訴你那其實是一件很簡單的事。那么,你想不想再挑戰一次呢?
  這是一本兼具趣味性、實用性與學習性的書籍。作者從計算機的構造、匯編語言、C語言開始解說,讓你在實踐中掌握算法。在這本書的指導下,從零編寫所有代碼,30天后就可以制作出一個具有窗口系統的32位多任務操作系統。
  本書以課題為主導,邊做邊玩,拋開晦澀難懂的語言,行文風格十分隨性,還充滿了各種歡樂的吐槽,適合操作系統愛好者和程序設計人員閱讀。

作者簡介:
川合秀實(Hidemi Kawai)
? 生于1975年,是一位以“輕量化”編程思想見長的“非主流”開發者。2000年因自行開發的OSASK項目而名聲大噪。OSASK是一個開源的 32位微型操作系統,它并非以Linux等內核為基礎,而是完全從零開始開發,在一張軟盤的容量下實現了GUI、多任務、多語言等高級特性,啟動時間只需 1秒。本書的內容可以看成是作者以OSASK為藍本,教會讀者從零開始開發一個操作系統,同時可以讓初學者在編寫操作系統的過程中,了解操作系統背后更多 的知識。

作者網站:http://hrb.osask.jp/

前  言
  “好想編寫一個操作系統呀!”筆者的朋友曾說這是所有程序員都曾經懷揣的一個夢想。說“所有的程序員”可能有點夸張了,不過作為程序員的夢想,它至少也應該能排進前十名吧。

  也許很多人覺得編寫操作系統是個天方夜譚,這一定是操作系統業界的一個陰謀(笑)。他們故意讓大家相信編寫操作系統是一件非常困難的事情,這樣就 可以高價兜售自己開發的操作系統,而且操作系統的作者還會被頂禮膜拜。那么實際情況又怎么樣呢?和別的程序相比,其實編寫操作系統并沒有那么難,至少筆者 的感覺是這樣。

  在各位讀者之中,也許有人曾經挑戰過操作系統的編寫,但因為太難而放棄了。擁有這樣經歷的人也許不會認同筆者的觀點。其實你錯了,你的失敗并不是因為編寫操作系統太難,而是因為沒有人告訴你那其實是一件很簡單的事而已。

  不僅是編寫操作系統,任何事都是一樣的。如果講解的人認為它很難,那就不可能把它講述得通俗易懂,即便是同樣的內容,也會講得無比復雜。這樣的講解,肯定是很難懂的。

  那么,你想不想和筆者一起再挑戰一次呢?如果你曾經夢想過編寫自己的操作系統,一定會覺得樂在其中的。

  可能有人會說,這本書足足有700多頁,怎么會“有趣”和“簡單”呢?唔,這么一說筆者也覺得挺心虛的,不過其實也只是長了那么一點點啦。平均下來的話,每天只有大約23頁的內容,你看,也沒有那么長吧?

  這本書的文風非常輕松,也許你不知不覺中就會讀得很快。但是這樣的話可能印象不會很深,最好還是能靜下心來慢慢地讀。書中所展示的程序代碼和文字的說明同樣重要,因此也希望大家仔細閱讀。只要注意這些,理解本書的內容就應該沒有問題了。

  在本書中,我們使用C語言和匯編語言來編寫操作系統,不過不必擔心,你可以在閱讀本書的同時來逐步學習關于這些編程語言的知識。本書在這方面寫得 非常仔細,如果能有人通過本書終于把C語言中的指針給搞懂了,那筆者的目的也就達到了。即便是從這樣的水平開始,30天后你也能夠編寫出一個很棒的操作系 統,請大家拭目以待吧!

目    錄
第0天  著手開發之前  1
1  前言  1
2  何謂操作系統  3
3  開發操作系統的各種方法  4
4  無知則無畏  4
5  如何開發操作系統  6
6  操作系統開發中的困難  7
7  學習本書時的注意事項(重要!)  9
8  各章內容摘要  11
第1天  從計算機結構到匯編程序入門  13
1  先動手操作  13
2  究竟做了些什么  19
3  初次體驗匯編程序  22
4  加工潤色  24
第2天  匯編語言學習與Makefile入門  28
1  介紹文本編輯器  28
2  繼續開發  29
3  先制作啟動區  40
4  Makefile入門  41
第3天  進入32位模式并導入C語言  45
1  制作真正的IPL  45
2  試錯  50
3  讀到18扇區  51
4  讀入10個柱面  52
5  著手開發操作系統  54
6  從啟動區執行操作系統  55
7  確認操作系統的執行情況  56
8  32位模式前期準備  57
9  開始導入C語言  59
10  實現HLT(harib00j)  62
第4天  C語言與畫面顯示的練習  64
1  用C語言實現內存寫入(harib01a)  64
2  條紋圖案(harib01b)  67
3  挑戰指針(harib01c)  69
4  指針的應用(1)(harib01d)  74
5  指針的應用(2)(harib01e)  74
6  色號設定(harib01f)  75
7  繪制矩形(harib01g)  84
8  今天的成果(harib01h)  86
第5天  結構體、文字顯示與GDT/IDT初始化  88
1  接收啟動信息(harib02a)  88
2  試用結構體(harib02b)  89
3  試用箭頭記號(harib02c)  91
4  顯示字符(harib02d)  91
5  增加字體(harib02e)  94
6  顯示字符串(harib02f)  96
7  顯示變量值(harib02g)  97
8  顯示鼠標指針(harib02h)  99
9  GDT與IDT的初始化(harib02i)  101
第6天  分割編譯與中斷處理  108
1  分割源文件(harib03a)  108
2  整理Makefile(harib03b)  109
3  整理頭文件(harib03c)  110
4  意猶未盡  112
5  初始化PIC(harib03d)  115
6  中斷處理程序的制作(harib03e)  119
第7天  FIFO與鼠標控制  125
1  獲取按鍵編碼(hiarib04a)  125
2  加快中斷處理(hiarib04b)  127
3  制作FIFO緩沖區(hiarib04c)  130
4  改善FIFO緩沖區(hiarib04d)  133
5  整理FIFO緩沖區(hiarib04e)  135
6  總算講到鼠標了(harib04f)  138
7  從鼠標接受數據(harib04g)  141
第8天  鼠標控制與32位模式切換  144
1  鼠標解讀(1)(harib05a)  144
2  稍事整理(harib05b)  146
3  鼠標解讀(2)(harib05c)  148
4  移動鼠標指針(harib05d)  151
5  通往32位模式之路  153
第9天  內存管理  162
1  整理源文件(harib06a)  162
2  內存容量檢查(1)(harib06b)  163
3  內存容量檢查(2)(harib06c)  168
4  挑戰內存管理(harib06d)  172
第10天  疊加處理  181
1  內存管理(續)(harib07a)  181
2  疊加處理(harib07b)  184
3  提高疊加處理速度(1)(harib07c)  194
4  提高疊加處理速度(2)(harib07d)  197
第11天  制作窗口  201
1  鼠標顯示問題(harib08a)  201
2  實現畫面外的支持(harib08b)  202
3  shtctl的指定省略(harib08c)  203
4  顯示窗口(harib08d)  206
5  小實驗(harib08e)  208
6  高速計數器(harib08f)  209
7  消除閃爍(1)(harib08g)  211
8  消除閃爍(2)(harib08h)  214
第12天  定時器(1)  220
1  使用定時器(harib09a)  220
2  計量時間(harib09b)  224
3  超時功能(harib09c)  225
4  設定多個定時器(harib09d)  228
5  加快中斷處理(1)(harib09e)  232
6  加快中斷處理(2)(harib09f)  234
7  加快中斷處理(3)(harib09g)  236
第13天  定時器(2)  240
1  簡化字符串顯示(harib10a)  240
2  重新調整FIFO緩沖區(1)(harib10b)  241
3  測試性能(harib10c~harib10f)  243
4  重新調整FIFO緩沖區(2)(harib10g)  246
5  加快中斷處理(4)(harib10h)  253
6  使用“哨兵”簡化程序(harib10i)  257
第14天  高分辨率及鍵盤輸入  262
1  繼續測試性能(harib11a~harib11c)  262
2  提高分辨率(1)(harib11d)  266
3  提高分辨率(2)(harib11e)  269
4  鍵盤輸入(1)(harib11f)  272
5  鍵盤輸入(2)(harib11g)  275
6  追記內容(1)(harib11h)  277
7  追記內容(2)(harib11i)  279
第15天  多任務(1)  282
1  挑戰任務切換(harib12a)  282
2  任務切換進階(harib12b)  289
3  做個簡單的多任務(1)(harib12c)  291
4  做個簡單的多任務(2)(harib12d)  293
5  提高運行速度(harib12e)  294
6  測試運行速度(harib12f)  297
7  多任務進階(harib12g)  299
第16天  多任務(2)  304
1  任務管理自動化(harib13a)  304
2  讓任務休眠(harib13b)  308
3  增加窗口數量(harib13c)  313
4  設定任務優先級(1)(harib13d)  317
5  設定任務優先級(2)(harib13e)  320
第17天  命令行窗口  329
1  閑置任務(harib14a)  329
2  創建命令行窗口(harib14b)  331
3  切換輸入窗口(harib14c)  334
4  實現字符輸入(harib14d)  337
5  符號的輸入(harib14e)  341
6  大寫字母與小寫字母(harib14f)  343
7  對各種鎖定鍵的支持(harib14g)  346
第18天  dir命令  350
1  控制光標閃爍(1)(harib15a)  350
2  控制光標閃爍(2)(harib15b)  352
3  對回車鍵的支持(harib15c)  355
4  對窗口滾動的支持(harib15d)  357
5  mem命令(harib15e)  359
6  cls命令(harib15f)  363
7  dir命令(harib15g)  366
第19天  應用程序  371
1  type命令(harib16a)  371
2  type命令改良(harib16b)  378
3  對FAT的支持(harib16c)  382
4  代碼整理(harib16d)  387
5  第一個應用程序(harib16e)  387
第20天  API  392
1  程序整理(harib17a)  392
2  顯示單個字符的API(1)(harib17b)  399
3  顯示單個字符的API(2)(harib17c)  402
4  結束應用程序(harib17d)  403
5  不隨操作系統版本而改變的API(harib17e)  405
6  為應用程序自由命名(harib17f)  408
7  當心寄存器(harib17g)  410
8  用API顯示字符串(harib17h)  412
第21天  保護操作系統  418
1  攻克難題——字符串顯示API(harib18a)  418
2  用C語言編寫應用程序(harib18b)  420
3  保護操作系統(1)(harib18c)  424
4  保護操作系統(2)(harib18d)  426
5  對異常的支持(harib18e)  431
6  保護操作系統(3)(harib18f)  434
7  保護操作系統(4)(harib18g)  435
第22天  用C語言編寫應用程序  443
1  保護操作系統(5)(harib19a)  443
2  幫助發現bug(harib19b)  448
3  強制結束應用程序(harib19c)  452
4  用C語言顯示字符串(1)(harib19d)  455
5  用C語言顯示字符串(2)(harib19e)  457
6  顯示窗口(harib19f)  462
7  在窗口中描繪字符和方塊(harib19g)  465
第23天  圖形處理相關  468
1  編寫malloc(harib20a)  468
2  畫點(harib20b)  472
3  刷新窗口(harib20c)  475
4  畫直線(harib20d)  478
5  關閉窗口(harib20e)  483
6  鍵盤輸入API(harib20f)  484
7  用鍵盤輸入來消遣一下(harib20g)  488
8  強制結束并關閉窗口(harib20h)  489
第24天  窗口操作  493
1  窗口切換(1)(harib21a)  493
2  窗口切換(2)(harib21b)  495
3  移動窗口(harib21c)  496
4  用鼠標關閉窗口(harib21d)  498
5  將輸入切換到應用程序窗口(harib21e)  500
6  用鼠標切換輸入窗口(harib21f)  506
7  定時器API(harib21g)  507
8  取消定時器(harib21h)  511
第25天  增加命令行窗口  515
1  蜂鳴器發聲(harib22a)  515
2  增加更多的顏色(1)(harib22b)  518
3  增加更多的顏色(2)(harib22c)  520
4  窗口初始位置(harib22d)  523
5  增加命令行窗口(1)(harib22e)  524
6  增加命令行窗口(2)(harib22f)  528
7  增加命令行窗口(3)(harib22g)  531
8  增加命令行窗口(4)(harib22h)  532
9  變得更像真正的操作系統(1)(harib22i)  534
10  變得更像真正的操作系統(2)(harib22j)  538
第26天  為窗口移動提速  541
1  提高窗口移動速度(1)(harib23a)  541
2  提高窗口移動速度(2)(harib23b)  543
3  提高窗口移動速度(3)(harib23c)  547
4  提高窗口移動速度(4)(harib23d)  549
5  啟動時只打開一個命令行窗口(harib23e)  551
6  增加更多的命令行窗口(harib23f)  554
7  關閉命令行窗口(1)(harib23g)  555
8  關閉命令行窗口(2)(harib23h)  561
9  start命令(harib23i)  563
10  ncst命令(harib23j)  564
第27天  LDT與庫  571
1  先來修復bug(harib24a)  571
2  應用程序運行時關閉命令行窗口(harib24b)  573
3  保護應用程序(1)(harib24c)  577
4  保護應用程序(2)(harib24d)  580
5  優化應用程序的大小(harib24e)  583
6  庫(harib24f)  587
7  整理make環境(harib24g)  590
第28天  文件操作與文字顯示  598
1  alloca(1)(harib25a)  598
2  alloca(2)(harib25b)  601
3  文件操作API(harib25c)  605
4  命令行API(harib25d)  612
5  日文文字顯示(1)(harib25e)  615
6  日文文字顯示(2)(harib25f)  624
7  日文文字顯示(3)(harib25g)  629
第29天  壓縮與簡單的應用程序  635
1  修復bug(harib26a)  635
2  文件壓縮(harib26b)  636
3  標準函數  644
4  非矩形窗口(harib26c)  647
5  bball(harib26d)  648
6  外星人游戲(harib26e)  651
第30天  高級的應用程序  659
1  命令行計算器(harib27a)  659
2  文本閱覽器(harib27b)  664
3  MML播放器(harib27c)  671
4  圖片閱覽器(harib27d)  679
5  IPL的改良(harib27e)  683
6  光盤啟動(harib27f)  688
第31天  寫在開發完成之后  690
1  繼續開發要靠大家的努力  690
2  關于操作系統的大小  692
3  操作系統開發的訣竅  693
4  分享給他人使用  694
5  關于光盤中的軟件  695
6  關于開源的建議  696
7  后記  698
8  畢業典禮  703
9  附錄  704

多任務(1) --挑戰任務切換( harib12a)

  “話說,多任務到底是啥呢?”我們今天的內容,就從這個問題開始吧。

  多任務,在英語中叫做 “multitask”,顧名思義就是“多個任務”的意思。簡單地說,在Windows等操作系統中,多個應用程序同時運行的狀態(也就是同時打開好幾個窗口的狀態)就叫做多任務。

  對于生活在現代社會的各位來說,這種多任務簡直是理所當然的事情。比如你會一邊用音樂播放軟件聽音樂一邊寫郵件,郵件寫到一半忽然有點東西要查,便打開 Web瀏覽器上網搜索。這對于大家來說這些都是家常便飯了吧。可如果沒有多任務的話會怎么樣呢?想寫郵件的時候就必須關掉正在播放的音樂,要查東西的時候就必須先保存寫到一半的郵件,然后才能打開 Web瀏覽器……光想象一下就會覺得太不方便了。

  然而在從前,沒有多任務反倒是普遍的情形(那個時候大家不用電腦聽音樂,也沒有互聯網)。在那個年代,電腦一次只能運行一個程序,如果要同時運行多個程序的話,就得買好幾臺電腦才行。

  就在那個時候,誕生了昀初的多任務操作系統,大家都覺得太了不起了。從現在開始,我們也要準備給“紙娃娃系統”添加執行多任務的能力了。連這樣一個小不點兒操作系統都能夠實現多任務,真是讓人不由地感嘆它生逢其時呀。

  稍稍思考一下我們就會發現,多任務這個東西還真是奇妙,它究竟是怎樣做到讓多個程序同時運行的呢?如果我們的電腦里面裝了好多個 CPU的話,同時運行多個程序倒也順理成章,但實際上就算我們只有一個 CPU,照樣可以實現多任務。

  其實說穿了,這些程序根本沒有在同時運行,只不過看上去好像是在同時運行一樣:程序 A運行一會兒,接下來程序 B運行一會兒,再接下來輪到程序 C,然后再回到程序 A……如此反復,有點像日本忍者的“分身術”呢(笑)。

  為了讓這種分身術看上去更完美,需要讓操作系統盡可能快地切換任務。如果 10秒才切換一次,那就連人眼都能察覺出來了,同時運行多個程序的戲碼也就穿幫了。再有,如果我們給程序 C發出一個按鍵指令,正巧這個瞬間系統切換到了程序 A的話,我們就不得不等上 20秒,才能重新輪到程序 C對按鍵指令作出反應。這實在是讓人抓狂啊(哭)。




  在一般的操作系統中,這個切換的動作每 0.01~0.03秒就會進行一次。當然,切換的速度越快,讓人覺得程序是在同時運行的效果也就越好。不過, CPU進行程序切換(我們稱為“任務切換”)這個動作本身就需要消耗一定的時間,這個時間大約為 0.0001秒左右,不同的 CPU及操作系統所需的時間也有所不同。如果 CPU每0.0002秒切換一次任務的話,該 CPU處理能力的 50%都要被任務切換本身所消耗掉。這意味著,如果同時運行 2個程序,每個程序的速度就只有單獨運行時的1/4,這樣你會覺得開心嗎?如果變成這種結果,那還不如干脆別搞多任務呢。

  相比之下,即便是每 0.001秒切換一次任務,單單在任務切換上面也要消耗 CPU處理能力的 10%。大概有人會想, 10%也沒什么大不了的吧?可如果你看看速度快 10%的CPU賣多少錢,說不定就會恍然大悟,“對啊,只要優化一下任務切換間隔,就相當于一分錢也不花,便換上了比現在更快的 CPU嘛……”(笑),你也就明白了浪費 10%也是很不值得的。正是因為這個原因,任務切換的間隔昀短也得 0.01秒左右,這樣一來只有 1%的處理能力消耗在任務切換上,基本上就可以忽略不計了。

  關于多任務是什么的問題,已經大致講得差不多了,接下來我們來看看如何讓 CPU來處理多任務。

  當你向CPU發出任務切換的指令時, CPU會先把寄存器中的值全部寫入內存中,這樣做是為了當以后切換回這個程序的時候,可以從中斷的地方繼續運行。接下來,為了運行下一個程序, CPU會把所有寄存器中的值從內存中讀取出來(當然,這個讀取的地址和剛剛寫入的地址一定是不同的,不然就相當于什么都沒變嘛),這樣就完成了一次切換。我們前面所說的任務切換所需要的時間,正是對內存進行寫入和讀取操作所消耗的時間。

  接下來我們來看看寄存器中的內容是怎樣寫入內存里去的。下面這個結構叫做“任務狀態段”(task status segment),簡稱TSS。TSS有16位和32位兩個版本,這里我們使用 32位版。顧名思義, TSS也是內存段的一種,需要在 GDT中進行定義后使用。



  參考上面的結構定義,TSS共包含26個int成員,總計 104字節(摘自 CPU的技術資料),我特意把它們分成 4行來寫。從開頭的 backlink起,到 cr3為止的幾個成員,保存的不是寄存器的數據,而是與任務設置相關的信息,在執行任務切換的時候這些成員不會被寫入( backlink除外,某些情況下是會被寫入的)。后面的部分中我們會用到這里的設定,不過現在你完全可以先忽略它。

  第2行的成員是 32位寄存器,第 3行是16位寄存器,應該沒必要解釋了吧……不對, eip好像到現在還沒講過呢。 EIP的全稱是“extended instruction pointer”,也就是“擴展指令指針寄存器”的意思。這里的“擴展”代表它是一個 32位寄存器,也就是說其對應的 16位版本叫做 IP,類比一下的話,跟 EAX與AX之間的關系是一樣的。

  EIP是CPU用來記錄下一條需要執行的指令位于內存中哪個地址的寄存器,因此它才被稱為
“指令指針”。如果沒有這個寄存器,記性不好的 CPU就會忘記自己正在運行哪里的程序,于是程序就沒辦法正常運行了。每執行一條指令, EIP寄存器中的值就會自動累加,從而保證一直指向下一條指令所在的內存地址。

  說點題外話, JMP指令實際上是一個向 EIP寄存器賦值的指令。 JMP 0x1234這種寫法, CPU會解釋為 MOV EIP,0x1234,并向 EIP賦值。也就是說,這條指令其實是篡改了 CPU記憶中下一條該執行的指令的地址,蒙了 CPU一把。這樣一來, CPU在讀取下一條指令時,就會去讀取 0x1234這個地址中的指令。你看,這不就相當于是做了一個跳轉嗎?

  對了,如果你在匯編語言里用 MOV EIP,0x1234這種寫法是會出錯的,還是不要嘗試的好。在匯編語言中,應該使用 JMP 0x1234來代替MOV EIP,0x1234。


  如果在TSS中將EIP寄存器的值記錄下來,那么當下次再返回這個任務的時候, CPU就可以明白應該從哪里讀取程序來運行了。

  按照常識,段寄存器應該是 16位的才對,可是在 TSS數據結構中卻定義成了 int(也就是 DWORD)類型。我們可以大膽想象一下,說不定英特爾公司的人將來會把段寄存器變成 32位的,這樣想想也挺有意思的呢(笑)。

  第4行的ldtr和iomap也和第1行的成員一樣,是有關任務設置的部分,因此在任務切換時不會被CPU寫入。也許你會想,那就和第 1行一樣,暫時先忽略好了——但那可是絕對不行的!如果胡亂賦值的話,任務就無法正常切換了,在這里我們先將ldtr置為0,將iomap置為0x40000000就好了。

  關于TSS的話題暫且先告一段落,我們回來繼續講任務切換的方法。要進行任務切換,其實還得用JMP指令。 JMP指令分為兩種,只改寫 EIP的稱為near模式,同時改寫 EIP和CS的稱為far模式,在此之前我們使用的 JMP指令基本上都是 near模式的。不記得 CS是什么了? CS就是代碼段(code segment)寄存器啦。

  說起來我們其實用過一次 far模式的JMP指令,就在 asmhead.nas的“bootpack啟動”的昀后一句(見8.5節)。 MP DWORD 2*8:0x0000001b 這條指令在向 EIP存入0x1b的同時,將CS置為2*8(=16)。像這樣在 JMP目標地址中帶冒號( :)的,就是far模式的 JMP指令。

  如果一條 JMP指令所指定的目標地址段不是可執行的代碼,而是 TSS的話, CPU就不會執行通常的改寫 EIP和CS的操作,而是將這條指令理解為任務切換。也就是說, CPU會切換到目標 TSS所指定的任務,說白了,就是 JMP到一個任務那里去了。

  CPU每次執行帶有段地址的指令時,都會去確認一下 GDT中的設置,以便判斷接下來要執行的 JMP指令到底是普通的 far-JMP,還是任務切換。也就是說,從匯編程序翻譯出來的機器語言來看,普通的 far-JMP和任務切換的 far-JMP,指令本身是沒有任何區別的。

  好了,枯燥的講解就到這里,讓我們實際做一次任務切換吧。我們準備兩個任務:任務 A和任務B,嘗試從 A切換到B。

  

  現在兩個TSS都創建好了,該進行實際的切換了。

  我們向TR寄存器存入3 * 8這個值,這是因為我們剛才把當前運行的任務定義為 GDT的3號。 TR寄存器以前沒有提到過,它的作用是讓 CPU記住當前正在運行哪一個任務。當進行任務切換的時候,TR寄存器的值也會自動變化,它的名字也就是“ task register”(任務寄存器)的縮寫。我們每次給 TR寄存器賦值的時候,必須把 GDT的編號乘以 8,因為英特爾公司就是這樣規定的。如果你有意見的話,可以打電話找英特爾的大叔投訴哦(笑)。

  給TR寄存器賦值需要使用 LTR指令,不過用 C語言做不到。唉,各位是不是都已經見怪不怪了啊?啥?你早就料到了?(笑)所以說,正如你所料,我們只能把它寫進 naskfunc.nas里面。






  對了,LTR指令的作用只是改變 TR寄存器的值,因此執行了 LTR指令并不會發生任務切換。要進行任務切換,我們必須執行 far模式的跳轉指令,可惜 far跳轉這事 C語言還是無能為力,這種語言還真是不方便啊。沒辦法,這個函數我們也得在 naskfunc.nas里創建。



  也許有人會問,在 JMP指令后面寫個 RET有意義嗎?也對,通常情況下確實沒意義,因為已經跳轉到別的地方了嘛,后面再寫什么指令也不會被執行了。不過,用作任務切換的 JMP指令卻不太一樣,在切換任務之后,再返回這個任務的時候,程序會從這條 JMP指令之后恢復運行,也就是執行JMP后面的RET,從匯編語言函數返回,繼續運行 C語言主程序。

  另外,如果 far-JMP指令是用作任務切換的話,地址段(冒號前面的 4*8的部分)要指向 TSS這一點比較重要,而偏移量(冒號后面的 0的部分)并沒有什么實際作用,會被忽略掉,一般來說像這樣寫 0就可以了。

  現在我們需要在 HariMain的某個地方來調用 taskswitch(),可到底該寫在哪里呢?唔,有了,就放在顯示“ 10[sec]”的語句后面好了。也就是說,程序啟動 10秒以后進行任務切換。



大功告成了?不對,我們還沒準備好 tss_b呢。在任務切換的時候需要讀取 tss_b的內容,因此我們得在TSS中定義好寄存器的初始值才行。




  乍看之下,貌似會有很多看不懂的地方吧,我們從后半段對寄存器賦值的地方開始看。這里我們給cs置為GDT的2號,其他寄存器都置為 GDT的1號,asmhead.nas的時候也是一樣的。也就是說,我們這次使用了和bootpack.c相同的地址段。當然,如果你用別的地址段也沒問題,不過這次我們只是想隨便做個任務切換的實驗而已,這種麻煩的事情還是以后再說吧。

  繼續看剩下的部分,關于 eflags的賦值,如果把 STI后的EFLAGS的值通過 io_load_eflags賦給變量的話,該變量的值就顯示為 0x00000202,因此在這里就直接使用了這個值,僅此而已。如果還有看不懂的地方,大概就是 eip和esp的部分了吧。

。。。。。。

 在eip中,我們需要定義在切換到這個任務的時候,要從哪里開始運行。在這里我們先把 task_b_main這個函數的內存地址賦值給它。



  這個函數只執行了一個 HLT,沒有任何實際作用,后面我們會對它進行各種改造,現在就先這樣吧。

  task_b_esp是專門為任務 B所定義的棧。有人可能會說,直接用任務 A的棧不就好了嗎?那可不行,如果真這么做的話,棧就會混成一團,程序也無法正常運行。



  總之先寫成這個樣子了。我們為任務B的棧分配了64KB的內存,并計算出棧底的內存地址。
請各位回憶一下向棧PUSH數據(入棧)的動作,ESP中存入的應該棧末尾的地址,而不是棧開
頭的地址。

  好了,我們已經講解得夠多了,現在總算是萬事俱備啦,馬上“make run”一下吧。這個程
序如果運行正常的話應該是什么樣子呢?嗯,啟動之后的10秒內,還是跟以前一樣的,10秒一到便執行任務切換,task_b_main開始運行。因為task_b_main只有一句HLT,所以接下來程序就全部停止了,鼠標和鍵盤也應該都沒有反應了。

  唔……這樣看起來好像很無聊啊,算了,總之我們先來“make run”吧。10秒鐘的等待還真
是漫長……哇!停了停了!

  看來我們的首次任務切換獲得了圓滿成功。

總結

以上是生活随笔為你收集整理的《30天自制操作系统》前言、目录、样章欢迎阅读!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。