gpt4 book ai didi

c++ - cygwin 上的 C 编译以面向独立平台

转载 作者:行者123 更新时间:2023-11-30 17:15:50 25 4
gpt4 key购买 nike

我有下面的代码,我想静态编译以在小型操作系统上运行(几乎没有操作系统!在激活保护模式后,我会将机器代码加载到内存中的特定地址)。到目前为止我的尝试还没有成功。首先有可能吗?如果没有,完成这样的事情最简单的方法是什么?

#include <stdio.h>
#define TXT_COLOR 7
#define printf(...) {sprintf(str,__VA_ARGS__);\
int i=0; while(str[i])\
write_string(TXT_COLOR, &str[i++] );}

// sprintf takes printf arguments and format data
// then write_string outputs data to the video buffer

int write_string( int colour, const char *string );

int _start()

{
char str[256]="";
char c='Z';
int j=9;
float f=9.76777;

printf("%d\t%f\t%c\this is a test\n test more!\n\n",j,f,c);
}

int write_string( int colour, const char *string )

{ /* Function to write a character to the video buffer*/

volatile char *videoBuff = (volatile char*)0xB8000;
while( *string != 0 )
{
*videoBuff++ = *string++;
*videoBuff++ = colour;
}
return 0;
}

最佳答案

对于这个答案,我假设微型操作系统是一个非常简单的内核,它启动到 32 位保护模式并且不做太多其他事情。

没有 C 标准库:-(

首先,您的程序存在问题,因为您正在使用 C 标准库中的 sprintf。恐怕您必须编写自己的 sprintf(相对容易)或将 *libc 的某些实现移植到您的操作系统(稍微更具挑战性)。我建议您在第一次测试时,只需调用原始 write_string 函数即可。我们还在 _start 末尾放置一个无限循环 - 请记住,“从 main 返回”涉及幕后发生的许多事情,这些事情尚未在裸机操作系统上实现:

#define TXT_COLOR 7

int write_string( int colour, const char *string );

int _start() {
write_string(TXT_COLOR, "this is a test");
for (;;);
}

/* Function to write a character to the video buffer*/
int write_string( int colour, const char *string ) {
volatile char *videoBuff = (volatile char*)0xB8000;
while( *string != 0 ) {
*videoBuff++ = *string++;
*videoBuff++ = colour;
}
return 0;
}

编译

使用 Cygwin GCC,我们可以分三个阶段将此源文件(我命名为 prog.c)编译为原始二进制文件。

首先,我们通过 C 编译器运行它以生成中间目标文件 (prog.o),确保指定它适用于 32 位机器:

cc -m32 -c -o prog.o prog.c

接下来,我们将 prog.o 提供给链接器,指定 32 位 PE 输出格式(在 Linux 上这将是 32 位 ELF)以及它将加载到内存中的地址(本例中为 2MB)。我们还需要指定哪个函数将作为入口点,即 _start (GCC 默认情况下在函数名称前添加下划线,因此它的真实名称实际上是 __start):

ld -mi386pe -Ttext 0x200000 --entry __start -o prog.pe prog.o

最后,我们将 PE 二进制文件 prog.pe 转换为原始、平面二进制文件 (prog.bin),不需要任何操作系统提供的基础设施即可运行。这是您将加载到内存并直接执行的内容:

objcopy -O binary prog.pe prog.bin

健全性检查

要在尝试从操作系统加载输出之前对其进行完整性检查,请查看反汇编代码:

objdump -d prog.pe

您应该在最顶部看到 _start 函数,其中包含您指定的加载地址。例如:

Disassembly of section .text:

00200000 <__start>:
200000: 55 push %ebp
200001: 89 e5 mov %esp,%ebp
200003: 83 ec 18 sub $0x18,%esp
...

然后确保 prog.bin 反汇编的原始字节与上面的匹配(符号/名称将不可见,因为它们已全部被删除)。例如:

$ objdump -D -b binary -m i386 prog.bin

Disassembly of section .data:

00000000 <.data>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
...

关于c++ - cygwin 上的 C 编译以面向独立平台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29859578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com