今天尝试写我的第一个裸机程序,虚拟机使用bochs,这个虚拟机配置很容易,也比较简单,非常新手。

 1# bochs 配置文件
 2
 3# 设置Bochs 在运行过程中能够使用的内存,32MB
 4megs: 32
 5
 6# BIOS和显示BIOS
 7romimage: file=/home/admin123/Desktop/bochs/share/bochs/BIOS-bochs-latest
 8vgaromimage: file=/home/admin123/Desktop/bochs/share/bochs/VGABIOS-lgpl-latest
 9
10# 软盘,不用
11# floppya: 1_44=a.img, status=inserted
12
13# 使用硬盘
14# boot: floppy
15boot: disk
16
17# 日志文件的输出。
18log: bochs.out
19
20# 关闭鼠标
21mouse: enabled=0
22keyboard_mapping: enabled=1,map=/home/admin123/Desktop/bochs/share/bochs/keymaps/x11-pc-us.map
23
24# 硬盘设置
25ata0-master: type=disk, path="hd60M.img", mode=flat, cylinders=121, heads=16, spt=63
26ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
27
28# gdb的支持,1234 端口调试
29gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0
 1[org 0x7c00]
 2[bits 16]
 3BOOT_MAIN_ADDR equ 0x500
 4readdiskmsg db "ReadDisk...", 0
 5
 6global _start
 7
 8_start:
 9    xor ax, ax
10    mov ds, ax
11    mov es, ax
12    mov ss, ax
13    mov fs, ax
14    mov sp, 0x7c00
15
16    mov ax, 3
17    int 0x10
18
19    mov ecx, 2
20    mov bl, 2
21
22    mov dx, 0x1f2
23    mov al, bl
24    out dx, al
25
26    inc dx
27    mov al, cl
28    out dx, al
29
30    inc dx
31    mov al, ch
32    out dx, al
33
34    inc dx
35    shr ecx, 16
36    mov al, cl
37    out dx, al
38
39    inc dx
40    mov al, ch
41    and al, 0b1110_1111
42    out dx, al
43
44    inc dx
45    mov al, 0x20
46    out dx, al
47
48    mov si, readdiskmsg
49    call print
50
51.hd_ready_check:
52    mov dx, 0x1f7
53    in al, dx
54    and al, 0b0000_1000
55    cmp al, 0b0000_1000
56    jnz .hd_ready_check
57
58    mov dx, 0x1f0
59    mov cx, 256
60    mov edi, BOOT_MAIN_ADDR
61
62.read_boot:
63    in ax, dx
64    mov [edi], ax
65    add edi, 2
66    loop .read_boot
67
68    jmp BOOT_MAIN_ADDR
69
70;; mov si, string
71;; call print
72print:
73    mov ah, 0x0e
74    mov bh, 0
75    mov bl, 0x01
76.print_loop:
77    mov al, [si]
78    cmp al, 0
79    jz .print_done
80    int 0x10
81
82    inc si
83    jmp .print_loop
84
85.print_done:
86    ret
87
88times 510 - ($ - $$) db 0
89db 0x55, 0xaa

汇编具体就不解释了,太累了。

我没有在这个代码里分段,因为分段之后编译出来的二进制会有内存对齐,导致最后大小不是512字节。

运行效果:

image.png