The bootstrap can be considered as the first code to run after the PC is powered on. It is a 16-bit code that runs in real mode with a length of 512 bytes. In fact, after the machine is started, it will first run 0xffff0 (or 0xfffffff0 in some documents, I am not familiar with BIOS:-() BIOS code in ROM, and then jump to 0x07c00 to execute the boot program.
1. First, a complete sample code is provided. This Code only describes the execution process of the Bootstrap program. It does not have the function of loading the actual operating system, but simply prints a piece of information on the screen.
#define BOOTSEG 0x07C0 .code16 .section ".bstext", "ax" .global bootsect_start bootsect_start: # Normalize the start address ljmp $BOOTSEG, $start2 start2: movw %cs, %ax movw %ax, %ds movw %ax, %es movw %ax, %ss xorw %sp, %sp sti cld movw $bugger_off_msg, %si msg_loop: lodsb andb %al, %al jz bs_die movb $0xe, %ah movw $7, %bx int $0x10 jmp msg_loop bs_die: # Allow the user to press a key, then reboot xorw %ax, %ax int $0x16 int $0x19 # int 0x19 should never return. In case it does anyway, # invoke the BIOS reset code... ljmp $0xf000,$0xfff0 bugger_off_msg: .ascii "Hello Boot!\r\n" .ascii "by harvey\r\n" .ascii "\n" .byte 0 .org 510 .word 0xAA55
Note the following code:
1). the code16 directive instructs the assembler to compile this code segment into 16-bit code.
2) In the ljmp $ bootseg, $ start2 command, bootseg is defined as 0x07c0, and assume that the offset of start2 in the code segment is S. We know that the actual mode address mode is: Segment Base Address * 16 + offset. After this ljmp command is executed, the control will jump to 0x7c00 + S. Because the entire boot code will be loaded at 0x7c00 before, so the control "exactly" jumps to the code at start2.
3) The pseudo command. org 510 at the end of the Code sets the location counter to 510, And the 0xaa55 followed by it is set to 511,512 bytes. 0xaa55 is a flag for the BIOS to identify and load the boot program.
2. Compile and link this program
1) Use the as command to assemble and generate the target file.
As-maid-O boot. O boot. s
2) use the LD command link to generate an executable file.
LD-O boot. O-tboot. LD
Boot. LD is a link script with the following content:
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")OUTPUT_ARCH(i386)ENTRY(bootsect_start)SECTIONS{ . = 0; .boot : {*(.bstext)} . = ASSERT(. <= 512, "Boot too big!");}
This script instructs LD to copy the. Text Segment link in the target file boot. o to the. Boot segment in the executable file boot, and the starting VMA address of the. Boot segment is 0 .. The boot code segment is the boot code we need. For more link script syntax, see http://sourceware.org/binutils/docs/ld/index.html.
3. Create a boot floppy disk image
1) run the DD command to create a new disk image named. IMG.
Dd If =/dev/Zero of = limits. img bs = 512 COUNT = 2880
2) use the losetup command to associate idea. IMG with the loop device. In this way, you can use the/dev/loop3 device to operate the idea. imgfile like a real floppy disk.
Losetup/dev/loop0 callback. img
3) write the boot code in the executable file boot to the first sector of worker. IMG. First, we need to confirm. the position of the boot segment in the executable file boot. Note that this position is not specified. the VMA address of the boot segment refers to its physical location stored in the disk file boot. We can use the objdump command to view:
Objdump-H boot
The output is as follows:
From the file off column, we can see that the. Boot segment is located at 0x00001000 from the boot file header. Then run the DD command to write the. Boot segment to the first sector of kernel. IMG.
Dd If = boot IBS = 512 skip = 8 of =/dev/loop0 obs = 512 seek = 0 count = 1
Skip * IBS = 0x00001000 is the data to be written, that is. boot segment, in the input source file, that is, the offset distance in the boot file. Seek * obs = 0 indicates that the data to be written will be written to the output target file, that is, bytes. the starting position of the imgfile, that is, from the starting position. the first byte of the imgfile starts to write data. Count * obs = 512 indicates the length of the data to be written.
Here, the boot floppy disk image is ready. For more information about DD, losetup, and objdump commands, refer to the previous article.
4. Use qemu to start the system from the boot floppy disk image.
Run the following command to start qemu.
Qemu-boot order = A-FDA/dev/loop0
At this point, we should be able to see hello boot in the qemu simulator window! .
Qemu also provides single-step debugging. With GDB, you can easily debug the boot program. Run the following command to start qemu.
Qemu-s-boot order = A-FDA/dev/loop0
The-s option is related to GDB debugging. After running this command, the qemu simulator stops and waits for GDB to send a single-step execution command. For more information about qemu, see http://qemu.weilnetz.de/qemu-doc.html.
Call the gdb command on another terminal to enter the gdb command line, and enter the following commands in sequence.