- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我尝试创建一个打印“hello world”的简单引导加载程序。
当我调用一个只打印“hello world”的函数时我可以做到这一点,但是当我调用一个函数来打印特定字符串时,什么也没有发生。
为此,我使用了两个文件。第一个是 boot.ld,第二个是 boot.cpp(它也可以在 C 中使用 boot.c)。
首先,我从我的终端创建软盘:
dd if=/dev/zero of=floppy.img bs=512 count=2880
其次,我编译代码(boot.cpp 和 boot.ld):
gcc -c -g -Os -m64 -ffreestanding -Wall -Werror boot.cpp -o boot.o
ld -static -Tboot.ld -nostdlib --nmagic -o boot.elf boot.o
objcopy -O binary boot.elf boot.bin
最后,我将 boot.bin 添加到 floppy.img 中:
dd if=boot.bin of=floppy.img
现在我们只需要从 VirtualBox 的存储面板添加软盘并启动我们的虚拟机。
源代码
来自:http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part
启动.ld
ENTRY(main);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7DFE)
{
SHORT(0xaa55);
}
}
boot.cpp(或 boot.c)
void cout();
void main()
{
cout();
}
void cout()
{
__asm__ __volatile__("movb $'h' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'e' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'l' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'l' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'o' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $' ' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'w' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'o' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'r' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'l' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
__asm__ __volatile__("movb $'d' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
}
输出:
有漏洞的源代码
boot.cpp(或 boot.c)
void cout(const char* str);
void main()
{
cout("hello world");
}
void cout(const char* str)
{
while(*str)
{
__asm__ __volatile__ ("int $0x10" : : "a"(0x0e00 | *str), "b"(0x0007));
++str;
}
}
输出:
为什么输出是空的?
我的功能有什么问题?
我忘记了什么?
感谢您的帮助。
最佳答案
在我的交叉编译器 (i686-elf-gcc (GCC) 4.9.2
) 上,后面的代码生成以下 (dis) 程序集:
boot.o: file format elf32-i386
Disassembly of section .text:
00000000 <cout>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 53 push %ebx
4: bb 07 00 00 00 mov $0x7,%ebx
9: 8b 55 08 mov 0x8(%ebp),%edx
c: 0f be 02 movsbl (%edx),%eax
f: 84 c0 test %al,%al
11: 74 08 je 1b <cout+0x1b>
13: 80 cc 0e or $0xe,%ah
16: cd 10 int $0x10
18: 42 inc %edx
19: eb f1 jmp c <cout+0xc>
1b: 5b pop %ebx
1c: 5d pop %ebp
1d: c3 ret
我很想知道您是否将 GCC(一种非 16 位兼容的编译器)与 16 位内容(BIOS 中断)一起使用。如果您要编写 16 位代码,请使用完整的汇编代码! GCC 只会把它搞砸,因为它生成的 32 位代码将在 16 位模式下运行。如果你想直接上C/C++,那么你要写的可能不是bootloader,而是一个kernel。 .在这种(常见)情况下,请阅读 the unquestionable sacred ritual to initiate you into OSDev .你的第一个例子成功只是运气,任何微小的变化都可能破坏一切,甚至导致 the mythical horrifying triple fault, nightmares of kernel panics themselves .
无论如何,你最好直接写入 VGA DMA 内存而不是使用 BIOS 调用(你需要先访问 protected mode,然后访问 setup the VGA hardware and modes (GRUB 会为您完成此操作,但您正在创建引导加载程序,不是吗?)):
void PrintString(const char *str) {
uint16_t *vga = (uint16_t*)0xB8000;
for(; *str != '\0'; str++, vga++)
*vga = ((uint16_t)0x07 << 8) | *str; // Light grey on a black background, nice!
}
顺便说一句,您可能会发现 the OSDev community, wiki, andforums很有用。而且,如评论中所示,您应该为 real mode 使用 .code16
代码,并且您的链接文章已经显示了它的年龄。
关于c++ - 编写一个简单的 Bootloader HelloWorld - 错误函数打印字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32931063/
我想知道引导加载程序在哪些硬件上运行?它是在 RAM 上运行,还是在主板的处理器上运行,如果它不在处理器上运行,那么在加载操作系统时处理器的用途是什么,例如将操作系统的内核加载到处理器中(如果它是'就
我将编写并测试一个引导加载程序。为了做到这一点,我计划将引导加载程序复制到软盘镜像文件并将其安装在 VM 中。 但是,我不确定将引导加载程序的机器代码放在哪里。它是否只是转储到文件的前几个字节中? 最
我需要在 grub2 命令提示符下挂载 VHD 文件。 我尝试使用“loopback”命令,如下所示: grub > insmod ntfs grub > insmod ntldr grub > lo
引导加载程序与引导加载程序有何不同。根据我的说法,引导加载程序存储在 ROM 中,引导加载程序存储在硬盘的 MBR 中(如果我错了,请纠正我)。 bootstrap loader是启动后第一个执行的程
我有以下 U-Boot 环境变量: nas220> printenv autoload=no autostart=no baudrate=115200 bootargs=console=ttyS0,1
我正在考虑开发一个简单的(开始)UEFI 引导加载程序来加载 ELF 镜像,并且想知道是否有人可以很好地进入任何现有项目,或者我可以用来开始的示例和。 此外,我想知道是否有人有任何让 virtual
我目前正在修复我为加载自定义实模式 x86 内核 (SYS.BIN) 而编写的引导加载程序。我设法让它读取根目录和 FAT,并从文件系统加载一个小型内核,所有这些都在引导扇区内。但是,我开始用更大的内
终于, Spark 板边缘板今天到了;-) 遵循这个写得很好的指南:https://codelabs.developers.google.com/codelabs/sparkfun-tensorflo
STM32 App Note 2606 对此进行了讨论,但没有简单的代码示例。 最佳答案 此答案已使用 IAR EWARM 在 STM32F072 Nucleo 板上进行测试。该答案仅使用“STM32
我已经为位于扇区 0 的 SAM4S 编写了一个引导加载程序,并在扇区 1 加载了一个应用程序。然而问题是,当我尝试跳转到新函数时,它似乎生成了一个异常(调试器转到 Dummy_Handler ())
这个主要是在facebook的源码中看到的 Bootloader.setResourceMap({"bMxb7":{"name":.... javascript中的bootloader到底是什么?有什
我终于了解了汇编和裸机编程的基础知识。或者至少这是我的想法。这是我写的(我自己第一次:)) [BITS 16] [ORG 0X7C00] Yaz: MOV SI, Msa MOV AL, [SI
我查了很多关于这个问题的资料,但还没有找到明确的答案。如您所知,AVR 微 Controller Atmega128有一个Flash存储器,可分为引导加载程序和应用程序存储器。我已经调整了每一项的参数
我发现我的 android 图像存在问题,命令 adb reboot bootloader 只是重新启动 android,而不是进入引导加载程序模式。 为了解决这个问题,我做了一些研究,发现实际上有两
我尝试创建一个打印“hello world”的简单引导加载程序。 当我调用一个只打印“hello world”的函数时我可以做到这一点,但是当我调用一个函数来打印特定字符串时,什么也没有发生。 为此,
我在通过 Java Webstart 运行 Java RCP 应用程序时遇到问题。 这适用于团队中的其他人,但不适用于我。 (你不就是喜欢这类问题吗) 我认为问题在于它正在下载 32 位版本的应用程序
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
我找到了这个网站:http://www.os-forum.com/minix/boot/ 声称记录了Minix的启动顺序。 但是在我从Git获得的Minix 3.2的源代码树中,上述站点中描述的文件根
引导加载程序无论如何都会在该地址加载它?为什么要在程序中指定这个? 最佳答案 ORG 伪指令的作用是告诉汇编器将此偏移量添加到提到的所有绝对地址。例如,如果您编写“MOV AX,my_string”并
我是这些设备的新手,即使它们很便宜,我也不想不必要地把它们弄成砖头。 我使用 esptool 将 NodeMCU 固件刷写到我的模块上。这样做时,我需要指定写入文件的地址,通常是 0x00000。这是
我是一名优秀的程序员,十分优秀!