start16.asm

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· 汇编 代码 · 共 843 行 · 第 1/3 页

ASM
843
字号
;------------------------------------------------------------------------------
;*
;*   Copyright 2006, Intel Corporation                                                         
;*   All rights reserved. This program and the accompanying materials                          
;*   are licensed and made available under the terms and conditions of the BSD License         
;*   which accompanies this distribution.  The full text of the license may be found at        
;*   http://opensource.org/licenses/bsd-license.php                                            
;*                                                                                             
;*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
;*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
;*   
;*    start16.asm
;*  
;*   Abstract:
;*
;------------------------------------------------------------------------------

        .model  small
        .stack
        .486p
        .code

FAT_DIRECTORY_ENTRY_SIZE  EQU     020h
FAT_DIRECTORY_ENTRY_SHIFT EQU     5
BLOCK_SIZE                EQU     0200h
BLOCK_MASK                EQU     01ffh
BLOCK_SHIFT               EQU     9

        org 0h
Ia32Jump:
  jmp   BootSectorEntryPoint  ; JMP inst    - 3 bytes
  nop

OemId             db  "INTEL   "    ; OemId               - 8 bytes
SectorSize        dw  0200h         ; Sector Size         - 16 bits
SectorsPerCluster db  08h           ; Sector Per Cluster  - 8 bits
ReservedSectors   dw  08h           ; Reserved Sectors    - 16 bits
NoFats            db  02h           ; Number of FATs      - 8 bits
RootEntries       dw  0200h         ; Root Entries        - 16 bits
Sectors           dw  0000h         ; Number of Sectors   - 16 bits
Media             db  0f8h          ; Media               - 8 bits  - ignored
SectorsPerFat     dw  00f8h         ; Sectors Per FAT     - 16 bits
SectorsPerTrack   dw  003fh         ; Sectors Per Track   - 16 bits - ignored
Heads             dw  00ffh         ; Heads               - 16 bits - ignored
HiddenSectors     dd  0000h         ; Hidden Sectors      - 32 bits - ignored
LargeSectors      dd  0007bc00h     ; Large Sectors       - 32 bits 
PhysicalDrive     db  00h           ; PhysicalDriveNumber - 8 bits  - ignored
CurrentHead       db  00h           ; Current Head        - 8 bits
Signature         db  29h           ; Signature           - 8 bits  - ignored
Id                db  "    "        ; Id                  - 4 bytes
FatLabel          db  "EFI FAT16  " ; Label               - 11 bytes
SystemId          db  "FAT16   "    ; SystemId            - 8 bytes

BootSectorEntryPoint:
        ASSUME  ds:@code
        ASSUME  ss:@code

; si      = NumberOfClusters
; cx      = ClusterNumber
; dx      = CachedFatSectorNumber
; ds:0000 = CacheFatSectorBuffer
; es:di   = Buffer to load file
; bx      = NextClusterNumber

        mov     si,0                                ; NumberOfClusters = 0 - Special case for first cluster
        xor     di,di                               ; di = 0
        mov     dx,0fffh                            ; CachedFatSectorNumber = 0xfff
        push    cx                                  ; Push StartCluster onto stack
FatChainLoop:
        mov     ax,cx                               ; ax = ClusterNumber    
        and     ax,0fff8h                           ; ax = ax & 0xfff8
        cmp     ax,0fff8h                           ; See if this is the last cluster
        je      FoundLastCluster                    ; Jump if last cluster found
        mov     ax,cx                               ; ax = ClusterNumber
        shl     ax,1                                ; FatOffset = ClusterNumber * 2
        push    si                                  ; Save si
        mov     si,ax                               ; si = FatOffset
        shr     ax,BLOCK_SHIFT                      ; ax = FatOffset >> BLOCK_SHIFT
        add     ax,word ptr [bp+ReservedSectors]    ; ax = FatSectorNumber = ReservedSectors + (FatOffset >> BLOCK_OFFSET)
        and     si,BLOCK_MASK                       ; si = FatOffset & BLOCK_MASK
        cmp     ax,dx                               ; Compare FatSectorNumber to CachedFatSectorNumber
        je      SkipFatRead
        mov     bx,2                                
        push    es
        push    ds
        pop     es
        call    ReadBlocks                          ; Read 2 blocks starting at AX storing at ES:DI
        pop     es
        mov     dx,ax                               ; CachedFatSectorNumber = FatSectorNumber
