我想使用Visual C++为x86机器构建一个嵌入式内核.我有一些C和汇编代码文件要编译,我想以一种与GRUB等多重引导加载程序兼容的方式将它们连接在一起.
我正在研究一个小的x86内核.我正在访问并尝试读取GRUB在多重引导标头中提供的内存映射.我有一个Intel i3 cpu和4 GiB的RAM.在这台机器上运行时,我正在阅读以下内存映射:
--Base Address-- --Length-- --Type--
0x0000000000000000 0x000000000009d000 0x1
0x000000000009d000 0x0000000000003000 0x2
0x00000000000e0000 0x0000000000020000 0x2
0x0000000000100000 0x00000000bb53f000 0x1
0x00000000bb63f000 0x0000000000080000 0x2
0x00000000bb6bf000 0x0000000000100000 0x4
0x00000000bb7bf000 0x0000000000040000 0x3
0x00000000bb7ff000 0x0000000000001000 0x1
0x00000000bb800000 0x0000000004800000 0x2
0x00000000e0000000 0x0000000010000000 0x2
0x00000000feb00000 0x0000000000004000 0x2
0x00000000fec00000 0x0000000000001000 0x2
0x00000000fed10000 0x0000000000004000 0x2
0x00000000fed18000 0x0000000000002000 0x2
0x00000000fed1b000 0x0000000000005000 0x2
0x00000000fee00000 0x0000000000001000 0x2
0x00000000ffe80000 0x0000000000180000 0x2
0x0000000100000000 0x0000000038000000 0x1
Run Code Online (Sandbox Code Playgroud)
当我总计可用的内存区域时,我得到......
0x1(可用) - 3893.8 MiB
这似乎是正确的,留下最后的200米MiB保留给其他设备.唯一的问题是其他内存类型的总数:
0x2,0x3,0x4 - 331.5 MiB
将我的RAM总量设置为4225.3 MiB或略高于4.1 GiB,这引出了我的问题:
当我只安装了4GiB时,为什么总计超过4GiB的RAM?
为什么内存映射中的最后一个基址是0x0000000100000000?只有4GiB的RAM,32位应该是解决所有内容所需的最大地址大小.我在这里误解了什么吗?
我一直在阅读BrokenThorn的操作系统开发教程,我正在创建和加载第二阶段引导加载程序.本教程适用于Windows,但我在Linux(Ubuntu 13.04)中这样做.
这就是我所做的:
floppy.img下~/Documents/floppy用mkfs.vfat命令boot.asm使用nasm 编译的文件给我boot.bindd if=boot.bin of=~/Documents/floppy/floppy.img bs=512 count=1因此,我有第一阶段bootloader的软盘映像.在使用qemu开始时,它工作正常.
但是,在我创建第二阶段引导加载程序之后,(如果我是正确的)我将必须floppy.img将第二阶段2安装到已安装的文件系统上.在这种情况下,如何使用qemu启动已安装的软盘?它甚至可能吗?如果没有,我如何使用第二阶段引导加载程序.
请原谅我任何愚蠢的假设/问题,因为我是新手.
我正在开发一个操作系统项目,使用isolinux(syslinux 4.5)作为引导加载程序,使用组织在0x200000的多引导头加载我的内核.
据我所知,内核已经处于32位保护模式.我的问题:有没有更简单的方法来访问BIOS中断?(基本上我想要0x10:D)
加载后,我的内核设置了自己的GDT和IDT条目,并进一步重新映射IRQ.因此,在内核加载并设置VGA/SVGA模式(VBE 2.0模式)后,是否可以跳转到实模式.然后,我将继续我的内核并跳转到保护模式,我使用VBE 2.0物理缓冲区地址写入屏幕?如果有,怎么样?我尝试了很多,但没有成功:(
旁注:我在互联网上搜索了很多,发现syslinux 1.x +提供了_intcall api,我对此并不是100%肯定.请参阅"syslinux 4.5\com32\lib\sys\initcall.c"
当我在不使用libcore的情况下编写一个简单的裸机代码时,我收到以下错误:
错误:二进制操作
!=无法应用于类型u32[E0369]
直接实施面临鸡蛋问题:
#![crate_type = "lib"]
#![feature(no_std, no_core, lang_items)]
#![no_std]
#![no_core]
#[lang = "sized"]
pub trait Sized {}
#[lang = "sync"]
pub trait Sync {}
pub const CONST1: u32 = 1;
pub const CONST2: u32 = 2;
pub struct Struct {
pub field: u32,
}
impl Sync for Struct {}
pub static VAR: Struct = Struct {
field: CONST1 + CONST2,
};
Run Code Online (Sandbox Code Playgroud)
在这里我收到以下错误:
错误:二进制操作
+无法应用于类型u32[E0369]
在以下 x86 汇编代码中:
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002+0x00)
Run Code Online (Sandbox Code Playgroud)
这些值似乎没有分配给任何变量。那么这段代码有什么作用呢?我听说过它被存储在内存中,但具体在哪里呢?
我正在开发一个32位,保护模式的业余爱好操作系统.目前,我希望增加简单的声音支持.为此,我希望使用声音冲击波16并使用直接模式写入DAC(我想不惜一切代价避免使用DMA).但是,当我向DAC输出一个简单的方波(使用命令0x10)时,我的计算机扬声器没有声音输出.我正在寻找这个问题的解决方案.
我试图使用以下算法来产生声音:
1. Reset DSP
2. Enable the speakers
3. Write 0x10 to 0x22C (direct mode DAC write command)
4. Write 0x00 to 0x22C (To set the speaker to low)
5. Write 0x10 to 0x22C
6. Write 0xFF to 0x22C (To set the speaker to high)
7. Jump back to step 4 and repeat.
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
#define DSP_RESET 0x226
#define DSP_READ 0x22A
#define DSP_WRITE 0x22C
#define DSP_READ_STATUS 0x22E
#define DSP_INT_ACK 0x22F
#define REG_ADDR 0x224
#define REG_DATA 0x225
#define DIRECT_DAC 0x10
#define …Run Code Online (Sandbox Code Playgroud) 在之前的Stackoverflow 回答中,玛格丽特·布鲁姆 (Margaret Bloom) 说道:
\n\n\n\n\n唤醒 AP
\n\n这是通过向所有 AP 发出 INIT-SIPI-SIPI (ISS) 序列来实现的。
\n\n将发送 ISS 序列的 BSP 使用“全部排除自身”简写作为目的地,从而针对所有 AP。
\n\nSIPI(启动处理器间中断)会被所有在收到 SIPI 时被唤醒的 CPU 忽略,因此,如果第一个 SIPI 足以唤醒目标处理器,则第二个 SIPI 将被忽略。出于兼容性原因,英特尔建议这样做。
\n
我多年来一直在编写多处理代码,我对硬件的观察是,在某些处理器上,它似乎与所述不同。我很确定我已经观察到应用处理器 (AP) 在收到启动 IPI 后修改了其指令指针,即使它处于活动状态(不在等待启动 IPI 中)。
\n\n是否有任何英特尔文档说明 AP在不处于等待启动 IPI 状态时收到启动 IPI 后将执行的操作,或将行为记录为未定义?我似乎无法在英特尔软件文档手册或补充英特尔文档Minimal Boot Loader for Intel\xc2\xae Architecture中找到明确的答案。
\n\n通常,我编写初始化代码来初始化并启动 AP,假设 AP 可以获取 SIPI 并在活动状态(而不是等待启动 IPI 状态)下重置其指令指针。
\n\n我正在尝试确定 Margaret Bloom 声明的准确性,即先前已唤醒的 …
我正在开发一个简单而小型的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) 我正在研究对齐检查的问题。但我不知道处理器是在检查有效地址、线性地址还是物理地址,还是所有检查。
比如一个数据的有效地址已经对齐,但是加上段描述符的基地址形成的线性地址不再对齐,此时处理器抛出#AC异常。