操作系统真象-MBR

操作系统真象-MBR

Column: September 5, 2021
Tags: learning experience, 操作系统

磁盘创建:

两种创建光秃秃系统盘的方法:

qemu:

qemu-img create -f qcow2 -b hd60M.img -size 60M

bochs:

bximage -hd -mode="flat" size=60 -q hd60M.img

磁盘启动:

启动方式:(bochs生成的可以在qemu使用. 但qemu生成的好像不能在bochs使用, 至少在我这是这样的, 可能少选了点参数?)

qemu:

qemu-system-i386 -drive file=hd60M.img,index=0,media=disk,format=raw

bochs:

./bin/bochs -f ./bochsrc.disk

一些汇编的操作:

jmp $ //跳转到本行(相当于死循环一样, 可以挂起程序, 或许以后侧信道攻击也用得上)
jmp $$ //跳转到本section的头一行, 相当于section重新执行

如果定义了vstart, 则 是 v s t a r t 的 延 续 , 而 是vstart的延续, 而 vstart,$就是跳转到vstart地址

部分前置知识:

nasm:

nasm的最基本用法, 如果是想输出默认的bin文件, 则只需要用-o指定一下文件名就行了, 若是elf, 则再加上一个-f的参数

mbr位置那点事儿:

mbr和BIOS都是在0盘0道1扇区上的, 工程师假定PC 5150 BIOS最小内存是32kb, 所以mbr被放在了最后1kb上, 即0x7c00

dd:

直接对磁盘进行操作, 有点类似vim直接打开一个程序那种(当然vim打开磁盘直接就卡死了XD)

if: in file, of: out file(一个指定输入文件, 一个指定输出文件)

bs: block size(指定块大小, ibs和obs是指定输入块和输出块的大小), count(指定块的数量)

seek(指定当块输出到of时要跳过多少个块)

conv=notrunc(不打断文件, 追加数据时的方式)

vstart的实际作用:

vstart和org被指定一个值之后, 在地址上不会从0地址开始填充0直到以那个值为地址, 而是程序内部中全都加上了个逻辑偏移

mbr代码(无显卡):

我稍微改了一丢丢, 主要是打印出来的字符串

;MBR
;-----
SECTION MBR vstart=0x7c00
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov fs, ax
    mov sp, 0x7c00

;clear
;-----
;int 0x10, function numb:0x6, function: clear
;-----
;ah: function numb
;al: clear lines, if lines==0, clear all lines
;bh: clear line attributes
;(cl, ch): the position of the upper left corner of the windows (x, y)
;(dl, dh): the position of the lower right corner of the windows (x, y)
;no return

    mov ax, 0x600
    mov bx, 0x700
    mov cx, 0
    mov dx, 0x184f

    int 0x10

;-----
;get the position of the cursor and print string
    mov ah, 3; function numb
    mov bh, 0; page of cursor

    int 0x10

;-----
;print string
    mov ax, message
    mov bp, ax; the position of string

    mov cx, 0xb; length of string, not include \x00
    mov ax, 0x1301; ah: function numb, al: ways of writing, 1==display string, cursor follow with
    mov bx, 5; bh: page numb be writed, bl: char attributes

    int 0x10

;-----
;program stop
    jmp $

    message db "Thule's MBR"
    times 510-($-$$) db 0
    db 0x55, 0xaa

mbr代码(有显卡)

;MBR
;-----
SECTION MBR vstart=0x7c00
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov fs, ax
    mov sp, 0x7c00
    mov ax, 0xb800; Graphics_card base memory
    mov gs, ax

;clear
;-----
;int 0x10, function numb:0x6, function: clear
;-----
;ah: function numb
;al: clear lines, if lines==0, clear all lines
;bh: clear line attributes
;(cl, ch): the position of the upper left corner of the windows (x, y)
;(dl, dh): the position of the lower right corner of the windows (x, y)
;no return

    mov ax, 0x600
    mov bx, 0x700
    mov cx, 0
    mov dx, 0x184f

    int 0x10

