使用 NASM 编写/链接平面二进制文件LD

发布于 2024-11-06 13:41:15 字数 1699 浏览 7 评论 0原文

我正在创建自己的“玩具”操作系统,并且我已经达到了尝试理解链接和可执行格式的地步 - 特别是我有一个平面文件二进制格式可执行文件,我正在将其加载到地址 0x500 然后直接调用。作为示例,请考虑以下两条指令(我知道它是人为的,我只想在示例中包含 callmov

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 as 0x500 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

贪了杯 2024-11-13 13:41:15

所以我发现我做了很多错误的事情,其中​​最严重的是尝试使用LD(不支持16位代码)编译和链接16位代码,并且没有使用BITS 16(这意味着 NASM 发出 32 位内存地址)。

这总体上解释了 LD 在上述情况的某些变体中给我的一些奇怪的错误消息,以及为什么链接的二进制文件的反汇编是垃圾 - 我试图将 32 位代码反编译为 16 位代码或反之亦然。

理想情况下,我希望能够链接 16 位代码,但发现我无法使用 LD 来做到这一点(而且很少有替代方案可以做到这一点),我决定解决了解当我用 32 位代码重复同样的事情时发生了什么。我的输入文件:

; Address locations are now 32 bits so I must use `eax` instead of `ax`
mov eax, some_label 
call some_label
; some_label is at a different address into the resulting binary (because 
; pointers are wider the resulting machine code is larger)

然后我使用以下内容链接它:

:: Output as win32 object files - makes it possible to use -r with LD.
nasm -f win myfile.asm -o myfile.o
:: Link using LD - the -r flag prevents extra un-used code (e.g. __CTOR_LIST__) being generated - see the link in my original question text
ld myfile.o -Ttext 0x500 -s -r -o myfile.tmp
:: Use objdump to output as a flat binary - -j .text ensures that just the .text section is included which keeps the output file size down
objcopy -O binary -j .text myfile.tmp myfile

当使用 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:

; Address locations are now 32 bits so I must use `eax` instead of `ax`
mov eax, some_label 
call some_label
; some_label is at a different address into the resulting binary (because 
; pointers are wider the resulting machine code is larger)

I then link this using the following:

:: Output as win32 object files - makes it possible to use -r with LD.
nasm -f win myfile.asm -o myfile.o
:: Link using LD - the -r flag prevents extra un-used code (e.g. __CTOR_LIST__) being generated - see the link in my original question text
ld myfile.o -Ttext 0x500 -s -r -o myfile.tmp
:: Use objdump to output as a flat binary - -j .text ensures that just the .text section is included which keeps the output file size down
objcopy -O binary -j .text myfile.tmp myfile

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文