Gcc MinGW';s ld无法对非PE输出文件执行PE操作

Gcc MinGW';s ld无法对非PE输出文件执行PE操作,gcc,assembly,mingw,nasm,osdev,Gcc,Assembly,Mingw,Nasm,Osdev,我知道还有一些类似的问题,不管是不是StackOverflow。我为此做了很多研究,但仍然没有找到一个解决方案。 我正在做一个操作系统作为辅助项目。我一直在做汇编,但现在我想加入C代码。 为了进行测试,我创建了以下程序集代码文件(称为test.asm): 然后我制作了这个C文件(称为main.C): 为了链接,我使用了这个文件(称为make.bat): 我已经研究很久了,我仍然在努力寻找答案。我希望这不会被标记为重复。我承认存在类似的问题,但都有不同的答案,没有一个适合我 问题:我做错了什么?旧

我知道还有一些类似的问题,不管是不是StackOverflow。我为此做了很多研究,但仍然没有找到一个解决方案。 我正在做一个操作系统作为辅助项目。我一直在做汇编,但现在我想加入C代码。 为了进行测试,我创建了以下程序集代码文件(称为test.asm):

然后我制作了这个C文件(称为main.C):

为了链接,我使用了这个文件(称为make.bat):

我已经研究很久了,我仍然在努力寻找答案。我希望这不会被标记为重复。我承认存在类似的问题,但都有不同的答案,没有一个适合我


问题:我做错了什么?

旧的MinGW版本有一个问题,“ld”根本无法创建非PE文件

也许现在的版本也有同样的问题

解决方法是创建一个带有“ld”的PE文件,然后使用“objcopy”将PE文件转换为二进制、十六进制或S19

---编辑---

再想想这个问题,我发现了两个问题:

正如我已经说过的,“ld”的一些版本在创建“二进制”输出(而不是使用“PE”、“ELF”或任何格式)时存在问题

而不是:

ld.exe --oformat binary -o file.bin c.o asm.o
应使用以下顺序创建二进制文件:

ld.exe -o file.tmp c.o asm.o
objcopy -O binary file.tmp file.bin
这将创建一个名为“binary.tmp”的“.exe”文件;然后“objcopy”将从“.exe”文件创建原始数据

第二个问题是链接本身:

“ld”采用类似于.exe的文件格式,即使输出文件是二进制文件。这意味着

  • 。。。您甚至无法确定“main.o”的目标代码是否真的位于生成的目标代码的第一个地址。“ld”还可以将“a()”的代码放在“main()”之前,甚至可以将“internal”代码放在“a()”和“main()”之前
  • 。。。寻址的工作方式有点不同,这意味着如果您做错了什么,将创建大量的填充字节(可能在文件的开头!)
我看到的唯一可能性是创建一个“链接器脚本”(有时称为“链接器命令文件”)并在汇编代码中创建一个特殊部分(因为我通常使用的是“nasm”以外的另一个汇编程序,我不知道这里的语法是否正确):

在链接器脚本中,可以指定哪些节以何种顺序显示。指定“.entry”是文件的第一部分,以便您可以确保它是文件的第一条指令

在链接器脚本中,您也可以说多个部分(例如“.entry”、“.text”和“.data”)应该合并到一个部分中。这很有用,因为PE文件中的节通常是0x1000字节对齐的!如果不将多个节合并为一个节,则会在节之间获得大量存根字节

不幸的是,我不是链接器脚本的专家,所以在这方面我帮不了你太多

使用“-Ttext”也有问题:

在PE文件中,节的实际地址计算为“图像基”+“相对地址”。“-Ttext”参数将仅影响“相对地址”。因为在Windows a中,第一节的“相对地址”通常固定为0x1000“-Ttext 0x2000”除了在第一节的开头填充0x1000存根字节外,什么都不做。但是,您根本不影响“.text”的起始地址-您只在“.text”部分的起始处填充存根字节,以便第一个有用的字节位于0x2000。(可能某些“ld”版本的行为有所不同。)

如果希望文件的第一部分位于地址0x100000,则应在链接器脚本中使用“-Ttext 0x1000”的等效项(-Ttext在使用链接器脚本时不使用),并将“映像库”定义为0xFF000:

ld.exe -T linkerScript.ld --image-base 0xFF000 -o binary.tmp a.o main.o
“.text”部分的内存地址将为0xFF000+0x1000=0x100000


(由“objcopy”生成的二进制文件的第一个字节将是第一部分的第一个字节-表示内存地址0x100000。)

您能告诉我您的答案吗?非常感谢您的回答。我真的以为没有人会回答,因为这不是一个著名的主题,还有其他类似的问题。@HelderNovais:我编辑了我的答案,也许它会对你有更多帮助。我有一个未定义的main参考。“ld-o exec.e xe c.o asm.o asm.o:test.asm:(.entry+0x1):未定义对'main'的引用”,顺便问一句,对我来说最好的解决方案是什么?
ld.exe --oformat binary -o file.bin c.o asm.o
ld.exe -o file.tmp c.o asm.o
objcopy -O binary file.tmp file.bin
[BITS 32]
GLOBAL _a
SECTION .entry
    jmp _main
SECTION .text
_a:
    jmp $
ld.exe -T linkerScript.ld --image-base 0xFF000 -o binary.tmp a.o main.o