⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.asm

📁 一个用于学习的操作系统
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;文件名: setup.asm;说明:   获取硬件信息,加载内核到0x10000处,进行分段,;        移动内核到0x100000处,进行分页,跳转到start_kernel中;作者:   marsinfan;日期:   2005/12/29;---------------------------------------------------------------------------; 常量定义;---------------------------------------------------------------------------REAL_KERNEL_SEG         EQU 0x1000      ; kernel加载到的段地址REAL_KERNEL_OFFSET      EQU 0x0000      ; kernel加载到的段内偏移量SETUP_SEG               EQU 0x9000      ; setup的段地址SETUP_OFFSET            EQU 0x0000      ; setup加载到的段内偏移量SECTOR_SPER_TRACK       EQU 18          ; 1.44M软盘的扇区数BYTE_SPERSECTOR         EQU 512         ; 每扇区字节数LOAD_ADDR               EQU 0x7C00      ; 引导程序地址  NEW_LOAD_ADDR           EQU 0x0600      ; 移动后的引导程序地址  PARAM_ADDR              EQU 0x0500      ; 硬件参数存放的地址    GDT_SEG                 EQU 0x0000      ; gdt的段地址GDT_0FFSET              EQU 0x0800      ; gdt的段内偏移量PAGE_SIZE               EQU 0x1000      ; 页表大小PAGE_DIR                EQU 0x10000     ; 页目录地址PAGE_0_ADDR             EQU 0x11000     ; 第一个页表地址PAGE_1_ADDR             EQU 0x12000     ; 第二个页表地址PAGE_2_ADDR             EQU 0x13000     ; 第三个页表地址PAGE_3_ADDR             EQU 0x14000     ; 第四个页表地址;ADDRS_PAGE              EQU 0x400      ; 每页表所容纳的地址数PAGE_OFFSET             EQU 0xC0000000  ; 进行分页后,内核所在的虚拟地址SMAP                    EQU 0x534d4150E820MAX	                EQU 128		    ; number of entries in E820MAPE820NR                  EQU PARAM_ADDR + 46[BITS 16][ORG 0x90000]    mov    ax, SETUP_SEG    mov    ds, ax    mov    es, ax    mov    si, boot_msg    call   print_msg        mov    ax, 0x0000;     mov    ds, ax    mov    es, ax        ; 读取光标的坐标        mov    ah, 0x03    ;    xor    bh, bh    int    0x10        ; save it in known place, con_init fetches    mov    [PARAM_ADDR + 0], dx        ; 光标的位置存放到PARAM_ADDR处    ; 取得物理内存大小 (1M以上的扩展内存, KB)    mov    ah, 0x88    int    0x15;;探测内存是否小于16M,如果小于,则提示并死机    cmp    ax, 0x3C00    jae    next    mov    ax, SETUP_SEG    mov    ds, ax      mov    si, mem_too_small             ;         call   print_msg                     ;     jmp    $    next:        add    ax, 1024;    shr    ax, 2                          ; 换成4k个数    shr    ax, 10                         ; 换成所需页目录项数    ;mov    [PARAM_ADDR + 2], ax           ; 16M的页目录项数存放到PARAM_ADDR + 2处    mov    ax, 4    mov    [PARAM_ADDR + 2], ax           ; 16M的页目录项数存放到PARAM_ADDR + 2处; 取得video-card显示模式    mov    ah, 0x0f    int    0x10    mov    [PARAM_ADDR + 4], bx        ; bh = display page    mov    [PARAM_ADDR + 6], ax        ; al = video mode, ah = window width    ; 取得EGA/VGA配置参数    mov    ah, 0x12    mov    bl, 0x10    int    0x10    mov    [PARAM_ADDR + 8], ax    mov    [PARAM_ADDR + 10], bx    mov    [PARAM_ADDR + 12], cx    ;复制硬盘信息    lds    si, [4 * 0x41];    mov    di, PARAM_ADDR + 14    mov    cx, 0x10;    cld    rep    movsb;INT 15 E820 - newer BIOSes - GET SYSTEM MEMORY MAP;Inp.:;	AX = E820h;	EAX = 0000E820h;	EDX = 534D4150h ('SMAP');	EBX = continuation value or 00000000h to start at beginning of map;	ECX = size of buffer for result, in bytes (should be >= 20 bytes);	ES:DI -> buffer for result (see #00560);Return: CF clear if successful;	    EAX = 534D4150h ('SMAP');	    ES:DI buffer filled;	    EBX = next offset from which to copy or 00000000h if all done;;    ECX = actual length returned in bytes;	CF set on error;	    AH = error code (86h) (see #00475 at INT 15/AH=80h);Notes:	originally introduced with the Phoenix BIOS v4.0, this function is;	  now supported by most newer BIOSes, since various versions of Windows;	  call it to find out about the system memory;	a maximum of 20 bytes will be transferred at one time, even if ECX is;	  higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the;	  value of ECX on entry, and always copy 20 bytes;;some BIOSes expect the high word of EAX to be clear on entry, i.e.;	  EAX=0000E820h;	if this function is not supported, an application should fall back;	  to AX=E802h, AX=E801h, and then AH=88h;	the BIOS is permitted to return a nonzero continuation value in EBX;	  and indicate that the end of the list has already been reached by;	  returning with CF set on the next iteration;	this function will return base memory and ISA/PCI memory contiguous;	  with base memory as normal memory ranges; it will indicate;;  chipset-defined address holes which are not in use and motherboard;	  memory-mapped devices, and all occurrences of the system BIOS as;	  reserved; standard PC address ranges will not be reported;SeeAlso: AH=C7h,AX=E801h"Phoenix",AX=E881h,MEM xxxxh:xxx0h"ACPI";;Format of Phoenix BIOS system memory map address range descriptor:;Offset	Size	Description	(Table 00559); 00h	QWORD	base address; 08h	QWORD	length in bytes; 10h	DWORD	type of address range (see #00560);;(Table 00560);Values for System Memory Map address type:; 01h	memory, available to OS; 02h	reserved, not available (e.g. system ROM, memory-mapped device); 03h	ACPI Reclaim Memory (usable by OS after reading ACPI tables); 04h	ACPI NVS Memory (OS is required to save this memory between NVS;	  sessions); other	not defined yet -- treat as Reserved;    mov ax, 0x0000    mov ds, ax    mov es, ax        mov	    byte [E820NR], 0        ; E820 map数量清零    jmp     meme820; bail820:                            ; 获取meme820失败,死机    mov    ax, SETUP_SEG    mov    ds, ax      mov    si, get_mem_size_err_msg ;         call   print_msg                ;     jmp    $          meme820:	xor     ebx, ebx			    ; continuation value or 00000000h to start at beginning of map	                                    ; Copied from Ralf Brown's Interrupt List	mov     di, PARAM_ADDR + 48     ; 获取内存信息存放的地址jmpe820:	mov	    eax, 0x0000e820		    ; 必须为 e820	mov	    edx, SMAP			    ; 必须为'SMAP'	mov	    ecx, 20			        ; e820结构的大小	int	    0x15				    ; 调用 0x15中断	jc	    bail820				    ; 如果失败,则提示后死机	cmp	    eax, SMAP			    ; 检查调用返回值是否是`SMAP'	jne	    bail820				    ; 不是则表示调用失败,提示死机good820:	mov	    al, byte [E820NR]		; 检查获取的E820 map数量,	cmp	    al, E820MAX             ; 如果超过128,说明有错误	jae	    bail820	inc	    byte [E820NR]           ; E820 map数量加一	mov	    ax, di	add	    ax, 20                  ; 指向一下个存放E820map地址	mov	    di, axagain820:	cmp	    ebx, 0			        ; 检测ebx	jne	    jmpe820				    ; 如果不等于0表示后面还有内存需要检测	    call cls                        ; 清屏     mov ax, SETUP_SEG    mov ds, ax    mov es, ax       mov ah, 2               mov dx, 0                            ; 光标的位置 0,0    mov bh, 0                            ; video page 0    int 10h                              ; 设置cursor到 0,0    mov si, boot_msg                     ;         call print_msg                       ; 显示"Starting Fairy Sky...",;开始加载内核load_kernel:        mov ax, REAL_KERNEL_SEG              ; 0x1000    mov es, ax    xor bx, bx                           ;     mov cx, 0x0004                       ; ch = 磁道号, cl = 扇区号    mov dx, 0x0000                       ; dh = 磁头号, dl = 驱动器号    mov ax, 1000                          ;        mov [kernel_sectors], ax             ; 设置待读取的扇区数    call read_kernel_to_memory           ; 从chs:002读取内核到0x1000处    ;对8259重新编程    mov   al,   0x11        ; initialization sequence    out   0x20, al          ; send it to 8259A-1    dw    0x00eb, 0x00eb    ; jmp $+2, jmp $+2    out   0xA0, al          ; and to 8259A-2    dw    0x00eb, 0x00eb    mov   al,   0x20        ; start of hardware int's (0x20)    out   0x21, al    dw    0x00eb, 0x00eb    mov   al,   0x28        ; start of hardware int's 2 (0x28)    out   0xA1, al    dw    0x00eb, 0x00eb    mov   al,   0x04        ; 8259-1 is master    out   0x21, al    dw    0x00eb, 0x00eb    mov   al,   0x02        ; 8259-2 is slave    out   0xA1, al    dw    0x00eb, 0x00eb    mov   al,   0x01        ; 8086 mode for both    out   0x21, al    dw    0x00eb,0x00eb    out   0xA1, al    dw    0x00eb, 0x00eb    mov   al,0xFF           ; mask off all interrupts for now    out   0xA1, al    dw    0x00eb, 0x00eb    mov   al,   0xFB        ; mask all irq's but irq2 which    out   0x21, al          ; is cascaded            ; 如果运行到这里代表已经完成内核的加载pre_goto_pm:        call cls                            ; 清屏                mov dx, 0x3f2        mov al, 0x0c    out dx, al                          ; 停止软驱    ;准备开始进入保护模式    cli                                 ; 关中断    push es    mov ax, GDT_SEG    mov es, ax                          ;     mov di, GDT_0FFSET    mov si, gdt_table    mov cx, gdt_end - gdt_table    rep movsb                           ; 把gdt_table移动到0x0000:0x0800处    pop es            lgdt [tmpgdtr]                         ; 加载GDT         mov eax, cr0            or al, 0x01               mov cr0, eax                        ; 进入保护模式    ;打开A20,这样可以访问高1M的内存    in al, 0x92    or al, 2    out 0x92, al                jmp dword KERNEL_CS: go_pm           ; 跳到32位code中 ;---------------------------------------------------------------------------;工具函数定义    ;---------------------------------;打印字符串; print_msg: 利用BIOS中断(int 10h)进行写屏 ; 参数: si:字符串的首地址, 字符串以结尾

⌨️ 快捷键说明

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