;-----
;using Graphics_card to print
    mov byte [gs:0x00], 'T'
    mov byte [gs:0x01], 0xA4
    mov byte [gs:0x02], 'h'
    mov byte [gs:0x03], 0xA5
    mov byte [gs:0x04], 'u'
    mov byte [gs:0x05], 0xA6
    mov byte [gs:0x06], 'l'
    mov byte [gs:0x07], 0xA7
    mov byte [gs:0x08], 'e'
    mov byte [gs:0x09], 0xA8

;-----
;program stop
    jmp $

    times 510-($-$$) db 0
    db 0x55, 0xaa

只要把数据丢到0xb8000开始的显存就行了, 这里我们是32kb用于文本显示器, 然后基址随便放那个寄存器都可以, 双字节用来表示一个字符, 低的是内容, 高的是内容的属性

后面就是

nasm mbr.S -o mbr.bin
dd if=./mbr.bin of=./hd60M.img bs=512, count=1, conv=notrunc

然后用之前的指令启动就行了啊啊啊

mbr使用硬盘

;MBR
;-----
%include "boot.inc"
SECTION MBR vstart=0x7c00
    mov ax, cs
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov fs, ax
    mov sp, 0x7c00
    mov ax, 0xb800; Graphics_card base memory
    mov gs, ax

;clear
;-----
;int 0x10, function numb:0x6, function: clear
;-----
;ah: function numb
;al: clear lines, if lines==0, clear all lines
;bh: clear line attributes
;(cl, ch): the position of the upper left corner of the windows (x, y)
;(dl, dh): the position of the lower right corner of the windows (x, y)
;no return

    mov ax, 0x600
    mov bx, 0x700
    mov cx, 0
    mov dx, 0x184f

    int 0x10

;-----
;using Graphics_card to print
    mov byte [gs:0x00], 'T'
    mov byte [gs:0x01], 0xA4
    mov byte [gs:0x02], 'h'
    mov byte [gs:0x03], 0xA5
    mov byte [gs:0x04], 'u'
    mov byte [gs:0x05], 0xA6
    mov byte [gs:0x06], 'l'
    mov byte [gs:0x07], 0xA7
    mov byte [gs:0x08], 'e'
    mov byte [gs:0x09], 0xA8

;-----
;set sector addr
    mov eax, LOADER_START_SECTOR; LBA num
    mov bx, LOADER_BASE_ADDR; memory addr be writen
    mov cx, 1; sector count
    call rd_disk_m_16
    jmp LOADER_BASE_ADDR
;-----
;read n sectors from hard_disk
rd_disk_m_16:
    mov esi, eax
    mov di, cx

    mov dx, 0x1f2
    mov al, cl
    out dx, al; out port 0x1f2 with sector count
    mov eax, esi

    mov dx, 0x1f3
    out dx, al
    mov cl, 8
    shr eax, cl
    mov dx, 0x1f4
    out dx, al
    shr eax, cl
    mov dx, 0x1f5
    out dx, al; out port 0x1f3-0x1f5 with LOADER_START_SECTOR(LBA num)

    shr eax, cl
    and al, 0x0f
    or al, 0xe0
    mov dx, 0x1f6
    out dx, al; out port 0x1f6 to set lba mode

    mov dx, 0x1f7
    mov al, 0x20
    out dx, al

.not_ready:
    nop
    in al, dx
    and al, 0x88
    cmp al, 0x08
    jnz .not_ready; judge sector status

    mov ax, di
    mov dx, 256
    mul dx
    mov cx, ax; set read word count
    mov dx, 0x1f0
.go_on_read:
    in ax, dx
    mov [bx], ax
    add bx, 2
    loop .go_on_read
    ret

    times 510-($-$$) db 0
    db 0x55, 0xaa

loader:

%include "boot.inc"
section loader vstart=LOADER_BASE_ADDR

mov byte [gs:0x00], 'l'
mov byte [gs:0x01], 0xa4

mov byte [gs:0x02], 'o'
mov byte [gs:0x03], 0xa4

mov byte [gs:0x04], 'a'
mov byte [gs:0x05], 0xa4

mov byte [gs:0x06], 'd'
mov byte [gs:0x07], 0xa4

mov byte [gs:0x08], 'e'
mov byte [gs:0x09], 0xa4

mov byte [gs:0x0a], 'r'
mov byte [gs:0x0b], 0xa4

jmp $

Guess you like

Origin blog.csdn.net/eeeeeight/article/details/120267220