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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

babyos (三)——利用BIOS INT 0x13读取软盘

發布時間:2025/6/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 babyos (三)——利用BIOS INT 0x13读取软盘 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

注:以下程序為原創,若發現任何BUG,歡迎指正;若有問題,歡迎交流;權利歸原作者所有,若轉載,請注明出處;若能有益于一二訪客,幸甚。

昨天學習了VGA顯示的一些東西,今天準備學習一下讀取軟盤的知識。


1.babyos將使用的引導過程

1)系統上電或reset時,處理器執行一些初始化,CPU處于實模式
2)處理器會執行一個位于已知位置處的代碼,PC中這個位置位于BIOS,它保存在主板上的閃存中
3)控制權交給BIOS后,它尋找一個可引導的設備(軟盤、硬盤等),BIOS讀取引導扇區(512字節)到內存0x7c00處,并跳轉到該地址執行
4)引導扇區中存放的指令可以使用BIOS中斷,它將會讀取軟盤中內核部分到一個臨時地址(如0x10000,不覆蓋0x7c00處的boot代碼即可)
5)將內核前512字節(load.s, 它主要負責將內核剩余部分拷貝到load.s后面)移動到0x0處,將GDT拷貝到0x80000處。為什么不一次全部將內核放到0x0處呢?因為內核可能較大,會覆蓋掉0x7c00處的代碼。
6)開啟A20總線,置位CR0的bit 0,開啟保護模式,加載GDT到GDTR,跳轉到GDT第二項(第一項為空GDT),即load.s處執行
7)load.s將內核剩余部分移動到load.s后面,即0x200開始的地址處。然后執行初始化代碼。
8)初始化代碼,至此系統啟動成功。

所以首當其沖的問題就是如何讀軟盤。

2.軟盤的結構

3.5寸1.44M 軟盤,如圖floppy_struct.png 所示,有兩個磁頭,正反兩面各一個;80個磁道(即80個圓圈);每個磁道有18個扇區;每個扇區為512字節。
容量 = 512字節/扇區 * 2面 * 80磁道(柱面)/面 * 18扇區/磁道 = 1440 KB

磁頭,即面:編號[0, 1]
80個磁道,即柱面(圓圈):編號[0, 79]
18個扇區:編號[1, 18]

