我目前正在尝试在 bochs 中编译并运行一个简单的引导加载程序。目前,这是我的 bootloader.asm 文件:
\n\n[BITS 16]\n[ORG 0x7C00] ;Where the code gets mapped\ntop:\n jmp top ;Loop forever\ntimes 510-($-$$) db 0 ;Pad with 0\ndw 0xAA55 ;Bootloader signature (backwards)\n ;; dw declares a word (2 bytes because we\xe2\x80\x99re 16 bits)\nRun Code Online (Sandbox Code Playgroud)\n\n然后,从我的 pragmalinux-img 目录中输入以下命令:
\n\nyasm bootloader.asm\ndd if=bootloader bs=512 \nbochs\nRun Code Online (Sandbox Code Playgroud)\n\n运行 bochs 后,我收到以下错误消息。(抱歉文字墙)
\n\n Bochs x86 Emulator 2.6\n Built from SVN snapshot on September 2nd, 2012\n========================================================================\n00000000000i[ ] LTDL_LIBRARY_PATH not set. using compile time default '/usr/lib/bochs/plugins'\n00000000000i[ ] BXSHARE not set. using …Run Code Online (Sandbox Code Playgroud) 有人知道下面的代码有什么问题吗?
我无法让它按照我想要的方式工作。我只想打印变量的单个字符(字母“h”)。
为此,我只需通过方括号使用间接寻址来复制内容
[]
; Set BIOS print screen settings
mov ah, 0x0e ; Teletype
mov bh, 0 ; Page number
mov bl, 4 ; Red on black (00000100 - High 0000 is black, low 0100 is red)
mov cx, 1 ; Writes one character
; Printing to screen
mov al, [msg] ; Copy the contents of 'H' into 'al'; IT SEEMS THIS IS NOT WORKING!!!
jmp print_char ; Jump to executable code and do not let CPU step on …Run Code Online (Sandbox Code Playgroud) 我正在制作一个引导加载程序并赋予它自我更新的能力。此过程包括将二进制文件复制到新位置,跳转到该位置,然后使用它在原始位置刷新新的引导加载程序。这一切都是使用 ARM GCC 工具链在 Eclipse 中为 M4 处理器开发的。
为此,我认为需要将其编译为位置无关代码(PIC)。
我四处搜索并发现这篇优秀的文章,因此当我将“-fPIC”添加到 ARM GCC 编译器调用时,我预计会看到有关 GOT 和 PLT 丢失的链接器错误 https://eli.thegreenplace.net/2011/11 /03/共享库中的位置无关代码图片/
在我的链接器脚本中,我将这些位置添加到 .data 部分,如下所示:
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* Create a global symbol at data start. */
*(.got*) /* .got and .plt for position independent code */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
KEEP(*(.jcr*))
. = ALIGN(4);
__data_end__ = .; /* Define a global symbol at data end. */ …Run Code Online (Sandbox Code Playgroud) 我基于 MikeOS 引导加载程序(链接)制作了一个非常基本的引导加载程序。我使用 NASM 和 QEMU 进行组装和测试。我正在尝试为我的操作系统启用保护模式。因此,我开始在网上搜索更多详细信息并了解有关 BIOS 中断的更多信息。我偶然发现了维基百科并阅读了一篇文章......
许多现代操作系统(例如 Linux 和较新版本的 Windows)完全绕过内置 BIOS 中断通信系统,更喜欢使用自己的软件直接控制连接的硬件。最初的原因主要是这些操作系统以保护模式运行处理器,而调用 BIOS 需要切换到实模式并再次返回,而切换到实模式的速度很慢。然而,也有严重的安全原因不切换到实模式,并且 BIOS 代码在功能和速度上都有限制(来源:维基百科(链接))
维基百科上的文章说
.....主要是这些操作系统以保护模式运行处理器,而调用BIOS需要切换到实模式并再次返回,而切换到实模式很慢......
(来源:维基百科(链接))
根据我的理解,在保护模式下的程序中不建议使用太多BIOS中断all,对吗?如果我是对的,那么我的引导加载程序还使用许多 BIOS 中断在屏幕上打印字符......这是好是坏?如果不好,为什么?我需要进行哪些更改才能创建打印字符程序?
由于我想让我的操作系统进入保护模式,我很困惑是否应该使用 BIOS 中断?目前我已经制作了一个仅在屏幕上打印字符串的引导加载程序,目前我的引导加载程序中没有使用任何 BIOS 中断的任何其他功能。如果在保护模式下使用 BIOS 中断不好,那么当我在保护模式下加载内核时(当我创建它时:p),我应该如何处理打印字符串功能?
还,
许多现代操作系统(例如 Linux 和较新版本的 Windows)完全绕过内置 BIOS 中断通信系统,更喜欢使用自己的软件直接控制连接的硬件。(来源:维基百科(链接))
这些开发人员如何能够开发这些软件?这些软件是用汇编语言还是其他语言制作的?他们需要深厚的硬件软件知识吗?如果可以在我的操作系统中制作这些软件,那么我正在考虑添加这些...是否建议这样做,或者我应该只使用 BIOS 中断?
尝试在测试引导加载程序上实现硬件中断。例外正在工作(因此发现它是 GPF)。当尝试时sti,会发生 GPF。这是我的主要代码:
cli
lgdt [gdt_desc]
lidt [idt_desc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x8:bit_32
bit_32:
[bits 32]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, 0x8000
mov esp, eax
mov ebp, esp
sti ; exception raised
Run Code Online (Sandbox Code Playgroud)
这就是我的 GDT 的样子:
start_gdt:
null:
dd 0x0
dd 0x0
code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 01000000b
db 0x0
data:
dw 0xffff …Run Code Online (Sandbox Code Playgroud) 我有一个Leopard板(带有DM368 Ti处理器)启动并运行.(Uboot + Linux Kernel + root fs)
现在,问题是,我不再需要busybox(目前在那里)..所以我删除它.(从/ bin/busybox)并重新启动板,但启动时给出一条错误消息说 -
Kernel panic - not syncing: No init found
还有什么我必须删除才能让它工作?或者我做错了什么?
任何帮助!谢谢.
我在网上的一些教程中读到,中断的分支地址已经硬连线.他们为什么需要在引导程序中创建IVT?
我一直在搞乱x86-16程序集并使用VirtualBox运行它.出于某种原因,当我从内存中读取并尝试将其作为角色打印时,我得到的结果与我期望的完全不同.但是,当我将字符硬编码为指令的一部分时,它工作正常.这是代码:
ORG 0
BITS 16
push word 0xB800 ; Address of text screen video memory in real mode for colored monitors
push cs
pop ds ; ds = cs
pop es ; es = 0xB800
jmp start
; input = di (position*2), ax (character and attributes)
putchar:
stosw
ret
; input = si (NUL-terminated string)
print:
cli
cld
.nextChar:
lodsb ; mov al, [ds:si] ; si += 1
test al, al
jz .finish
call putchar
jmp .nextChar
.finish:
sti
ret …Run Code Online (Sandbox Code Playgroud) 我正在学习x86实模式编程,并使用QEMU编写了一个小型引导加载程序来测试它.我选择了GNU汇编程序来学习.
这是汇编代码:
#
# boot.s
#
.section .text
.globl start
start:
//setup stack
mov $0x7c0, %ax
mov %ax, %ss
mov $512, %sp
//setup video
mov $0x0, %eax
mov $0x0, %al
int $0x10
//print a character say 'm'
mov $'m', %al
mov $0x0E, %ah
int $0x10
1:
jmp 1b
Run Code Online (Sandbox Code Playgroud)
QEMU显示屏上显示以下文本:
从硬盘启动...
问题:打印上面的消息,它似乎仍然没有做任何事情.
我用来组装的脚本链接是:
> to assemble : gcc -c boot.s
> to link : ld -T link.ld boot.o -o b.bin
> to put on bootsector of Hard-disk …Run Code Online (Sandbox Code Playgroud) 我正在尝试为STM32F030x8编写一个bootloader应用程序.我通过UART将bin文件写入控制器.当UART RDR寄存器中存在数据时,我将其放入全局声明的1Kb缓冲区中.每次缓冲区已满,我都会尝试将其写入FLASH.写入FLASH后,应用程序向PC软件发出确认,并准备接受新的1Kb块.因此,在写入FLASH时,不会写入缓冲区.当我尝试将全局缓冲区写入FLASH时,应用程序进入Hardfault处理程序.
但是当我使用memcpy()将缓冲区复制到1Kb的本地声明的缓冲区中,并尝试将该缓冲区写入FLASH时,它没有任何问题.
为什么我不能只将全局声明的缓冲区写入FLASH?当本地声明的缓冲区写入FLASH时为什么没有问题?
提前致谢!
编辑:
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data ,uint16_t DataLength)
{
uint32_t i = 0;
for (i = 0; (i < DataLength) && (*FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)
{
/* the operation will be done by word */
if (FLASH_Program(FLASH_TYPEPROGRAM_WORD, *FlashAddress, *(uint32_t*)(Data+i)) == 1)
{
/* Check the written value */
if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data+i))
{
/* Flash content doesn't match SRAM content */
return(2);
}
/* Increment FLASH destination address */
*FlashAddress += 4;
}
else …Run Code Online (Sandbox Code Playgroud)