ITPub博客

首页 > 应用开发 > Java > x86架构冷启动代码示例

x86架构冷启动代码示例

原创 Java 作者:src33 时间:2025-10-25 13:29:16 0 删除 编辑
;============================================
; CPU冷启动代码 - 从复位向量开始
; 文件名:boot.asm
; 描述:x86架构CPU冷启动引导代码
;============================================
[BITS 16]                    ; 16位实模式
[ORG 0x7C00]                 ; BIOS加载引导扇区到0x7C00
;============================================
; 引导扇区签名
;============================================
boot_start:
    jmp short main           ; 跳过BPB区域
    nop
;============================================
; BIOS参数块 (BPB) - FAT12文件系统
;============================================
bpb_oem:                    db "BOOT    "
bpb_bytes_per_sector:       dw 512
bpb_sectors_per_cluster:    db 1
bpb_reserved_sectors:       dw 1
bpb_number_of_fats:         db 2
bpb_root_entries:           dw 224
bpb_total_sectors:          dw 2880
bpb_media:                  db 0xF0
bpb_sectors_per_fat:        dw 9
bpb_sectors_per_track:      dw 18
bpb_heads_per_cylinder:     dw 2
bpb_hidden_sectors:         dd 0
bpb_total_sectors_big:      dd 0
bpb_drive_number:           db 0
bpb_unchanged:              db 0
bpb_ext_boot_signature:     db 0x29
bpb_serial_number:          dd 0x12345678
bpb_volume_label:           db "BOOT VOLUME"
bpb_file_system:            db "FAT12   "
;============================================
; 主引导代码
;============================================
main:
    ; 设置段寄存器
    cli                     ; 关中断
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00          ; 设置栈指针
    sti                     ; 开中断
    ; 保存启动驱动器号
    mov [boot_drive], dl
    ; 显示启动消息
    mov si, msg_booting
    call print_string
    ; 检测内存
    call detect_memory
    ; 加载第二阶段引导程序
    call load_stage2
    ; 跳转到保护模式
    jmp switch_to_protected_mode
;============================================
; 字符串打印函数
;============================================
print_string:
    pusha
    mov ah, 0x0E            ; BIOS teletype功能
.print_loop:
    lodsb                   ; 加载字符到AL
    cmp al, 0               ; 检查字符串结束
    je .print_done
    int 0x10                ; 调用BIOS视频服务
    jmp .print_loop
.print_done:
    popa
    ret
;============================================
; 内存检测函数
;============================================
detect_memory:
    pusha
    mov ax, 0
    mov es, ax
    mov di, memory_map      ; 内存映射缓冲区
    
    mov edx, 0x534D4150     ; 'SMAP'签名
    xor ebx, ebx            ; EBX=0表示开始
    
.memory_loop:
    mov eax, 0xE820         ; 功能号
    mov ecx, 24             ; 缓冲区大小
    mov [es:di + 20], dword 1 ; 强制有效的ACPI 3.X条目
    int 0x15                ; 调用BIOS内存检测
    
    jc .memory_done         ; 出错则结束
    cmp eax, 0x534D4150     ; 检查签名
    jne .memory_done
    
    add di, 24              ; 移动到下一个条目
    inc dword [memory_entries]
    
    cmp ebx, 0              ; EBX=0表示结束
    jne .memory_loop
.memory_done:
    popa
    ret
;============================================
; 加载第二阶段引导程序
;============================================
load_stage2:
    pusha
    
    ; 重置磁盘系统
    mov ah, 0
    mov dl, [boot_drive]
    int 0x13
    
    ; 读取扇区
    mov ax, 0x07E0          ; 加载到0x7E00 (紧接引导扇区之后)
    mov es, ax
    xor bx, bx
    
    mov ah, 0x02            ; 读扇区功能
    mov al, 4               ; 读取4个扇区
    mov ch, 0               ; 柱面0
    mov cl, 2               ; 从扇区2开始
    mov dh, 0               ; 磁头0
    mov dl, [boot_drive]    ; 驱动器号
    int 0x13
    
    jc disk_error           ; 读取失败
    
    popa
    ret
;============================================
; 切换到保护模式
;============================================
switch_to_protected_mode:
    cli                     ; 关中断
    
    ; 加载GDT
    lgdt [gdt_descriptor]
    
    ; 开启A20线
    call enable_a20
    
    ; 设置保护模式位
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax
    
    ; 远跳转到32位代码段
    jmp CODE_SEG:init_protected_mode