相對扇區號[0, 2879]:
相對扇區號按照柱面排序,即從最外頭的圓圈到最里頭的圓圈。
0柱面正面(即磁頭號為0)的1-18扇區為0-17號相對扇區,0柱面反面(即磁頭號為2)的1-18扇區為18-35號相對扇區,然后是1柱面,2柱面,直到79柱面。如下:
[cpp] view plaincopyprint?
  • 0柱面,0磁頭,1扇區?????????0??
  • 0柱面,0磁頭,2扇區?????????1??
  • ……??
  • 0柱面,0磁頭,18扇區????????17??
  • 0柱面,1磁頭,1扇區?????????18??
  • ……??
  • 0柱面,1磁頭,18扇區????????35??
  • 1柱面,0磁頭,1扇區?????????36??
  • ……??
  • 1柱面,0磁頭,18扇區????????53??
  • 1柱面,1磁頭,1扇區?????????54??
  • ……??
  • 1柱面,1磁頭,18扇區????????71??
  • 2柱面,0磁頭,1扇區?????????72??
  • ……??

  • 3.利用BIOS 中斷讀取軟盤

    [cpp] view plaincopyprint?
  • -------------------------------------------------------------------??
  • ????????????????????INT?0x13,功能02??
  • -----------------------------------------------------------??
  • 參數:??
  • ????AH??????02??
  • ????AL??????讀取扇區數??
  • ????CH??????柱面[0,?79]??
  • ????CL??????扇區[1,?18]??
  • ????DH??????磁頭[0,?1]??
  • ????DL??????驅動器(0x0?~?0x7f表示軟盤,0x80?~?0xff表示硬盤)??
  • ????ES:BX???緩沖區地址,即數據讀到這里??
  • 返回值:??
  • ????CF?=?0表示操作成功,此時AH=0,AL=傳輸的扇區數??
  • ????CF?=?1即carry位置位(可用JC表示跳轉)表示操作失敗,AH=狀態代碼??
  • --------------------------------------------------------------------??
  • 4.相對扇區號的計算

    1)知道柱面號,磁頭號,扇區號計算相對扇區號
    由上面可知0號柱面包含了相對扇區號[0,35],1號柱面包含相對扇區號[36,71],依次類推。
    設相對扇區號為N,則
    柱面號CH = N / 36;
    令x = N % 36;
    則x范圍為[0,35],其中[0,17] 為磁頭號0, [18,35]為磁頭號1.
    則磁頭號DH = x / 18;
    零y = x % 18; y范圍[0, 17]
    則扇區號CL = y + 1。

    2)知道相對扇區號,計算柱面號、磁頭號、扇區號
    N = 36*CH + 18*DH + CL;
    由此式子,也可計算:
    CH = N / 36
    DH = (N % 36) / 18
    CL = (N % 36) % 18 + 1

    5.讀取一個扇區

    實驗:將一些數據寫入軟盤的第二個扇區(第一個扇區是引導扇區),然后用BIOS 中斷讀取該扇區的數據,并顯示在屏幕上。然后看讀取的數據是否與寫入的數據相同。注:第二個扇區相對扇區號為1.
    [cpp] view plaincopyprint?
  • 寫數據的C代碼:??
  • /*************************************************************************?
  • ????>?File:??????write_data.c?
  • ????>?Author:????孤舟釣客?
  • ????>?Mail:??????guzhoudiaoke@126.com??
  • ????>?Time:??????2012年12月26日?星期三?01時20分26秒?
  • ?************************************************************************/??
  • ??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • ??
  • int?main()??
  • {??
  • ????FILE?*fp;??
  • ????fp?=?fopen("./data",?"wb");??
  • ??????
  • ????int?i;??
  • ????char?*str?=?"baby?os,?guzhoudiaoke@126.com?";??
  • ????int?len?=?strlen(str);??
  • ??????
  • ????for?(i?=?0;?i?<?len;?i++)??
  • ????????fprintf(fp,?"%c",?str[i]);??
  • ??
  • ????for?(i?=?512-len;?i?>?0;?i--)??
  • ????????fprintf(fp,?"%c",?i?%?26?+?'A');??
  • ??
  • ????return?0;??
  • }??
  • ??
  • 匯編代碼:??
  • #?This?program?draws?color?pixels?at?mode?0x13??
  • #?2012-12-26?01:31??
  • #?guzhoudiaoke@126.com??
  • ??
  • .include?"boot.inc"??
  • ??
  • .section?.text??
  • .global?_start??
  • .code16??
  • ??
  • _start:??
  • ????jmp?????main??
  • ??
  • #--------------------------------------------------------------??
  • #?清屏函數:??
  • #???設置屏幕背景色,調色板的索引0指代的顏色為背景色??
  • clear_screen:???????????????#?清屏函數??
  • ????movb????$0x06,??%ah?????#?功能號0x06??
  • ????movb????$0,?????%al?????#?上卷全部行,即清屏??
  • ????movb????$0,?????%ch?????#?左上角行??
  • ????movb????$0,?????%ch?????#?左上角列????
  • ????movb????$24,????%dh?????#?右下角行??
  • ????movb????$79,????%dl?????#?右下角列??
  • ????movb????$0x07,??%bh?????#?空白區域屬性??
  • ????int?????$0x10??
  • ????ret??
  • ??
  • #---------------------------------------------------------------??
  • #?直接寫顯存顯示一些文字函數:??
  • #???調用前需要設置DS:SI為源地址,DI為顯示位置,??
  • #???CX?為顯示的字符個數,?AL為顏色屬性??
  • draw_some_text:??
  • ????#?ES:DI?is?the?dst?address,?DS:SI?is?the?src?address??
  • ????movw????$VIDEO_SEG_TEXT,????%bx??
  • ????movw????%bx,????????????????%es??
  • ??????
  • copy_a_char:??
  • ????movsb??
  • ????stosb??
  • ????loop????copy_a_char??
  • ????ret??
  • ??
  • #----------------------------------------------------------------??
  • #?讀取軟盤第二個扇區:??
  • #???使用BIOS?INT?0x13中斷,使用前需要設置ES:BX作為緩沖區??
  • read_one_sect:??
  • ????movb????$0x02,??%ah?????#?功能號??
  • ????movb????$0x01,??%al?????#?讀取扇區數??
  • ????movb????$0x00,??%ch?????#?柱面號??
  • ????movb????$0x02,??%cl?????#?扇區號??
  • ????movb????$0x00,??%dh?????#?磁頭號??
  • ????movb????$0x00,??%dl?????#?驅動器號??
  • ??
  • re_read:????????????????????#?若調用失敗則重新調用??
  • ????int?????$0x13??
  • ????jc??????re_read?????????#?若進位位(CF)被置位,表示調用失敗??
  • ??????
  • ????ret??
  • ??
  • main:??
  • ????movw????%cx,????%ax??
  • ????movw????%ax,????%ds??
  • ????movw????%ax,????%es??
  • ??
  • ????call????clear_screen????????#?清屏??
  • ??
  • ????movw????$0,?????????%ax??
  • ????movw????%ax,????????%ds??
  • ????leaw????msg_str,????%si??
  • ????xorw????%di,????????%di??
  • ????movw????msg_len,????%cx??
  • ????movb????$TEXT_COLOR,%al??
  • ????call????draw_some_text??????#?繪制字符串??
  • ??
  • ????movw????$BUFFER_SEG,%ax???????
  • ????movw????%ax,????????%es?????#?ES:BX?為緩沖區地址??
  • ????xorw????%bx,????????%bx??
  • ????call????read_one_sect??
  • ??
  • ????#?下面調用繪制函數,在屏幕上顯示讀取的信息??
  • ????movw????$BUFFER_SEG,%ax??
  • ????movw????%ax,????????%ds?????#?ds:si?為源地址??
  • ????xorw????%si,????????%si??
  • ????movw????$160,???????%di?????#?第一行已經打印了msg_str,從第二行開始顯示??
  • ????movw????$512,???????%cx?????#?顯示512個字符??
  • ????movb????$0x01,??????%al??
  • ????call????draw_some_text??
  • ??
  • 1:??
  • ????jmp?????1b??
  • ??
  • msg_str:??
  • ????.asciz??"The?data?of?the?second?sect?of?the?floppy?(sect?1):"??
  • msg_len:??
  • ????.int????.?-?msg_str?-?1??
  • ??
  • ????.org????0x1fe,??0x90??
  • ????.word???0xaa55??
  • 實驗結果:



    6.讀取任意扇區(給定相對扇區號)

    實驗,寫用C語言寫入文件,該文件包含512個‘a’,512個1……512個‘z’, 循環50次,將該文件寫入軟盤(相對扇區號1~50*26),然后讀取給定的相對扇區號的扇區,將讀取的內容打印到屏幕上。并與寫入的數據比較,驗證讀取的正確性。

    [cpp] view plaincopyprint?
  • C代碼用于寫文件:??
  • /*************************************************************************?
  • ????>?File:??????write_data.c?
  • ????>?Author:????孤舟釣客?
  • ????>?Mail:??????guzhoudiaoke@126.com??
  • ????>?Time:??????2012年12月26日?星期三?20時16分45秒?
  • ?************************************************************************/??
  • ??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • ??
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ????if?(argc?!=?2)??
  • ????{??
  • ????????printf("usage:?./write_data?file_name");??
  • ????????exit(0);??
  • ????}??
  • ??
  • ????FILE?*fp;??
  • ????fp?=?fopen(argv[1],?"wb");??
  • ??????
  • ????int?i,?j,?k;??
  • ??
  • ????for?(i?=?0;?i?<?50;?i++)??
  • ????{??
  • ????????for?(j?=?'a';?j?<=?'z';?j++)??
  • ????????{??
  • ????????????for?(k?=?0;?k?<?512;?k++)??
  • ????????????{??
  • ????????????????fprintf(fp,?"%c",?(char)j);??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????return?0;??
  • }??
  • ??
  • 匯編代碼:??
  • #?This?program?draws?color?pixels?at?mode?0x13??
  • #?2012-12-26?20:23:42??
  • #?guzhoudiaoke@126.com??
  • ??
  • .include?"boot.inc"??
  • ??
  • .section?.text??
  • .global?_start??
  • .code16??
  • ??
  • _start:??
  • ????jmp?????main??
  • ??
  • #--------------------------------------------------------------??
  • #?清屏函數:??
  • #???設置屏幕背景色,調色板的索引0指代的顏色為背景色??
  • clear_screen:???????????????#?清屏函數??
  • ????movb????$0x06,??%ah?????#?功能號0x06??
  • ????movb????$0,?????%al?????#?上卷全部行,即清屏??
  • ????movb????$0,?????%ch?????#?左上角行??
  • ????movb????$0,?????%ch?????#?左上角列????
  • ????movb????$24,????%dh?????#?右下角行??
  • ????movb????$79,????%dl?????#?右下角列??
  • ????movb????$0x07,??%bh?????#?空白區域屬性??
  • ????int?????$0x10??
  • ??????
  • ????ret??
  • ??
  • #---------------------------------------------------------------??
  • #?直接寫顯存顯示一些文字函數:??
  • #???調用前需要設置DS:SI為源地址,DI為在屏幕上的顯示位置,??
  • #???CX?為顯示的字符個數,?AL為顏色屬性??
  • draw_some_text:??
  • ????#?ES:DI?is?the?dst?address,?DS:SI?is?the?src?address??
  • ????movw????$VIDEO_SEG_TEXT,????%bx??
  • ????movw????%bx,????????????????%es??
  • ??????
  • copy_a_char:??
  • ????movsb??
  • ????stosb??
  • ????loop????copy_a_char??
  • ??
  • ????ret??
  • ??
  • #----------------------------------------------------------------??
  • #?讀取軟盤一個扇區:??
  • #???使用BIOS?INT?0x13中斷,使用前需要設置ES:BX作為緩沖區??
  • #???AX為相對扇區號??
  • read_one_sect:??
  • ????movb????$36,????%dl??
  • ????divb????%dl??
  • ????movb????%al,????%ch?????#?柱面號=N?/?36,?假設x?=?N?%?36??
  • ??????
  • ????movb????%ah,????%al?????#?AL?=?N?%?36??
  • ????movb????$0,?????%ah?????#?AX?=?N?%?36??
  • ????movb????$18,????%dl??
  • ????divb????%dl??
  • ????movb????%al,????%dh?????#?磁頭號DH?=?x?/?18??
  • ????movb????%ah,????%cl???????
  • ????incb????%cl?????????????#?扇區號CL?=?x?%?18?+?1??
  • ??
  • ????movb????$0x00,??%dl?????#?驅動器號DL??
  • ??
  • ????movb????$0x02,??%ah?????#?功能號??
  • ????movb????$0x01,??%al?????#?讀取扇區數??
  • ??
  • re_read:????????????????????#?若調用失敗則重新調用??
  • ????int?????$0x13??
  • ????jc??????re_read?????????#?若進位位(CF)被置位,表示調用失敗??
  • ??????
  • ????ret??
  • ??
  • #-------------------------------------------------------------------??
  • #?該函數讀取指定的若干扇區號??
  • #???需要指定ES:BX作為緩沖區??
  • read_sects:??
  • ????movw????$0x00,??????????%si?????#?已經讀取的扇區數??
  • ????leaw????sect_no,????????%di??
  • 1:????
  • ????movw????(%di),??????????%ax?????#?獲取相對扇區號??
  • ????addw????$2,?????????????%di??
  • ??????
  • ????call????read_one_sect??
  • ??????
  • ??
  • ????incw????%si??
  • ????incw????%bx??
  • ????cmpw????num_to_read,????%si??
  • ????jne?????1b??
  • ??
  • ????ret??
  • ??
  • main:??
  • ????movw????%cx,????%ax??
  • ????movw????%ax,????%ds??
  • ????movw????%ax,????%es??
  • ??
  • ????call????clear_screen????????#?清屏??
  • ??
  • ????#?顯示提示信息??
  • ????movw????$0,?????????%ax??
  • ????movw????%ax,????????%ds??
  • ????leaw????msg_str,????%si??
  • ????xorw????%di,????????%di??
  • ????movw????msg_len,????%cx??
  • ????movb????$TEXT_COLOR,%al??
  • ????call????draw_some_text??????#?繪制字符串??
  • ??
  • ????#?讀取軟盤??
  • ????movw????$BUFFER_SEG,????????%ax???????
  • ????movw????%ax,????????????????%es?????#?ES:BX?為緩沖區地址??
  • ????xorw????%bx,????????????????%bx??
  • ????call????read_sects??
  • ??????
  • #?在屏幕上顯示讀取的信息??
  • #???movw????$BUFFER_SEG,%ax??
  • #???movw????%ax,????????%ds?????#?ds:si?為源地址??
  • #???movw????$0,?????????%si??
  • #???movw????$320,???????%di?????#?第一行已經打印了msg_str,從第二行開始顯示??
  • #???movw????$512,???????%cx?????#?顯示字符數??
  • #???movb????$0x01,??????%al??
  • #???call????draw_some_text??
  • ??????
  • ????#?將緩沖區中前data_len個字節拷貝到data_save??
  • ????xorw????%ax,????????%ax??
  • ????movw????%ax,????????%ds??
  • ????movw????num_to_read,%cx??
  • ??????
  • ????movw????$BUFFER_SEG,%ax??
  • ????movw????%ax,????????%ds??
  • ????xorw????%ax,????????%ax??
  • ????movw????%ax,????????%es??
  • ????movw????$0,?????????%si??
  • ????movw????$data_save,?%di??
  • ??
  • ????cld??
  • ????rep?????movsb??
  • ??
  • ????#?下面調用繪制函數,在屏幕上顯示讀取的信息??
  • ????xorw????%ax,????????%ax??
  • ????movw????%ax,????????%ds?????#?ds:si?為源地址??
  • ????leaw????data_save,??%si??
  • ????movw????$160,???????%di?????#?第一行已經打印了msg_str,從第二行開始顯示??
  • ????movw????num_to_read,%cx?????#?顯示字符數??
  • ????movb????$0x01,??????%al??
  • ????call????draw_some_text??
  • ??
  • 1:??
  • ????jmp?????1b??
  • ??
  • msg_str:??
  • ????.asciz??"The?data?read?from?floppy:"??
  • msg_len:??
  • ????.short??.?-?msg_str?-?1??
  • ??
  • sect_no:??
  • ????#?下面的扇區數據為:"babyosguzhoudiaoke"??
  • ????#?sect:?2+26*1,?????1+26*2,?????2+26*3,?????25+26*4,????15+26*5,????19+26*6,??????
  • ????#???????7+26*11,????21+26*12,???26+26*13,???8+26*14,????15+26*15,???21+26*16,??
  • ????#???????4+26*31,????9+26*32,????1+26*33,????15+26*34,???11+26*35,???5+26*36??
  • ????.short??28,?????????53,?????????80,?????????129,????????145,????????175???
  • ????.short??293,????????333,????????364,????????372,????????379,????????411??
  • ????.short??810,????????841,????????859,????????899,????????921,????????941??
  • num_to_read:??
  • ????.short??18??
  • ??
  • data_save:??
  • ????.asciz??"XXXXXXXXXXXXXXXXXX"??
  • ??????
  • ????.org????0x1fe,??0x90??
  • ????.word???0xaa55??



  • [cpp] view plaincopyprint?
  • <pre></pre>??
  • <pre></pre>??
  • ????
  • 總結

    以上是生活随笔為你收集整理的babyos (三)——利用BIOS INT 0x13读取软盘的全部內容,希望文章能夠幫你解決所遇到的問題。

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