以下站点"编写引导扇区代码"提供了一个代码示例,可在系统引导时将"A"打印到屏幕上.从我一直在阅读的不是你必须使用INT操作码让BIOS做某些事情?以下代码如何从上面引用的站点工作而不使用中断?代码的哪一部分实际告诉硬件将"A"打印到屏幕上?
有问题的代码:
.code16
.section .text
.globl _start
_start:
mov $0xb800, %ax
mov %ax, %ds
movb $'A', 0
movb $0x1e, 1
idle:
jmp idle
Run Code Online (Sandbox Code Playgroud)
附加原始问题
如果我使用以下代码,BIOS调用是否会为我写入文本缓冲区?缓冲区从地址0xb800开始?
# Author: Matthew Hoggan
# Date Created: Tuesday, Mar 6, 2012
.code16 # Tell assembler to work in 16 bit mode (directive)
.section .text
.globl _start # Help linker find start of program
_start:
movb $0x0e, %ah # Function to print a character to the screen
movb $0x00, %bh # Indicate the page …Run Code Online (Sandbox Code Playgroud) 我正在为Stellaris LM3S1607芯片开发一个引导加载程序.我正在使用Keil MicroVision4 C编译器.我们的想法是创建2个独立的固件,一个将更新另一个.在firmware1中,我下载了firmware2文件,并将其写入地址0x3200的闪存中.直到这里它才有效.我还验证了数据写入闪存是否正确.现在我在flash中有两个应用程序.一个是我的uip引导装载程序,而seoncd就是我的主要项目.我想知道如何从第一个程序跳转到位于0x3200的第二个程序.
如果有人能帮我跳,那就太好了.谢谢
我试图编写一个引导加载程序以在 dos-box 中使用我编写了以下代码
[BITS 16] ;tell the assembler that its a 16 bit code
[ORG 0x7C00] ;Origin, tell the assembler that where the code will
;be in memory after it is been loaded
JMP $ ;infinite loop
TIMES 510 - ($ - $$) db 0 ;fill the rest of sector with 0
DW 0xAA55 ; add boot signature at the end of bootloader
Run Code Online (Sandbox Code Playgroud)
我试图通过以下命令使用 nasm 组装它
nasm -f elf myfile.asm
Run Code Online (Sandbox Code Playgroud)
然后我看到那个错误
错误:无法识别的指令 [ORG]
我使用的是ubuntu 14.04 LTS,nasm的版本是2.10.09
我一直在用NASM编写一个测试程序,该函数用于int 13h从引导磁盘读取扇区,但每次使用sudo qemu-system-i386 load_disk.bin运行汇编程序时,它都会为我提供以下输出:
磁盘读取错误!磁盘读取错误!磁盘读取错误!*磁盘读取错误!*磁盘读取错误!*
如果设置了进位标志(CF),则可以预期。我一直在寻找答案的几天,并尝试了许多不同的解决方案(跳转到ES:BX之后jc test,将启动驱动器保存在DL...中),但似乎没有任何效果。
这是我的程序:
[bits 16] ;real mode
[org 0x7c00]
mov [DISK], dl ;save boot drive value
xor ax, ax ;setting up stack
cli
mov ss, ax
mov sp, 0x7c00
sti
mov di, 5 ` ;counter for number of tries
read_disk:
mov ah, 0x00 ;resetting disk
int 0x13
mov bx, 0x9000 ;data buffer
mov es, bx
mov bx ,0x0000
mov ah, 0x02 ; function number …Run Code Online (Sandbox Code Playgroud) 我目前正在编写一个bootloader并且已经开始耗尽我的512B空间,所以我开始在512B之外编写更多代码并打算使用bootloader将其读入内存.我添加到我的代码的末尾:
stack_start:
resb 4096
stack_end:
Run Code Online (Sandbox Code Playgroud)
这样我就可以在操作系统代码的末尾为堆栈分配空间.目前在我的引导程序中,我在引导加载程序之后为堆栈分配4KiB,使用以下我从这里获取:
mov ax, 07c0h ; 4K stack space after the bootloader -- code is running at 0x07c0
add ax, 288 ; (4096 + 512)/16 bytes per paragraph (288 paragraphs)
mov ss, ax
mov sp, 4096 ; moves the stack pointer
Run Code Online (Sandbox Code Playgroud)
但是现在我需要一种方法来将堆栈分配到我的操作系统代码的末尾,这将是一个未知的大小.
我相信我理解这些是如何建立的 - 类似于使用es,我ss用于扩展寻址空间,但我找不到任何能够很好地解释我的知识水平的东西.我也不确定如何正确设置它以使我的堆栈结束.我用过:
mov ax, stack_start
mov ss, ax
mov sp, 4096
Run Code Online (Sandbox Code Playgroud)
并没有遇到过错误; 但是我想知道这是否正确,或者我是否真的只为堆栈分配了一些空间,同时用更高的地址填充内存.
ss实际上如何运作?我如何使用它并sp在代码末尾为堆栈分配内存?
这是在使用nasm的i386中.
编辑:如果可能的话,某些方法来验证堆栈是否在正确的位置也非常有用.
我在程序集中编写了一个stage 1 bootloader,我试图将FAT12文件系统加载到内存中,以便我可以加载我的stage 2 bootloader.我已经设法将FAT加载到内存中,但是我很难将根目录加载到内存中.
我目前正在使用它作为参考,并产生了以下内容:
.load_root:
;es is 0x7c0
xor dx, dx ; blank dx for division
mov si, fat_loaded ; inform user that FAT is loaded
call print
mov al, [FATcount] ; calculate how many sectors into the disk must be loaded
mul word [SectorsPerFAT]
add al, [ReservedSectors]
div byte [SectorsPerTrack]
mov ch, ah ; Store quotient in ch for cylinder number
mov cl, al ; Store remainder in cl for sector number
xor dx, dx …Run Code Online (Sandbox Code Playgroud) 最近经常使用闪存 ROM,我发现在芯片的内部闪存以及外部 SPI 闪存设备中,扇区的大小通常都是这样的:
我很好奇为什么起始地址空间的扇区比后面的地址小。我怀疑使用引导加载程序之类的东西会更方便。由于引导加载程序通常小于 128k,因此这将允许引导加载程序写入前 2 或 3 个扇区。这使得主空间应用程序有更多的扩展空间,因为要对其进行编程,我们需要从新扇区的开头开始。如果我们只有 128k 大小的扇区,那么我们基本上就会浪费128k - bootloader_size空间。
我的怀疑正确吗?或者这样做还有其他原因吗?真的很想知道这里的设计决策是什么。
我将kexec压缩为一个二进制文件,并将其编写为x86_64 ELF。运行正常。
由于它是64位二进制文件,因此我知道处理器必须处于64位长模式。这需要使用分页,所以我知道必须打开分页。
我的问题是,这些页表的状态是什么?是否有某些区域(例如我加载的二进制文件)可以保证进行身份映射?是否所有可用的RAM标识都已映射?由于启用了分页,因此页面在哪里?
执行完kexec'之后,我想对整个地址空间进行身份映射。为此,我需要在我知道物理地址的地址处构建一些页表结构,然后将该结构的地址写入CR3。
如果我知道加载到内存中的小精灵二进制文件是身份映射的,则可以在其中静态构建页表,然后进行无缝切换。如果kexec之后没有标识映射的页面,则需要关闭分页,退出long模式,然后进行设置,然后重新进入long 64位模式。
谢谢!
我正在尝试制作一个适用于两种架构的引导加载程序:x86 和 PDP-11。主操作系统是为 PDP-11 兼容机器编写的,但从 x86 启动也应该可以工作,启动模拟器。
AFAIK,如果最后两个字节是, x86 加载第一个磁盘扇区0x7c00并跳转到那里。相反,如果第一个命令是且最后两个字节是 ,则 PDP-11 兼容机将第一个扇区加载到(八进制)并执行它。然而,由于一些硬件细节的原因,加载的数据实际上是颠倒的——例如,x86 读取的数据,另一台机器读取的数据。在这种情况下,这在某种程度上是一个功能,因为如果我制作最后两个字节,它们将适用于两台机器。0x55 0xaa0o20000NOP0xaa 0x550x120xed0x55 0xaa
总之,PDP-11兼容机需要前两个字节包含NOP命令,即0o000240,或0x00a0。数据被反转,因此 x86 实际上会读取0xff5f。
0x5f是 x86 中的真实命令。不幸的是,它是pop di. AFAIK,sp和ss值都没有指定,所以这个命令读取谁知道什么。
我的问题是:
0x0000:0x0000or 0xffff:0xffff?ss:sp指向读取不安全的内存映射硬件寄存器?如果是的话,如果我读了它们,会发生什么更糟糕的事情?我不想意外损坏笔记本电脑。ss:sp指向不可用的内存,即可能pop di触发总线错误?如果是,BIOS 将如何从中恢复,即它将重新启动、显示消息或执行其他操作?我正在为 Nucleo-F429ZI 编写引导加载程序。我有两个不同的 STM32 项目,一个用于引导加载程序本身,另一个用于从引导加载程序跳转的应用程序。
引导加载程序的链接器脚本
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
}
Run Code Online (Sandbox Code Playgroud)
应用程序的链接器脚本
_estack = ORIGIN(RAM) + LENGTH(RAM);
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 64K
}
Run Code Online (Sandbox Code Playgroud)
我没有忘记设置应用程序的闪光偏移。
system_stm32f4xx.c(在应用程序项目中)
#define VECT_TAB_BASE_ADDRESS FLASH_BASE // 0x8000000
#define …Run Code Online (Sandbox Code Playgroud)