;============================================
; 开启A20地址线
;============================================
enable_a20:
    ; 方法1: 使用键盘控制器
    call .a20_wait
    mov al, 0xAD
    out 0x64, al
    
    call .a20_wait
    mov al, 0xD0
    out 0x64, al
    
    call .a20_wait2
    in al, 0x60
    push eax
    
    call .a20_wait
    mov al, 0xD1
    out 0x64, al
    
    call .a20_wait
    pop eax
    or al, 2
    out 0x60, al
    
    call .a20_wait
    mov al, 0xAE
    out 0x64, al
    
    call .a20_wait
    ret
.a20_wait:
    in al, 0x64
    test al, 2
    jnz .a20_wait
    ret
.a20_wait2:
    in al, 0x64
    test al, 1
    jz .a20_wait2
    ret
;============================================
; 32位保护模式初始化
;============================================
[BITS 32]
init_protected_mode:
    ; 设置段寄存器
    mov ax, DATA_SEG
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    mov esp, 0x90000        ; 设置32位栈指针
    
    ; 调用第二阶段引导程序
    call 0x7E00
    
    ; 如果返回,则挂起系统
    cli
    hlt
;============================================
; 错误处理
;============================================
disk_error:
    mov si, msg_disk_error
    call print_string
    jmp $
;============================================
; GDT (全局描述符表)
;============================================
gdt_start:
    ; 空描述符
    dq 0x0000000000000000
    ; 代码段描述符 (基址=0, 限制=4GB)
gdt_code:
    dw 0xFFFF               ; 限制 (0-15)
    dw 0x0000               ; 基址 (0-15)
    db 0x00                 ; 基址 (16-23)
    db 10011010b            ; 访问字节 (代码段,可执行,可读)
    db 11001111b            ; 标志 + 限制 (16-19)
    db 0x00                 ; 基址 (24-31)
    ; 数据段描述符 (基址=0, 限制=4GB)
gdt_data:
    dw 0xFFFF               ; 限制 (0-15)
    dw 0x0000               ; 基址 (0-15)
    db 0x00                 ; 基址 (16-23)
    db 10010010b            ; 访问字节 (数据段,可读写)
    db 11001111b            ; 标志 + 限制 (16-19)
    db 0x00                 ; 基址 (24-31)
gdt_end:
; GDT描述符
gdt_descriptor:
    dw gdt_end - gdt_start - 1  ; GDT大小
    dd gdt_start                ; GDT地址
; 段选择子
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
;============================================
; 数据区
;============================================
boot_drive:         db 0
memory_entries:     dd 0
memory_map:         times 256 db 0
msg_booting:        db "Booting OS...", 0x0D, 0x0A, 0
msg_disk_error:     db "Disk read error!", 0x0D, 0x0A, 0
;============================================
; 引导扇区填充和签名
;============================================
times 510-($-$$) db 0       ; 填充到510字节
dw 0xAA55                   ; 引导扇区签名
;============================================
; 第二阶段引导程序
;============================================
stage2_start:
    ; 这里可以添加更复杂的初始化代码
    ; 比如设置分页、加载内核等
    mov eax, 0xDEADBEEF     ; 测试值
    ret

ARM架构冷启动代码示例

https://book.qq.com/book-search/%E3%80%90%E8%96%873777750%E3%80%91%E4%BD%A4%E9%82%A6%E5%AD%9F%E6%B3%A2%E6%96%B0%E7%9B%9B%E5%8E%85%E7%99%BB%E5%BD%95%E7%BD%91%E5%9D%80

https://book.qq.com/book-search/%E3%80%90%E8%96%873777750%E3%80%91%E4%BD%A4%E9%82%A6%E5%AD%9F%E6%B3%A2%E6%96%B0%E7%9B%9B%E5%8E%85%E5%90%8E%E5%8F%B0%E7%BD%91%E5%9D%80


assembly复制代码

/* ARM Cortex-A冷启动代码 */
.section .text.boot
.globl _start
_start:
    /* 异常向量表 */
    b   reset_handler        /* 复位向量 */
    b   undefined_handler    /* 未定义指令 */
    b   svc_handler         /* SVC调用 */
    b   prefetch_handler    /* 预取中止 */
    b   data_abort_handler  /* 数据中止 */
    b   .                   /* 保留 */
    b   irq_handler         /* IRQ中断 */
    b   fiq_handler         /* FIQ中断 */
