我使用Verilator设计了一个MIPS I模拟器,它允许我将verilog代码包装到c ++中。我试图在我的处理器上运行一个c ++程序,但我遇到了一些问题。我的目标是:
问题是第7步和第8步。我对ELF文件格式有一个非常基本的了解。据我所知(readelf可用于输出程序起始点)程序ounter应该最初设置在.text部分开头的地址。不幸的是,这样做不会导致在我的处理器上运行正确的程序。
我已经通过编写汇编程序,将它们加载到MIPS汇编模拟器中,并通过指令验证寄存器文件和生成的寻址匹配来验证我的处理器的正确程序执行。我不明白为什么我不能通过用c ++编写,编译和加载到我的“内存”来运行“helloworld”程序?我在这个领域并不是特别懂。我真的可以用一些帮助搞清楚这一点。
我的理解是.text和.data包含我的程序运行所需的一切。显然不是这种情况,因为当我遍历.text部分时,我的程序无法正确执行。在将ELF文件加载到内存之前,我还需要对ELF文件做些什么吗?
答案 0 :(得分:1)
我已经编写了一个完整的MIPS I模拟器,可以加载ELF二进制文件。您可以获取源代码here,也许您会得到问题的答案。还包括一些演示程序。关键是让编译器生成一个不使用任何运行时库的独立可执行文件,甚至不是gcc的支持库。
答案 1 :(得分:0)
答案 2 :(得分:0)
zvrba可能已经击中头部,你不能/不应该在你的程序中调用像printf这样的C库函数。
编写一个简单的C程序,可以从:
开始const unsigned char hello[]="helloworld"; void notmain ( void ) { unsigned int ra; for(ra=0;hello[ra];ra++) { PUT32(0x1234,hello[ra]); } }
并且从您编写的汇编程序中调用notmain,并且它们一起工作并链接在一起。
PUT32只是将一些数据写入某个地址,我通常在汇编程序ymmv中实现它们。
选择除0x1234以外的其他地址,我的假设是在您的SIM环境中,您可以观看对地址位置的访问并观看字符。当您可以观察总线上的字节时,无需与uart交谈并且必须在模拟中解码串行。
Elf文件真的很容易解析,如果你已经编写了一个模拟器,那么读取一个elf文件并不是什么大问题。我不打扰图书馆他们只是让它变得更难。如果您选择使用结构,这是一些结构。如果您愿意,我可以为您提供可以帮助您入门的代码。另一种方法是使用gnu工具将elf转换为二进制文件(mips-whatever-objcopy file.elf -O binary file.bin)。如果您的.text和.data彼此不相近,则objcopy程序将生成一个带有零的大文件,以便在两个地址空间之间填充。对于嵌入式,你想要避免在你的.data部分中有任何东西,总是不提前初始化程序中的变量而只读表make const所以它们在.text而不是.data
这是一个有趣或工作或一般公众消费的项目吗?我可能有兴趣使用它有一天我喜欢verilator的概念,但它对于verilog标准来说有限或太严格,而且那里的verilog不会在没有工作的情况下运行,所以我没有真正玩它。 / p> 祝你好运。