在完全仿真中,I/O设备,CPU,主存储器被虚拟化.客户操作系统将访问虚拟设备而不是物理设备.但究竟什么是完全虚拟化?是完全仿真还是完全不同的东西?
我正在尝试制作自己的自定义操作系统,我需要一些代码帮助.这是我的bootloader.asm:
[ORG 0x7c00]
start:
cli
xor ax, ax
mov ds, ax
mov ss, ax
mov es, ax
mov [BOOT_DRIVE], dl
mov bp, 0x8000
mov sp, bp
mov bx, 0x9000
mov dh, 5
mov dl, [BOOT_DRIVE]
call load_kernel
call enable_A20
call graphics_mode
lgdt [gdtr]
mov eax, cr0
or al, 1
mov cr0, eax
jmp CODE_SEG:init_pm
[bits 32]
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 …
Run Code Online (Sandbox Code Playgroud) 我一直在开发一个简单的引导加载程序,并且在某些环境中偶然发现问题,这些环境中的指令不起作用:
mov si, call_tbl ; SI=Call table pointer
call [call_tbl] ; Call print_char using near indirect absolute call
; via memory operand
call [ds:call_tbl] ; Call print_char using near indirect absolute call
; via memory operand w/segment override
call near [si] ; Call print_char using near indirect absolute call
; via register
Run Code Online (Sandbox Code Playgroud)
这些中的每一个碰巧涉及间接接近CALL到绝对存储器偏移.我发现如果我使用类似的JMP表,我会遇到问题.相对的呼叫和跳转似乎没有受到影响.像这样的代码有效:
call print_char
Run Code Online (Sandbox Code Playgroud)
我已经通过海报讨论了Stackoverflow上提出的建议,讨论了编写引导加载程序的注意事项.特别是我看到这个Stackoverflow回答了一般的Bootloader技巧.第一个提示是:
- 当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的CS,DS,ES,SS,SP寄存器.应在引导加载程序启动时正确设置它们.您只能保证将从物理地址0x07c00加载并运行引导加载程序,并将引导驱动器号加载到DL寄存器中. …
我正在开发一个简单而小型的64位操作系统。到目前为止,我只使用一个文件,并使用NASM进行编译:
nasm -f bin os.asm -o os.bin
Run Code Online (Sandbox Code Playgroud)
然后.bin
用qemu 测试文件。
现在,我需要在文件中使用多个os.bin
文件。我插入了这一行:
extern helper_func
Run Code Online (Sandbox Code Playgroud)
然后在代码中调用它。在另一个.asm文件中,我创建了此函数或过程。问题是bin格式不支持extern
,因此我尝试使用ELF格式创建.obj
文件,然后将它们与gcc链接:
gcc -m32 -nostdlib -nodefaultlibs -lgcc os.obj helper.obj -t linker.ld
Run Code Online (Sandbox Code Playgroud)
与此链接文件:
ENTRY(_start)
SECTIONS
{
. = 0x7C00;
.text :
{
*(.text);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试运行.bin
已创建的时,qemu无法识别该文件。我做错了什么?
(我使用过gcc是因为我计划将来使用C代码)
实际上,我什至不知道gcc中所有标志的作用。我已经从Internet XD复制了它们。
到目前为止,这是我所做的:
nasm -f elf os.asm -o os.obj
nasm -f elf helper.asm -o helper.obj
gcc -m32 -nostdlib -nodefaultlibs -lgcc os.obj helper.obj -t linker.ld -o myos.bin
objcopy --input-target=elf32-little --output-target=binary myos.bin myos.bin.new
qemu-system-x86_64 myos.bin.new …
Run Code Online (Sandbox Code Playgroud) 我正在学习汇编语言.我写了一个简单的bootloader.测试后,它没有用.这是我的代码:
[bits 16]
[org 0x7c00]
jmp start
data:
wolf_wel_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0
wolf_kernel_load db 'Loading kernel....',0x0D,0x0A,0
wolf_error_msg db 'Kernel.bin not found!',0x0D,0x0A,0
wolf_error_msg1 db 'Press any key to restart..',0
start:
mov si, wolf_wel_msg
call wolf_print
mov si, wolf_kernel_load
call wolf_print
pushf
stc
mov ah,00
mov dl,00
int 13h
read_sector:
mov ax, 0x0
mov es, ax
xor bx, bx
mov ah, 02
mov al, 01
mov ch, 01
mov cl, 02
mov dh, 00
mov dl, 00
int 13h
jc wolf_error …
Run Code Online (Sandbox Code Playgroud) 我对装配很新,但我正试图深入了解低级计算的世界.我正在尝试学习如何编写将作为引导加载程序代码运行的汇编代码; 所以独立于任何其他操作系统,如Linux或Windows.在阅读了本页和其他几个x86指令集列表之后,我想出了一些汇编代码,它应该在屏幕上打印10 A然后是1 B.
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov cl, 10 ; Use this register as our loop counter
mov ah, 0Eh ; This register holds our BIOS instruction
.repeat:
mov al, 41h ; Put …
Run Code Online (Sandbox Code Playgroud) 我正在尝试通过AMD 286系统上的异常处理来初始化保护模式。我已经在Bochs上调试了以下代码,并且在这里可以正常工作。在奔腾4机器上运行时也是如此。但是在286上,当到达int3
指令时,它只是三重故障。可以观察到的行为是:如果我注释掉了int3
,则会无限期地在屏幕上显示“ OK”,而按原样使用代码,则系统将重新启动。
该代码将由FASM编译,并将二进制文件放入HDD或FDD的引导扇区中。我实际上是从1.4M软盘运行它。
org 0x7c00
use16
CODE_SELECTOR = code_descr - gdt
DATA_SELECTOR = data_descr - gdt
; print "OK" on the screen to see that we've actually started
push 0xb800
pop es
xor di,di
mov ax, 0x0700+'O'
stosw
mov ax, 0x0700+'K'
stosw
; clear the rest of the screen
mov cx, 80*25*2-2
mov ax, 0x0720
rep stosw
lgdt [cs:gdtr]
cli
smsw ax
or al, 1
lmsw ax
jmp CODE_SELECTOR:enterPM
enterPM:
lidt [idtr]
mov cx, DATA_SELECTOR …
Run Code Online (Sandbox Code Playgroud) 我的引导加载程序由两个 512 字节的阶段组成。阶段 1 由 bios 加载到 MBR 区域。stage1 然后继续从驱动器加载 stage2 并跳转到它。
我用十六进制编辑器确认最终二进制“program.bin”的大小正好是 1024 字节长,并且包含两个“签名”(每个阶段的最后两个字节,0xAA55 用于 stage1(MBR 签名)和 0xCC77 用于 stage2)。
预期产出是:
1 // stage1 started
0000 or 0080 // drive# in hex
CC77 // stage2 "signature" in hex
2 // stage2 started
Run Code Online (Sandbox Code Playgroud)
这在 QEMU 中工作正常,但在 virtualbox 和硬件上失败。在我看来,stage2 加载无声无息地失败(错误分支没有被调用),我希望解决这个问题两周,但没有成功。
stage1.asm:
global _start
extern _stage2
extern _stage2data
BITS 16
_start:
; init registers
xor ax, ax
mov es, ax
mov gs, ax
mov ss, ax …
Run Code Online (Sandbox Code Playgroud) 我正在制作引导加载程序,作为学习汇编的一种方式。我已经研究过使用部分来组织和优化我的代码,但是当我调用 printf 函数时,一件事不起作用。当我在 .data 部分中有 HELLO_WORLD 字符串时,它根本不想加载该字符串
; Set Code to run at 0x7c00
org 0x7c00
; Put into real mode
bits 16
; Variables without values
section .bss
; Our constant values
section .data
HELLO_WORLD: db 'Hello World!', 0
; Where our code runs
section .text
_start:
mov si, HELLO_WORLD ; Moves address for string into si register
call printf ; Calls printf function
jmp $ ; Jump forever
printf:
lodsb ; Load the next character
cmp al, 0 …
Run Code Online (Sandbox Code Playgroud) 我想创建printl
允许我在寄存器中打印字符串的函数ax
。我处于 16 位实模式,找不到任何打印消息的方法。我用来int 0x10
打印一封信。
我尝试在寄存器中传递参数(要打印的字符串)bx
,然后在循环中逐个字母地打印,然后使用popa
and返回ret
。我的代码并没有真正起作用——要么它创建了一个无限循环,要么打印了一个奇怪的符号。
如果您知道更有效的方法,那么这不是问题。如果您提供任何评论,我还想询问您的代码
这是我的代码
启动.asm:
start:
mov bx, welcome ;put argument to bx
call printl ;call printl function in sysf.asm
hlt ;halt cpu
welcome db 'Hello', 0
include 'sysf.asm'
times 510 - ($-$$) db 0
db 0x55
db 0xAA
Run Code Online (Sandbox Code Playgroud)
sysf.asm:
;print function
; al is one letter argument (type Java:char)
;
print:
pusha
mov ah, 0x0e
int 0x10
popa
ret ; go back
;printl function …
Run Code Online (Sandbox Code Playgroud)