SkipFatRead:
        mov     bx,word ptr [si]                    ; bx = NextClusterNumber
        mov     ax,cx                               ; ax = ClusterNumber
        pop     si                                  ; Restore si

        cmp     si,0
        jne     NotFirstCluster
        mov     cx,bx
        pop     bx
        push    cx
        inc     si
        jmp     FatChainLoop
NotFirstCluster:

        dec     bx                                  ; bx = NextClusterNumber - 1
        cmp     bx,cx                               ; See if (NextClusterNumber-1)==ClusterNumber
        jne     ReadClusters
        inc     bx                                  ; bx = NextClusterNumber
        inc     si                                  ; NumberOfClusters++
        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
        jmp     FatChainLoop
ReadClusters:
        inc     bx
        pop     ax                                  ; ax = StartCluster
        push    bx                                  ; StartCluster = NextClusterNumber
        mov     cx,bx                               ; ClusterNumber = NextClusterNumber
        sub     ax,2                                ; ax = StartCluster - 2
        xor     bh,bh                               
        mov     bl,byte ptr [bp+SectorsPerCluster]  ; bx = SectorsPerCluster
        mul     bx                                  ; ax = (StartCluster - 2) * SectorsPerCluster
        add     ax, word ptr [bp]                   ; ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
        push    ax                                  ; save start sector
        mov     ax,si                               ; ax = NumberOfClusters
        mul     bx                                  ; ax = NumberOfClusters * SectorsPerCluster
        mov     bx,ax                               ; bx = Number of Sectors
        pop     ax                                  ; ax = Start Sector
        call    ReadBlocks
        mov     si,1                                ; NumberOfClusters = 1
        jmp     FatChainLoop
FoundLastCluster:
        mov     ax,cs
        mov     word ptr cs:[JumpSegment],ax
JumpFarInstruction:
        db      0eah
JumpOffset:
        dw      0200h
JumpSegment:
        dw      2000h

; ****************************************************************************
; ReadBlocks - Reads a set of blocks from a block device
;
; AX    = Start LBA
; BX    = Number of Blocks to Read
; ES:DI = Buffer to store sectors read from disk
; ****************************************************************************

; cx = Blocks
; bx = NumberOfBlocks
; si = StartLBA

ReadBlocks:
        pusha
        add     eax,dword ptr [bp+LBAOffsetForBootSector]    ; Add LBAOffsetForBootSector to Start LBA
        add     eax,dword ptr [bp+HiddenSectors]    ; Add HiddenSectors to Start LBA
        mov     esi,eax                             ; esi = Start LBA
        mov     cx,bx                               ; cx = Number of blocks to read
ReadCylinderLoop:
        mov     bp,07bfch                           ; bp = 0x7bfc
        mov     eax,esi                             ; eax = Start LBA
        xor     dx,dx                               ; dx = 0
        movzx   ebx,word ptr [bp]                   ; bx = MaxSector
        div     ebx                                 ; ax = StartLBA / MaxSector
        inc     dx                                  ; dx = (StartLBA % MaxSector) + 1

        sub     bx,dx                               ; bx = MaxSector - Sector
        inc     bx                                  ; bx = MaxSector - Sector + 1
        cmp     cx,bx                               ; Compare (Blocks) to (MaxSector - Sector + 1)
        jg      LimitTransfer
        mov     bx,cx                               ; bx = Blocks
LimitTransfer:
        push    ax                                  ; save ax
        mov     ax,es                               ; ax = es
        shr     ax,(BLOCK_SHIFT-4)                  ; ax = Number of blocks into mem system
        and     ax,07fh                             ; ax = Number of blocks into current seg
        add     ax,bx                               ; ax = End Block number of transfer
        cmp     ax,080h                             ; See if it crosses a 64K boundry
        jle     NotCrossing64KBoundry               ; Branch if not crossing 64K boundry
        sub     ax,080h                             ; ax = Number of blocks past 64K boundry
        sub     bx,ax                               ; Decrease transfer size by block overage
