2010-01-14 132 views
9

我写了简单的第一阶段启动加载程序,它使用中断向BIOS显示“Hello world”。现在作为编写第二阶段的下一个显而易见的步骤,但是代码应该存在以及如何从第一阶段加载它?如何从第一阶段加载第二阶段启动加载器?

下面是第一阶段的程序

[BITS 16] ;Tells the assembler that its a 16 bit code 
[ORG 0x7C00] ;Origin, tell the assembler that where the code will 
       ;be in memory after it is been loaded 

MOV SI, HelloString ;Store string pointer to SI 
CALL PrintString ;Call print string procedure 
JMP $  ;Infinite loop, hang it here. 


PrintCharacter: ;Procedure to print character on screen 
    ;Assume that ASCII value is in register AL 
MOV AH, 0x0E ;Tell BIOS that we need to print one charater on screen. 
MOV BH, 0x00 ;Page no. 
MOV BL, 0x07 ;Text attribute 0x07 is lightgrey font on black background 

INT 0x10 ;Call video interrupt 
RET  ;Return to calling procedure 



PrintString: ;Procedure to print string on screen 
    ;Assume that string starting pointer is in register SI 

next_character: ;Lable to fetch next character from string 
MOV AL, [SI] ;Get a byte from string and store in AL register 
INC SI  ;Increment SI pointer 
OR AL, AL ;Check if value in AL is zero (end of string) 
JZ exit_function ;If end then return 
CALL PrintCharacter ;Else print the character which is in AL register 
JMP next_character ;Fetch next character from string 
exit_function: ;End label 
RET  ;Return from procedure 


;Data 
HelloString db 'Hello World', 0 ;HelloWorld string ending with 0 

TIMES 510 - ($ - $$) db 0 ;Fill the rest of sector with 0 
DW 0xAA55   ;Add boot signature at the end of bootloader 
+0

你是用C语言?任何其他您可以分享的重要信息? – 2010-01-14 15:53:22

+0

,我们一直使用第一架组件的x86指令,但我们r打算写第二阶段在更高层次语言如C ..我在哪里存储第二阶段二进制以及如何从第一阶段的引导加载程序加载[加载内核的 – Xinus 2010-01-14 16:15:23

+0

可能的复制从组件(NASM)(http://stackoverflow.com/questions/1551240/loading-kernel-from-assembly-nasm) – 2015-10-28 18:14:36

回答

6

在x86上,你会做以下(简化):

  • 有引导程序加载磁盘/软盘的第n个部门(无论你从哪里启动)到内存中并执行它(即加载段/偏移量,并执行retf)。一个更好的选择是在文件系统中搜索某个文件名(例如KERNEL.BIN) - 但是你需要知道文件系统类型(例如,如果你是从软盘映像进行测试,则为FAT12)。
  • 内核然后会以实模式启动。它设置代码描述符,GDT等等,激活32位寻址(您应该听说过“A20”)并最终进入保护模式。然后你需要远程跳转到一个32位的代码段(内核文件必须以32位代码处于绝对位置的方式连接在一起,例如在偏移512处,紧跟在16位实模式之后) 。
  • 然后,32位内核程序集仅定义了EXTERN _mykernel并调用该符号。
  • 然后,你可以开始编写你的内核作为C函数mykernel

好吧,这是我几年前做的一个简短的概述(有很多从互联网复制&粘贴;)。如果这是没有帮助的,下面是OS开发一些好的网络资源:

希望帮助^^

+1

感谢第一个链接 – Xinus 2010-01-17 17:12:58

1

看看这里的GRUB实现(阶段1):

http://src.illumos.org/source/xref/illumos-gate/usr/src/grub/grub-0.97/stage1/stage1.S

首先注意到起始点为0x7c00,结束签名为0xaa55,这是第一个扇区。从拆解中,U可以看到这一点:

349 copy_buffer: 
350 movw ABS(stage2_segment), %es 
351 
352 /* 
353 * We need to save %cx and %si because the startup code in 
354 * stage2 uses them without initializing them. 
355 */ 
356 pusha 
357 pushw %ds 
358 
359 movw $0x100, %cx 
360 movw %bx, %ds 
361 xorw %si, %si 
362 xorw %di, %di 
363 
364 cld 
365 
366 rep 
367 movsw 
368 
369 popw %ds 
370 popa 
371 
372 /* boot stage2 */ 
373 jmp *(stage2_address) 
374 
375 /* END OF MAIN LOOP */ 
376 

本质的逻辑是第2阶段代码复制到内存的另一部分,并且跳跃后,直接出现,那就是“启动阶段2 ”。换句话说,“启动阶段1”在将扇区加载到内存后从BIOS中有效触发,而阶段2则是您跳到那里的地方 - 它可以在任何地方。

+0

如何汇编知道,所有的代码标签从装磁盘现在可以通过加载到RAM中的任何位置来抵消? – 2015-05-17 21:21:54

3

加载阶段2并跳转到它

use16 
org 0x7C00 

    ; You should do further initializations here 
    ; like setup the stack and segment registers. 

    ; Load stage 2 to memory. 
    mov ah, 0x02 
    ; Number of sectors to read. 
    mov al, 1 
    ; This may not be necessary as many BIOS set it up as an initial state. 
    mov dl, 0x80 
    ; Cylinder number. 
    mov ch, 0 
    ; Head number. 
    mov dh, 0 
    ; Starting sector number. 2 because 1 was already loaded. 
    mov cl, 2 
    ; Where to load to. 
    mov bx, stage2 
    int 0x13 

    jmp stage2 

    ; Magic bytes.  
    times ((0x200 - 2) - ($ - $$)) db 0x00 
    dw 0xAA55 

stage2: 

    ; Print 'a'. 
    mov ax, 0x0E61 
    int 0x10 

    cli 
    hlt 

    ; Pad image to multiple of 512 bytes. 
    times ((0x400) - ($ - $$)) db 0x00 

编译并执行最少的可运行NASM BIOS例如:

nasm -f bin -o main.img main.asm 
qemu-system-i386 main.img 

预期结果:a被打印在屏幕上,然后将程序暂停。

测试在Ubuntu 14.04。

使用接头脚本和更正确的初始化(段寄存器,栈)on my GitHub理智GAS例子。

+0

如果有人可以猜测为什么downvote,请这样做,我可以学习和改进信息。我从不报复。 – 2015-10-05 11:54:35

+0

啊,我正在浏览'bootloader'标签活动列表,我看到我们再次见面。我会做的一个观察是,我可能会把这个问题的范围过宽。虽然您提供了一个解决方案,但您声称OP将在MBR之后从下一个扇区加载。尽管这是一个解决方案,但我认为upvoted在讨论其他想法时更接近标准,例如为文件系统进行文件查找。这个答案假设了很多东西 - 是否有包含第二阶段的文件系统?它是什么文件系统?等... – 2015-10-05 19:34:37

+0

@MichaelPetch嘿再次:-)同意这是一个很好的答案。只是我通常喜欢先运行一些东西,看看它的美丽程度,然后让它更容易理解以后的更深层次的部分。 – 2015-10-05 19:44:06