如何在没有运行操作系统的情况下自行运行程序?你能创建计算机可以在启动时加载和运行的汇编程序,例如从闪存驱动器启动计算机并运行cpu上的程序吗?
我们知道,对于X86架构:按下电源按钮后,机器开始执行0xFFFFFFF0处的代码,然后它开始在BIOS中执行代码以进行硬件初始化.BIOS执行后,它使用bootloader将操作系统映像加载到内存中.最后,操作系统代码开始运行.对于ARM体系结构,使用后的启动过程按电源按钮是什么?谢谢!
我不是bootloader和系统SW的新手,但我不知道一般程序开始的原因0x8000
.我已经知道该地址0x8000
已被用作普通C/C++程序中的起始地址.
一般程序的引导加载程序的最小大小是否占用0x8000
?或者是应该分配给32KB引导加载程序的ROM的最小块大小?还是有其他原因吗?
我想从历史或逻辑上以及从虚拟地址的角度来了解这一点.
我感谢所有人,你的时间和帮助.为了使问题更清楚,问题与虚拟地址有关,而与物理有关.
从物理内存地址的角度来看,我基本同意R的意见.
没有说一个多样化的特定系统,例如linux(甚至在android),一般RTOS(核心,以及其他,特别是ARM链接器部分),它们都使用地址0x8000作为起始地址通用程序.如此命名为crt_begin.o,crt.o等位于0x0的加载器存在于该区域.
因此,如果在启动时将其置于BootROM(冷启动),考虑到块大小,我猜一般程序的引导加载程序的最小大小为32KB.
嗯,但我不确定......
有人可以解释一下Arduino引导加载程序的工作原理吗?我不是在寻找一个高级答案,我已经阅读了代码,我得到了它的要点.
在Arduino IDE和引导加载程序代码之间发生了许多协议交互,最终产生了许多内联汇编指令,这些指令通过串行接口传输程序来自动编程闪存.
我不清楚的是第270行:
void (*app_start)(void) = 0x0000;
Run Code Online (Sandbox Code Playgroud)
...我认为函数指针的声明和初始化为NULL.随后在引导加载程序要委托执行用户加载代码的位置调用app_start.
当然,某种程度上app_start
需要在某些时候获得非NULL值,以便将所有这些组合在一起.我在引导加载程序代码中没有看到它......它是否被引导加载程序加载的程序神奇地链接了?我认为引导加载程序的主要部分是芯片复位后进入软件的入口点.
包含70个左右的程序集必须是秘密的解码器环,告诉主程序app_start到底在哪里?或者也许是Arduino IDE利用了一些隐含的知识?我所知道的是,如果某人没有将app_start更改为指向0以外的其他位置,那么引导加载程序代码将永远自行旋转......那么诀窍是什么?
编辑
我有兴趣尝试将引导加载程序移植到没有用于引导加载程序代码的单独内存空间的Tiny AVR.由于我很明显引导加载程序代码依赖于某些保险丝设置和芯片支持,我想我真正感兴趣的是将引导加载程序移植到没有这些保险丝和硬件的芯片需要做些什么.支持(但仍具有自编程能力)?
我很难理解简单的引导装载程序是如何工作的.我正在谈论的引导加载程序是麻省理工学院"操作系统工程"课程中的一个.
首先,让我向您展示BIOS执行的一段汇编代码:
[f000:fec3] 0xffec3: lidtw %cs:0x7908
[f000:fec9] 0xffec9: lgdtw %cs:0x7948
[f000:fecf] 0xffecf: mov %cr0,%eax
[f000:fed2] 0xffed2: or $0x1,%eax
[f000:fed6] 0xffed6: mov %eax,%cr0
[f000:fed9] 0xffed9: ljmpl $0x8,$0xffee1
Run Code Online (Sandbox Code Playgroud)
从它的外观来看,此代码设置中断表和描述符表,然后打开保护模式.
转到启动加载程序代码 -
# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
lgdt gdtdesc
movl %cr0, %eax
orl …
Run Code Online (Sandbox Code Playgroud) 我是编写引导加载程序的新手.我在asm中编写了一个helloworld引导程序,我现在正在尝试用C语言编写一个.我在C中编写了一个helloworld引导程序,但我无法编译它.
这是我的代码.我究竟做错了什么?我完全采取了错误的做法吗?
void print_char();
int main(void){
char *MSG = "Hello World!";
int i;
__asm__(
"mov %0, %%SI;"
:
:"g"(MSG)
);
for(i=0;i<12;i++){
__asm__(
"mov %0, %%AL;"
:
:"g"(MSG[i])
);
print_char();
}
return 0;
}
void print_char(){
__asm__(
"mov $0X0E, %AH;"
"mov $0x00, %BH;"
"mov $0x04, %BL;"
"int $0x10"
);
}
Run Code Online (Sandbox Code Playgroud) 是否可以在不使用某种类型的Assembler的情况下使用C或C++创建引导加载程序(最好不使用__asm)?我正在编写一个操作系统,并希望它完全用C和C++编写.
我主要来自x86系统背景,其中BIOS(固件)负责从PowerON加载引导加载程序(如GRUB),后者又加载操作系统.我现在一直在阅读ARM系统上的等效启动序列,似乎网上有文章引用了两个术语:bootrom和bootloader.
有些文章提到,从PowerON开始,引导加载程序(如u-boot)是第一个被执行的东西,而有些文章说,从PowerON开始,bootrom(通常在处理器的内部ROM上闪存)首先执行,然后加载引导加载程序(如uboot)然后加载操作系统.
任何人都可以提供一些关于bootrom vs bootloader的说明吗?另外,我想知道通常在ARM系统中使用的流行bootrom的名称.
我在ARM cortex-A8上使用ELinux内核.
我知道引导加载程序的工作原理以及它正在做什么工作.但我有一个问题 - 为什么我们需要bootloader,为什么bootloader诞生了?
为什么我们不能在没有bootloader的情况下直接从闪存中将内核加载到RAM中?如果我们加载它会发生什么?事实上,处理器不会支持它,但为什么我们遵循这个程序呢?
我正在为嵌入式系统编写程序,更具体地说是一个引导加载程序.我将使用C库与一些硬件组件进行交互,我可以选择用C或C++编写它.我有什么理由选择一个而不是另一个吗?我不需要C++的面向对象功能,但它确实有一个更强大的类型系统.它是否有其他语言功能可以使程序更健壮?我知道有些人会避免使用C++,因为它可以(但不总是)生成大型固件映像.