首页 > 应用开发 > Java > x86架构冷启动代码示例
;============================================ ; 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
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 = .;
}
}这个冷启动代码包含了:
实际使用时需要根据具体的CPU架构和硬件平台进行调整。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048206/viewspace-3098612/ ,如需转载,请注明出处,否则将追究法律责任。