NotCrossing64KBoundry:
        pop     ax                                  ; restore ax

        push    cx
        mov     cl,dl                               ; cl = (StartLBA % MaxSector) + 1 = Sector
        xor     dx,dx                               ; dx = 0
        div     word ptr [bp+2]                     ; ax = ax / (MaxHead + 1) = Cylinder  
                                                    ; dx = ax % (MaxHead + 1) = Head

        push    bx                                  ; Save number of blocks to transfer
        mov     dh,dl                               ; dh = Head
        mov     bp,07c00h                           ; bp = 0x7c00
        mov     dl,byte ptr [bp+PhysicalDrive]      ; dl = Drive Number
        mov     ch,al                               ; ch = Cylinder
        mov     al,bl                               ; al = Blocks
        mov     ah,2                                ; ah = Function 2
        mov     bx,di                               ; es:bx = Buffer address
        int     013h
        jc      DiskError
        pop     bx
        pop     cx
        movzx   ebx,bx
        add     esi,ebx                             ; StartLBA = StartLBA + NumberOfBlocks
        sub     cx,bx                               ; Blocks = Blocks - NumberOfBlocks
        mov     ax,es
        shl     bx,(BLOCK_SHIFT-4)
        add     ax,bx
        mov     es,ax                               ; es:di = es:di + NumberOfBlocks*BLOCK_SIZE
        cmp     cx,0
        jne     ReadCylinderLoop
        popa
        ret

DiskError:
        mov  ax,0b800h
        mov  es,ax
        mov  ax, 2000h
        mov  ds, ax
        lea  si, cs:[ErrorString]
        mov  cx, 11
        mov  di, 160
        rep  movsw 
Halt:
        jmp   Halt
ErrorString:
        db 'U', 0ch, 'O', 0ch, 'L', 0ch, ' ', 0ch, 'E', 0ch, 'r', 0ch, 'r', 0ch, 'o', 0ch, 'r', 0ch, '2', 0ch, '!', 0ch
        org     01fah
LBAOffsetForBootSector:
        dd      0h

        org     01feh
        dw      0aa55h

;******************************************************************************
;******************************************************************************
;******************************************************************************

DELAY_PORT           equ     0edh    ; Port to use for 1uS delay
KBD_CONTROL_PORT     equ     060h    ; 8042 control port     
KBD_STATUS_PORT      equ     064h    ; 8042 status port      
WRITE_DATA_PORT_CMD  equ     0d1h    ; 8042 command to write the data port
ENABLE_A20_CMD       equ     0dfh    ; 8042 command to enable A20

        org     200h
start:  
        mov ax,cs
        mov ds,ax
        mov es,ax
        mov ss,ax
        mov sp,MyStack

        mov ax,0b800h
        mov es,ax
        mov byte ptr es:[160],'a'
        mov ax,cs
        mov es,ax

        mov ebx,0
        lea edi,MemoryMap
MemMapLoop:
        mov eax,0e820h
        mov ecx,20
        mov edx,'SMAP'
        int 15h
        jc  MemMapDone
        add edi,20
        cmp ebx,0
        je  MemMapDone
        jmp MemMapLoop
MemMapDone:
        lea eax,MemoryMap
        sub edi,eax                         ; Get the address of the memory map
        mov dword ptr [MemoryMapSize],edi   ; Save the size of the memory map

        xor     ebx,ebx
        mov     bx,cs                       ; BX=segment
        shl     ebx,4                       ; BX="linear" address of segment base
        lea     eax,[GDT_BASE + ebx]        ; EAX=PHYSICAL address of gdt
        mov     dword ptr [gdtr + 2],eax    ; Put address of gdt into the gdtr
        lea     eax,[IDT_BASE + ebx]        ; EAX=PHYSICAL address of idt
        mov     dword ptr [idtr + 2],eax    ; Put address of idt into the idtr
        lea     edx,[MemoryMapSize + ebx]   ; Physical base address of the memory map

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?