引導(dǎo)啟動(dòng)程序之bootsect.s

1. P52,47~56

start :
    mov ax, #BOOTSEG             
    mov ds, ax
    mov ax, #INITSEG
    mov es, ax
    mov cx, #256
    sub si, si
    sub di, di
    rep               !  重復(fù)執(zhí)行它的下一條語(yǔ)句movw,直到cx中的數(shù)值為0。這里是循環(huán)執(zhí)行256次
    movw              !  以字節(jié)為單位,從源地址往目的地址搬移數(shù)據(jù),si、di自增
    jmpi go,INITSEG   !  jmpi--段間跳轉(zhuǎn)指令,CS = INITSEG,IP = go,即跳轉(zhuǎn)到INITSEG:go處執(zhí)行

標(biāo)志寄存器EFlags

方向標(biāo)志DF(Direction Flag),用于決定執(zhí)行完一次串操作之后,變址寄存器ESI/EDI是加還是減

  • DF=0,自加
  • DF=1,自減

串操作

  • 取串(LODS),存串(STOS)、移串(MOVS)
  • 可以按照字節(jié)(B)、字(W)、雙字(D)進(jìn)行數(shù)據(jù)處理,

2. P53,62

扇區(qū)

一個(gè)扇區(qū)是512byte,setup 程序大約為 4 個(gè)扇區(qū)

段地址+偏移地址

  • x86處理器地址總線是20位,而內(nèi)部數(shù)據(jù)總線、寄存器都是16位的。
  • 如何用16位寄存器表示20位?物理地址=段地址 << 4 + 偏移地址
  • eg
    ss = 0x9000,sp=0xff00,那么sp指向的地址是0x90000 + 0xff00 = 0x9ff00

3. P53,67

INT 0x13 磁盤服務(wù)程序
  • 功能號(hào)0x00, 復(fù)位驅(qū)動(dòng)器

    AH = 0X00,DL = 需要復(fù)位的驅(qū)動(dòng)器號(hào)。

  • 功能號(hào)0x02, 讀磁盤扇區(qū)到內(nèi)存

    AH = 0x02,AL = 需要讀出的扇區(qū)數(shù)量;
    CH = 磁道(柱面)號(hào)的低 8 位; CL = 開始扇區(qū)(0-5 位),磁道號(hào)高 2 位(6-7);
    DH = 磁頭號(hào); DL = 驅(qū)動(dòng)器號(hào)(如果是硬盤則位 7 要置位);
    es:bx 指向數(shù)據(jù)緩沖區(qū); 如果讀取失敗則 CF 標(biāo)志置位

    返回信息

    傳輸成功:CF=0,AH=00H,AL=傳輸?shù)纳葏^(qū)數(shù)
    傳輸失敗:CF=1,AH=狀態(tài)代碼(見下表)

01H — 非法命令 02H — 地址目標(biāo)未發(fā)現(xiàn) 03H — 磁盤寫保護(hù)(軟盤) 05H — 復(fù)位失敗(硬盤)
06H — 軟盤取出(軟盤) 07H — 錯(cuò)誤的參數(shù)表(硬盤) 08H — DMA越界(軟盤) 09H — DMA超過(guò)64K界限
0AH — 錯(cuò)誤的扇區(qū)標(biāo)志(硬盤) 0BH — 錯(cuò)誤的磁道標(biāo)志(硬盤) 0CH — 介質(zhì)類型未發(fā)現(xiàn)(軟盤) 0DH — 格式化時(shí)非法扇區(qū)號(hào)(硬盤)
0EH — 控制數(shù)據(jù)地址目標(biāo)被發(fā)現(xiàn)(硬盤) 0FH — DMA仲裁越界(硬盤) 10H — 不正確的CRC或ECC編碼 11H — ECC校正數(shù)據(jù)錯(cuò)(硬盤)
20H — 控制器失敗 40H — 查找失敗 80H — 磁盤超時(shí)(未響應(yīng)) AAH — 驅(qū)動(dòng)器未準(zhǔn)備好(硬盤)
BBH — 未定義的錯(cuò)誤(硬盤) CCH — 寫錯(cuò)誤(硬盤) E0H — 狀態(tài)寄存器錯(cuò)(硬盤) FFH — 檢測(cè)操作失敗(硬盤)
  • 功能號(hào)0x08,讀取磁盤驅(qū)動(dòng)器參數(shù)
    AH = 0x08,DL = 驅(qū)動(dòng)器號(hào)(如果是硬盤則要置位 7 為 1)
    返回信息

    如果出錯(cuò)則 CF 置位,并且 AH = 狀態(tài)碼。
    AH = 0, AL = 0
    BL = 驅(qū)動(dòng)器類型(AT/PS2)
    CH = 最大磁道號(hào)的低 8 位,CL = 每磁道最大扇區(qū)數(shù)(位 0-5),最大磁道號(hào)高 2 位(位 6-7)
    DH = 最大磁頭數(shù),DL = 驅(qū)動(dòng)器數(shù)量
    es:di 軟驅(qū)磁盤參數(shù)表

4. P54,92~102

INT 0x10

CSDN

