汇编语言
汇编语言一发入魂 – 杨河老李 (kviccn.github.io)
Writing a Bootloader Part 1 | Alex Parker's Website (3zanders.co.uk) Part 2
part 3 在Ubuntu的编译:sudo apt install build-essential -y
asm: nasm -f elf32 a.asm -o boot1.bin
comipile: g++ -m32 -ffreestanding -fno-exceptions -fno-rtti -fno-pic -Wall -Wextra -Werror -nostdlib -std=c++11 -o kmain.o -c kmain.cpp
ld: ld -m elf_i386 -T linker.ld -o kernel.bin boot1.bin kmain.o
check:
hexdump kernel.bin
run:
qemu-system-x86_64 -fda kernel.bin
When you press the power button the computer loads the BIOS from some flash memory stored on the motherboard. The BIOS initializes and self tests the hardware then loads the first 512 bytes into memory from the media device (i.e. the cdrom or floppy disk). If the last two bytes equal
0xAA55
then the BIOS will jump to location0x7C00
effectively transferring control to the bootloader.At this point the CPU is running in 16 bit mode, meaning only the 16 bit registers are available. Also since the BIOS only loads the first 512 bytes this means our bootloader code has to stay below that limit, otherwise we’ll hit uninitialised memory!
只加载512k内容。其他内存区域是未初始化状态。
BIOS启动:
Boot Process Overview
- BIOS Initialization:
- When a computer is powered on, the Basic Input/Output System (BIOS) performs a Power-On Self Test (POST) to check the hardware components and ensure everything is functioning correctly.
- Loading the Boot Sector:
- After POST, the BIOS looks for a bootable device (like a hard drive, CD-ROM, or floppy disk) based on the boot order configured in the BIOS settings.
The BIOS reads the first sector (512 bytes) from the bootable device. This sector is known as the Master Boot Record (MBR) on hard drives or the boot sector on other media.
- The last two bytes of this 512-byte sector must contain the boot signature 0xAA55. This signature indicates that the sector is a valid boot sector.
- If the signature is present, the BIOS considers the sector bootable.
- The BIOS loads these 512 bytes into a specific location in memory, which is typically 0x7C00.
- This location is chosen because it is a conventional memory address that is free and available during the boot process. It is within the first 1MB of memory, which is accessible in real mode (the mode the CPU is in when the system first starts).
- After loading the boot sector into memory at 0x7C00, the BIOS jumps to this address to execute the code contained in the boot sector.
- This effectively transfers control from the BIOS to the bootloader, which is responsible for loading the operating system.
- Historical Reasons: The choice of 0x7C00 is largely historical. It was chosen as a convenient location that is free and does not conflict with other system components during the boot process.
- Real Mode Constraints: In real mode, the CPU can only address the first 1MB of memory. 0x7C00 is within this range, making it accessible during the initial boot phase.
16-bit Real Mode
1. 16-bit Mode: When the CPU starts, it operates in real mode, which is a 16-bit mode. This means that the CPU can use 16-bit registers and can address up to 1MB of memory (though typically only the first 640KB is usable for conventional memory).
- Addressing in Real Mode:
- In real mode, memory is addressed using a combination of segment and offset registers. The effective address is calculated as segment * 16 + offset.
- This addressing scheme allows access to the first 1MB of memory, but each segment can only be 64KB in size.
创建一个启动盘 Bootable USB Drive
1, 编译这段代码
hello.s
.code16
movw $0x07c0, %ax
movw %ax, %ds
movw $0xb800, %ax
movw %ax, %es
xorw %si, %si
movw message_length, %cx
l1:
movb message(%si), %bl
movb %bl, %es:(%si)
incw %si
loop l1
jmp .
message:
.byte 'H', 0xa, 'e', 0xa, 'l', 0xa, 'l', 0xa, 'o', 0xa, ' ', 0xa, 'W', 0xa, 'o', 0xa, 'r', 0xa, 'l', 0xa, 'd', 0xa
message_length:
.word . - message
.org 510
.word 0xAA55
as --32 boot.s -o boot.o
objcopy -O binary -j .text boot.o boot.bin
exdump boot0.bin 查看
一定注意,将没用的区域清零。否则总是引导不成功。由于这个boot.bin只有512。那么后面需要接00 00...
dd if=/dev/zero of=disk.img bs=1024 count=100 生产一个清空的磁盘印象。块大小是1024,产生100个,就是102400字节大小。
- Identify the device name of your USB drive using the lsblk or fdisk -l command. It will be something like /dev/sdX (where X is a letter representing the drive).
- Use the dd command to write your boot.bin file to the USB drive. This will overwrite the beginning of the drive with your bootloader code.