reset_handler:
    /* 关闭中断 */
    cpsid if
    
    /* 设置栈指针 */
    ldr sp, =stack_top
    
    /* 清零BSS段 */
    ldr r0, =_bss_start
    ldr r1, =_bss_end
    mov r2, #0
clear_bss:
    cmp r0, r1
    strlt r2, [r0], #4
    blt clear_bss
    
    /* 初始化系统时钟 */
    bl init_clock
    
    /* 初始化内存控制器 */
    bl init_memory
    
    /* 设置MMU */
    bl setup_mmu
    
    /* 跳转到C代码 */
    bl main
    
    /* 如果返回则挂起 */
    b .
/* 时钟初始化 */
init_clock:
    /* 设置PLL和时钟分频器 */
    ldr r0, =0x10000000     /* 时钟控制器基址 */
    
    /* 配置系统PLL */
    ldr r1, =0x00010020     /* PLL配置值 */
    str r1, [r0, #0x00]
    
    /* 等待PLL锁定 */
1:  ldr r1, [r0, #0x04]
    tst r1, #0x01
    beq 1b
    
    /* 设置时钟分频 */
    ldr r1, =0x00000101     /* 分频配置 */
    str r1, [r0, #0x08]
    
    bx lr
/* 内存控制器初始化 */
init_memory:
    /* 配置DRAM控制器 */
    ldr r0, =0x20000000     /* DRAM控制器基址 */
    
    /* 设置时序参数 */
    ldr r1, =0x12345678     /* 时序配置 */
    str r1, [r0, #0x00]
    
    /* 设置内存大小和地址映射 */
    ldr r1, =0x87654321     /* 内存配置 */
    str r1, [r0, #0x04]
    
    bx lr
/* 其他异常处理程序 */
undefined_handler:
    b .
svc_handler:
    b .
/* 中断处理程序 */
irq_handler:
    /* 保存上下文 */
    push {r0-r12, lr}
    
    /* 调用C中断处理程序 */
    bl handle_irq
    
    /* 恢复上下文 */
    pop {r0-r12, lr}
    subs pc, lr, #4
/* BSS段 */
.section .bss
.align 4
stack_bottom:
    .space 4096             /* 4KB栈空间 */
stack_top:

编译和构建脚本

http://www.chiyunwang.com/hangye/73.html

http://www.sdjmwj.com/?hangye/156.html

makefile复制代码

# Makefile for bootloader
AS = nasm
CC = gcc
LD = ld
CFLAGS = -m32 -nostdlib -nostartfiles -nodefaultlibs -fno-builtin
LDFLAGS = -m elf_i386 -T linker.ld
SOURCES = boot.asm stage2.c
OBJECTS = boot.o stage2.o
all: boot.bin
boot.bin: $(OBJECTS)
	$(AS) -f bin boot.asm -o boot.bin
stage2.o: stage2.c
	$(CC) $(CFLAGS) -c stage2.c -o stage2.o
clean:
	rm -f *.o *.bin
.PHONY: all clean

链接器脚本

http://www.gqf5.cn/?shangban/58.html

http://www.nrrox.com/?industry/73.html

ld复制代码

/* linker.ld - 引导加载程序链接器脚本 */
OUTPUT_FORMAT("binary")
ENTRY(_start)
SECTIONS
{
    . = 0x7C00;
    
    .text : {
        *(.text)
    }
    
    .data : {
        *(.data)
    }
    
    .bss : {
        _bss_start = .;
        *(.bss)
        _bss_end = .;
    }
}

这个冷启动代码包含了:

  1. 复位向量处理 - CPU上电后的第一条指令
  2. 硬件初始化 - 时钟、内存控制器、中断控制器
  3. 模式切换 - 从实模式到保护模式
  4. 内存管理 - GDT/MMU设置
  5. 异常处理 - 中断和异常向量表
  6. 引导流程 - 加载操作系统内核

实际使用时需要根据具体的CPU架构和硬件平台进行调整。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048206/viewspace-3098612/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2025-10-25

  • 博文量
    4
  • 访问量
    2318