由 BIOS 對(duì)屏幕及顯示器所提供的服務(wù)程序

    ! Print some inane message
    mov ah, #0x03       ! read cursor pos,AH=0x03,讀取光標(biāo),為了獲取光標(biāo)當(dāng)前的行列
    xor bh, bh           !bh = 頁(yè)號(hào)
    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

讀取光標(biāo)是必要的,為了獲取光標(biāo)位置(DH、DL)

  • AH=3,讀光標(biāo)位置

    BH = 頁(yè)號(hào)
    CH = 光標(biāo)開始行
    CL = 光標(biāo)結(jié)束行
    DH = 行
    DL = 列

  • AH=13,表示顯示字符串

    ES:BP = 串地址
    CX = 串長(zhǎng)度
    DH, DL = 起始行列
    BH = 頁(yè)號(hào)
    BL = 07H,正常的黑底白字

P55,151~155

read_it:
    mov ax, es
    test ax, #0x0fff
die:    jne die         ! es must be at 64kB boundary
    xor bx, bx         ! bx is starting address within segment

test指令

  • test的解釋( Intel技術(shù)手冊(cè))

TEMP ← SRC1 AND SRC2 ;
  SF ← MSB(TEMP) ;
IF TEMP = 0
  THEN ZF ← 1 ;
  ELSE ZF ← 0 ;
  FI:
  PF ← BitwiseXNOR(TEMP[0:7]);
  CF ← 0 ;
  OF ← 0 ;

  • 對(duì)代碼的解釋
    • test是進(jìn)行位與操作,相與等于0,說(shuō)明ax=es=0x1000,ZF=1
    • JNE/JNZ都是ZF標(biāo)志位為0時(shí)跳轉(zhuǎn),如果es在64kb處,則順序執(zhí)行;否則,死鎖

子程序151~218

實(shí)現(xiàn)功能

該子程序?qū)⑾到y(tǒng)模塊加載到內(nèi)存地址 0x10000 處,并確定沒有跨越 64KB 的內(nèi)存邊界。我們?cè)噲D盡快 地進(jìn)行加載,只要可能,就每次加載整條磁道的數(shù)據(jù)

執(zhí)行流程

  • read_it

    • 檢測(cè)讀入的數(shù)據(jù)是否在內(nèi)存地址64kB處
    • 是,則執(zhí)行rp_read;否,則死鎖
  • rp_read

    • 首先判斷是否已經(jīng)讀完
    • 是,返回調(diào)用處;否,執(zhí)行ok1_read
  • ok1_read

    • 取當(dāng)前磁道的扇區(qū)數(shù),計(jì)算是否超過(guò)64kB
    • 是,計(jì)算能讀取的最大值;否,執(zhí)行ok2_read
  • ok2_read

    • 執(zhí)行讀取操作(跳轉(zhuǎn)到了read_track)
    • 傳輸?shù)纳葏^(qū)數(shù)存儲(chǔ)在AL中,判斷是否已經(jīng)讀完當(dāng)前磁道的所有扇區(qū)
    • 是,順序執(zhí)行,如果當(dāng)前磁道是0,則磁道號(hào)+1,執(zhí)行ok4_read;如果磁道號(hào)是1,則直接跳轉(zhuǎn)到ok4_read;否,執(zhí)行ok3_read
  • ok3_read

    • 計(jì)算當(dāng)前已讀扇區(qū)數(shù)量,將讀取位置存儲(chǔ)在bx中
    • 跳轉(zhuǎn)到rp_read,繼續(xù)讀取
  • ok4_read

    • 保存磁道號(hào),清空ax
    • 如果未讀完,進(jìn)入ok3_read;否則,調(diào)整基址跳轉(zhuǎn)到rp_read
  • read_track

    • 對(duì)通用 寄存器壓棧保護(hù)
    • 設(shè)置要讀取的驅(qū)動(dòng)器號(hào)、磁道號(hào)、扇區(qū),然后調(diào)用INT 0x13軟件中斷
    • 調(diào)用正確,返回調(diào)用處;否則,執(zhí)行bad_rt,驅(qū)動(dòng)器復(fù)位,然后重新跳轉(zhuǎn)執(zhí)行read_track
  • kill_motor

    關(guān)閉軟驅(qū)的馬達(dá),這樣我們進(jìn)入內(nèi)核后它處于已知狀態(tài),以后也就無(wú)須擔(dān)心它了

子程序執(zhí)行流圖

8086寄存器

數(shù)據(jù)寄存器

  • AX (Accumulator):累加寄存器,也稱之為累加器;
  • BX (Base):基地址寄存器;
  • CX (Count):計(jì)數(shù)器寄存器;
  • DX (Data):數(shù)據(jù)寄存器;

指針寄存器

  • SP (Stack Pointer):堆棧指針寄存器;
  • BP (Base Pointer):基指針寄存器;

變址寄存器

  • SI (Source Index):源變址寄存器
  • DI (Destination Index):目的變址寄存器;

控制寄存器

  • IP (Instruction Pointer):指令指針寄存器;
  • FLAG:標(biāo)志寄存器;

段寄存器:

  • CS (Code Segment):代碼段寄存器;
  • DS (Data Segment):數(shù)據(jù)段寄存器;
  • SS (Stack Segment):堆棧段寄存器;
  • ES (Extra Segment):附加段寄存器
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容