使用 NASM 编写/链接平面二进制文件LD
我正在创建自己的“玩具”操作系统,并且我已经达到了尝试理解链接和可执行格式的地步 - 特别是我有一个平面文件二进制格式可执行文件,我正在将其加载到地址 0x500
然后直接调用。作为示例,请考虑以下两条指令(我知道它是人为的,我只想在示例中包含 call
和 mov
)
mov ax, some_label
call some_label
; some_label is at address 0x99 into the resulting binary
到目前为止,我一直在使用 NASM通过使用 org 0x500
指令和命令 nasm -f bin myfile.asm
来生成所需的输出。由此产生的反汇编看起来像这样并且工作完美:
mov ax, 0x599
call 0x599
我现在想开始使用 LD,以便我可以链接到其他对象,但经过大量实验和阅读后,我仍然不太明白发生了什么足以获得可靠的结果。
为了产生类似的输出,我需要:
- 将 NASM 输出为 obj 格式,其中包括适合链接的符号信息(我选择了 ELF,因为它似乎是一种很好的格式)
- 获取 LD将结果与
.text
部分的地址链接为0x500
,然后将结果作为平面二进制文件发出 - 由链接器最终决定各种偏移量的结果最终解析为二进制。
到目前为止,我已经尝试了以下操作:
:: Output as ELF
nasm -f elf myfile.asm
:: Then link and output as binary with the address of .text as 0x500
ld --oformat binary -Ttext 0x500 myfile.o
但这给了我以下错误(这是在 Mingw 上):
ld:无法对非 PE 输出文件执行 PE 操作
谷歌搜索引导我找到 此邮件列表,这似乎是有道理的,所以我尝试了以下操作:
:: Output as ELF
nasm -f elf myfile.asm -o myfile.o
:: Link using LD
ld myfile.o -Ttext 0x500 -s -o myfile.tmp
:: Use objdump to output as a flat binary
objcopy -O binary myfile.tmp myfile
然而,生成的 myfile
看起来像垃圾:
00000000 66B8C105E8B8 mov eax,0xb8e805c1
00000006 0000 add [bx+si],al
我已经尝试了上面的一些变体,但它们都没有产生什么我一直在期待,所以现在我很困惑:
- 任何人都可以帮助我理解这里发生了什么吗?
- 另外,我应该做什么才能对生成的二进制文件中的地址解析到的位置进行同样的控制?
I'm creating my own "toy" OS, and I've gotten to the point where I am trying to understand linking and executable formats - in particular I have a flat file binary format executable which I am loading into memory at address 0x500
and then directly calling. As an example consider the following two instructions (I know its contrived, I just wanted to include both a call
and mov
in my sample)
mov ax, some_label
call some_label
; some_label is at address 0x99 into the resulting binary
Up until now I have been using NASM to produce the desired output by using the org 0x500
directive with the command nasm -f bin myfile.asm
. The resulting disassembly looks like this and works perfectly:
mov ax, 0x599
call 0x599
I now want to start using LD so that I can link against other objects, but after a lot of experimentation and reading up I still don't really understand whats going on enough to get reliable results.
I've gather than in order to produce similar output I need to:
- Get NASM to output to an obj format which include symbol information suitable for linking (I've chosen ELF as it seems to be as good a format as any)
- Get LD to link the result with the address of the
.text
section as0x500
and then emit the result as a flat binary - it is the linker that ultimately decides what the various offsets get resolved to in the end binary.
So far I've tried the following:
:: Output as ELF
nasm -f elf myfile.asm
:: Then link and output as binary with the address of .text as 0x500
ld --oformat binary -Ttext 0x500 myfile.o
However this gives me the following error (this is on Mingw):
ld: cannot perform PE operations on non PE output file
Googling that led me to this mailing list, which seems to make sense and so instead I tried the following:
:: Output as ELF
nasm -f elf myfile.asm -o myfile.o
:: Link using LD
ld myfile.o -Ttext 0x500 -s -o myfile.tmp
:: Use objdump to output as a flat binary
objcopy -O binary myfile.tmp myfile
However the resulting myfile
looks like garbage:
00000000 66B8C105E8B8 mov eax,0xb8e805c1
00000006 0000 add [bx+si],al
I've tried a few variations on the above, but none of them produce what I was expecting and so right now I'm fairly confused:
- Can anyone help me understand what it is that is going on here?
- Also what should I be doing to give me the same sort of control over where addresses in the resulting binary are resolved to?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
所以我发现我做了很多错误的事情,其中最严重的是尝试使用LD(不支持16位代码)编译和链接16位代码,并且没有使用
BITS 16(这意味着 NASM 发出 32 位内存地址)。
这总体上解释了 LD 在上述情况的某些变体中给我的一些奇怪的错误消息,以及为什么链接的二进制文件的反汇编是垃圾 - 我试图将 32 位代码反编译为 16 位代码或反之亦然。
理想情况下,我希望能够链接 16 位代码,但发现我无法使用 LD 来做到这一点(而且很少有替代方案可以做到这一点),我决定解决了解当我用 32 位代码重复同样的事情时发生了什么。我的输入文件:
然后我使用以下内容链接它:
当使用
ndisasm
反汇编时,我需要指定-b 32
以便让它正确地将代码解释为 32 位。我进行了大量的实验并阅读了晦涩的论坛链接,但结果我现在对整个事情有了更好的理解。
So I figured out that I was doing multiple wrong things, the most serious of which was attempting to compile and link 16 bit code using LD (which does not support 16 bit code) and without explicitly specifying that the code was 16 bit using
BITS 16
(which meant that NASM emitted 32 bit memory addresses).This overall accounted for some of the odd error messages that LD would give me in some variations of the above situation, as well as why the dis assembly of the linked binary was garbage - I was attempting to decompile 32 bit code as 16 bit code or visa versa.
Ideally I'd like to be able to link 16 bit code, but having discovered that I can't do this with LD (and there are very few alternatives that can do this) I decided to settle with understanding whats going on when I repeat the same thing with 32 bit code. My input file:
I then link this using the following:
When disassembling using
ndisasm
I need to specify-b 32
in order to get it to correctly interpret the code as 32 bit.It took a lot of experimentation and reading up of obscure forum links but I now understand the whole thing a lot better as a result.