assembly 真实机器上的操作系统

nqwrtyyt  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(116)

我创建了一个小操作系统(未完成),仅使用16位汇编,可与qemu-system-i386一起工作。
但现在我想在一台真实的的机器上测试它,并在出现错误的情况下使它与真正的PC兼容。
这是操作系统
Makefile:

boot = bootloader.asm
kernel = kernel.asm

boot_o = bootloader.bin
kernel_o = kernel.bin

bin = myos.bin

asm_compiler = nasm
qemu = qemu-system-i386

compile:
    $(asm_compiler) -f elf32 -g $(boot) -o $(boot_o)
    $(asm_compiler) -f elf32 -g $(kernel) -o $(kernel_o)
    ld -m elf_i386 -nmagic -T linker.ld -o $(bin) $(boot_o) $(kernel_o)

run:
    $(qemu) -fda $(bin)

clean:
    -rm $(boot_o)
    -rm $(kernel_o)
    -rm $(bin)

字符串
linker.ld:

OUTPUT_FORMAT(binary)
ENTRY(_start)

SECTIONS
{
    . = 0x7c00;

    bootloader :
    {
        bootloader.bin (.boot);
    }

    kernel :
    {
        kernel.bin (.kernel);
    }

    /DISCARD/ :
    {
        *(.bss*);
        *(COMMON*);
    }
}


bootloader.asm:

bits 16

section .boot
global _start

_start:
    cli
        
    xor ax, ax
    mov ds, ax
    mov es, ax
        
    mov ss, ax
    mov sp, 0x9000

    mov bx, 0x7e00
    mov al, 1
    mov dh, 0
    mov dl, 0
    mov ch, 0
    mov cl, 2
    mov ah, 2
    int 0x13

    pusha

    mov ax, 0x0700  ; function 07, AL=0 means scroll whole window
    mov bh, 0x07    ; character attribute = white on black
    mov cx, 0x0000  ; row = 0, col = 0
    mov dx, 0x184f  ; row = 24 (0x18), col = 79 (0x4f)
    int 10h         ; call BIOS video interrupt

    popa

    pusha

    mov ah, 0x02
    xor dx, dx
    int 10h

    mov si, boot_msg
    mov ah, 0x0e
    boot_characterLoop:
        lodsb
        or al, al
        jz continue
        int 10h

    jmp boot_characterLoop
    continue:
        mov ah, 0x86
        mov cx, 0xF
        mov dx, 0x4240
        int 15h
        int 15h
        int 15h

    popa

    jmp 0x7e00

boot_msg: db "The os is correctly loaded"

times 510-($-$$) db 0
dw 0xAA55


kernel.asm:

bits 16

section .kernel
global _start_kernel

_start_kernel:

    mov ax, 0x3
    int 10h

    commandLoop:

        mov si, user
        call print

        mov di, input_string
        call input

        ifCommand:
            cld
            mov si, C_shutdown
            mov di, input_string
            mov cx, CL_shutdown
            repe cmpsb
            jz thenCommandShutdown
            
            cld
            mov si, C_reboot
            mov di, input_string
            mov cx, CL_reboot
            repe cmpsb
            jz thenCommandReboot

            cld
            mov si, C_clear
            mov di, input_string
            mov cx, CL_clear
            repe cmpsb
            jz thenCommandClear

            jmp elseCommand

        thenCommandShutdown:
            call shutdown

        thenCommandReboot:
            call reboot
        
        thenCommandClear:
            call clearScreen
            jmp commandLoop

        elseCommand:
            mov si, input_string
            call print
            mov si, cmdNotFound
            call print
            call newLine
            jmp commandLoop

    exit:
        cli
        hlt

;- Includes --------------------+
%include "lib/console.asm" ;    |
%include "lib/system.asm"  ;    |
;-------------------------------+

;- Variables ----------------------------------+
user: db "user >> ", 0                    ;    |
input_string: times 20 db 0               ;    |
cmdNotFound: db ": command not found!", 0 ;    |
;----------------------------------------------+

;- Commands Variables ------------------------------+
;                                                   |
C_shutdown:  db "shutdown", 0   ;                   |
CL_shutdown  equ $ - C_shutdown ;                   |
;                                                   |
C_reboot:    db "reboot", 0     ;                   |
CL_reboot    equ $ - C_reboot   ;                   |
;                                                   |
C_clear:     db "clear", 0      ;                   |
CL_clear     equ $ - C_clear    ;                   |
;---------------------------------------------------+

times 512-($-$$) db 0


我该怎么办?我需要食物吗?(我用的是ubuntu 22.04.02 LTS)ps。对不起的语法,但我是意大利人,我只有14岁😅

luaexgnf

luaexgnf1#

最简单的方法是将操作系统映像写入USB拇指驱动器,然后从该驱动器 Boot 机器。
插入您的拇指驱动器,然后运行dmesg查看内核日志并查看新设备的名称。它可能是sdb(SCSI驱动器B)。
请仔细检查是否写入了正确的设备,否则您的安装将被丢弃!
然后:

$ sudo dd if=myos.bin of=/dev/sdv

字符串
您需要确保目标计算机已配置:
1.在传统(非UEFI)模式下 Boot 。

  1. SecureBoot已禁用。
  2. USB驱动器在 Boot 优先级列表中的优先级很高。
    祝你好运!
eiee3dmh

eiee3dmh2#

离开qemu并在“真实的的机器”上工作会带来一些变化,qemu可能会为您提供帮助:

  • 您现在的代码使用硬编码0作为DL中的驱动器号。真实的的BIOS会在DL寄存器中将正确的驱动器号传递给您。您必须在ReadDiskSector函数02 h中使用 that 数字。
  • 你现在的代码期望第一次阅读磁盘成功。在真实的的硬件上,事情并不总是第一次就能成功。你应该尝试几次,如果事情根本不起作用,就在失败时中止。
  • 您当前的代码定位光标,而不考虑BH中的任何显示页码。当屏幕处于默认模式3(80 x 25 16色文本)时,真实的的BIOS支持8个显示页面。在调用SetCursorPosition函数02 h时使用mov bh, 0
cld
    xor  ax, ax
    mov  ds, ax
    mov  es, ax
    mov  ss, ax
    mov  sp, 9000h

    mov  di, 5        ; Allow 5 tries
TryNext:
    mov  dh, 0        ; CHS = (0,0,2), DL is drive number from BIOS
    mov  cx, 0002h
    mov  bx, 7E00h    ; ES:BX is buffer
    mov  ax, 0201h    ; BIOS.ReadDiskSector
    int  13h          ; -> AX CF
    jnc  Loaded
    mov  ah, 00h      ; BIOS.ResetDiskSystem
    int  13h          ; -> AH CF
    dec  di
    jnz  TryNext
Exit:
    cli
    hlt
    jmp  Exit
Loaded:

字符串

吃还是不吃

我在DOS/Windows系统上使用BIOS固件,所以既不是Ubuntu也不是UEFI固件。
每当我需要测试一个业余爱好的操作系统时,我就把它放在一个3. 5英寸的软盘上,我可以把它插入一个插入USB端口的外部软盘驱动器中。我唯一要确定的是外部设备在 Boot 顺序中是最高的(所以在硬盘和/或光驱之前)。有一个BIOS设置。
而不是软盘(最简单的),我可以只把它放在USB棒上,让BIOS假装这个棒是软盘。

相关问题