47

我想知道如何仅通过使用十六进制编辑器来编写像 Hello World 程序这样简单的东西。我知道我可以在接近机器级别使用汇编程序和汇编语言来实现这一点,但我只想尝试在 Hello World 等玩具示例中真正编写机器代码。

这可能是一个简单的 DOS .COM 文件,我可以在 DOSBox 上运行。但是,如果有人可以提供一个 .EXE 文件的示例,以便直接在我的 Windows PC 上运行它,那就太好了。

这只是纯粹的好奇。不...我不打算直接用二进制机器代码编写程序(我什至不经常编写汇编代码,我大多数时候只是使用 C/C++ 作为我最底层的工具)。我只是想看看是否有可能做到这一点,因为可能有人在计算机的早期就必须这样做。

PS:我知道关于这个主题有类似的问题,但没有一个提供有效的例子。我只想要一个简单的例子,这样它就可以帮助我理解编译器和汇编器是如何生成可执行文件的。我的意思是......过去必须有人为第一个程序手动完成此操作。此外,对于 Windows EXE 格式,肯定有人在 Microsoft 编写了第一个工具来生成格式以及 Windows 本身读取并执行它的方式。

4

6 回答 6

20

corkami/wiki/PE101上有一个非常简约但功能齐全的(在 Win7 上也是)exe ,它的每个字节都在漂亮的图形中进行了解释。您可以在十六进制编辑器中手动输入所有内容,但填充可能会使这有点乏味。

至于历史,是的,微软的某个人发明了 exe 格式(旧的 DOS MZ exe 格式),他(或微软的其他人)为它编写了一个加载器和一个链接器,这是传统上将输出转换为编译器(“目标文件”)转换成可执行文件。有可能(甚至可能,我会说)第一个 exe 程序是手工编写的,毕竟它们只是为了测试新的加载程序。

后来,AT&T 的 COFF 格式被 Microsoft 扩展为 PE 格式,它仍然具有 MZ 标头,并且通常(但可选,它不在 corkami 示例中,它实际上可以是任何东西)包含一个用于打印消息的小型 DOS 程序“此程序不能在 DOS 模式下运行”。

于 2012-07-31T16:08:08.103 回答
8

1) .com 文件是最简单的开始位置,将在 dosbox 上运行,基本上程序从文件中的偏移量 0x100 开始,我认为第一个 0x100 可以是任何东西,不记得了

2)虽然第一个程序通常是手动编写和组装成机器代码的,但我们正在谈论当您将两个数字相加时将它们保存在内存中并且很高兴您可以休息一天。将内容打印到视频卡的“hello world”程序要复杂得多。现在你可以使用dos系统调用做一个非常简单的,也许这不是你感兴趣的,也许是。

3)基于 2,在 1960 年代或 1970 年代,任何比一次测试一条或几条指令更复杂的东西,即使在编写手工组装程序时,您也可以手动在汇编器中编写程序,然后将其组装成机器代码,然后加载它。基本上首先学习汇编语言,然后学习如何为其生成机器代码,然后开始将这些字节输入十六进制编辑器。现在不是 1960 年代,除非你享受过度的痛苦,通过写 asm 来学习上面的内容,使用汇编程序生成机器码,然后使用反汇编程序对其进行反汇编,并将汇编语言和机器码并排检查以显着提高您获得一个工作程序所需的时间。如果你在有操作系统和指令集之前为一家芯片公司工作,您仍然可以利用团队的其他成员、芯片设计人员等来了解如何制作和安排机器代码。您不会仅凭高水平的语言经验就可以完成这一切,并希望成功。

4) x86 是一个可怕的指令集,如果你不懂汇编,我强烈建议你不要先学习它。拥有 x86 是我听到的最糟糕的借口,首先要学习 x86。你已经提到过dosbox,所以已经计划模拟/模拟,所以使用一个好的指令集并模拟它或购买硬件(低于50美元甚至低于20美元都会给你买一块具有更好指令集的板)。如果您选择购买一些,我建议先进行模拟/仿真并与硬件并行。如果您真的想要教育,编写自己的模拟器一点也不难。也许发明你自己的指令集。

5)这些都不能帮助您理解编译器的作用。了解汇编语言然后反汇编编译器输出是您获得该知识的最佳途径,不涉及机器代码,无需实际运行程序。编译器从高级语言转到低级语言(例如 C 到 asm 或 C++ 到 asm)。然后了解汇编程序的作用,由于历史和其他原因,有许多不同的解决方案。今天的典型解决方案是单独的编译器、汇编器和链接器(除非您告诉它不要,否则编译器会为您调用汇编器和链接器,这三个步骤是隐藏的,实际上编译过程可能不止一个程序运行以完成该任务)。输出二进制文件的汇编器必须解析整个程序,输出到对象的汇编器将在机器代码中留下漏洞供链接器填充。诸如分支或调用另一个对象中的项目之类的事情,在链接器将内容放入二进制文件并知道间距/寻址之前,它无法编码。还访问存在于其他对象中的变量。

您可能看不到有关十六进制编辑程序的实际示例,因为首先这是一个如此广泛的问题,没有简单的答案(什么操作系统,系统,什么系统调用或您正在创建这些,什么文件格式,什么十六进制编辑器等)。也因为它是一个高层次的问题和问题,真正的问题是我在哪里学习汇编,我在哪里学习汇编和机器代码之间的关系,我在哪里学习系统调用(这不是汇编问题,他们与学习 asm 无关,您学习汇编语言本身,然后如果您不能直接使用高级语言执行系统调用,则学习将其用作执行系统调用的工具),我在哪里了解可执行文件格式,例如 .com, .exe、coff、elf等。什么是好的或容易的或一些形容词,在 xyz 操作系统或环境上运行的十六进制编辑器。分别提出这些问题,您将找到答案和示例,一旦您有了这些答案,您将知道如何使用十六进制编辑器输入机器代码来制作程序。一个较短的示例是,当您看到 SO 上发布的程序的反汇编时,您正在看到完整程序的十六进制示例,其中一些是以十六进制显示的完整程序。如果您知道文件格式,您只需将这些内容输入十六进制编辑器即可。其中一些是以十六进制显示的完整程序。如果您知道文件格式,您只需将这些内容输入十六进制编辑器即可。其中一些是以十六进制显示的完整程序。如果您知道文件格式,您只需将这些内容输入十六进制编辑器即可。

于 2012-08-04T05:25:04.170 回答
5

我手工制作二进制文件,但我认为汇编本身比纯十六进制编辑器更容易,因为更新任何东西都会很困难。

  • 最简单的肯定是 DOS COM 格式,你甚至可以在 notepad 中输入,或者至少,即使是普通的Hello World也很容易。

  • EXE(非 DOS 格式)也不需要太多,请参见此处

  • 如果你想制作一个 PE,你可以制作一个TinyPE

大多数二进制文件应以PEEXE 和 COM的形式提供。

于 2012-09-01T15:21:45.037 回答
4

没有发现,但本教程应该让您更好地了解汇编如何映射到机器代码(x86 ELF):http ://timelessname.com/elfbin/ (特别是查看页面的下半部分)

这个页面是关于我尝试创建最小的 x86 ELF 二进制文件的尝试,该二进制文件将在 Ubuntu Linux 上执行 Hello World 我的第一次尝试从 C 开始,然后进展到 x86 汇编,最后到 hexeditor。

分析像这样的非常小的可执行文件非常棒,因为程序集和机器代码之间的映射将更容易发现。这也是一篇关于该主题的非常有趣的文章(虽然与您的问题不完全相关):http ://www.phreedom.org/research/tinype/ (x86 PE)

于 2012-07-31T15:37:03.540 回答
3

我写了一篇关于在命令提示符下使用 ECHO 创建可执行 DOS 二进制文件的文章。无需其他 3rd 方 HEX 实用程序或 x86 IDE!

该技术使用键盘组合 - ALT ASCII 代码,将 OPCODES 转换为在 MSDOS 下直接可读的二进制格式。输出是一个完全可运行的二进制 *.com 文件。

http://colinord.blogspot.co.uk/2015/02/extreme-programming-hand-coded.html

摘录: 在 DOS 提示符下键入以下键命令,记​​住按住左 ALT。

c:\>Echo LALT-178 LALT-36 LALT-180 LALT-2 LALT-205 LALT-33 LALT-205 LALT-32 > $.com

上面的代码实际上是描述 X86 汇编程序以在屏幕上打印美元符号的操作码值。

完成后,您的提示应如下所示。按回车构建!

c:\>Echo ▓$┤☻═!═  > $.com

运行文件“$.com”,您将看到屏幕上显示一个美元 ($) 字符。

c:\>$.com
$
c:\> 

恭喜!您刚刚创建了名为 $.com 的第一手编码可执行文件。

于 2015-02-05T11:21:47.940 回答
2

您可以进行反汇编并尝试找出您在汇编器中使用的操作码的机器码

例如

org 0x100
mov dx,msg
mov ah,0x09
int 0x21
ret
msg db 'hello$'

使用 nasm -fbin ./a.asm -o ./a.com 编译具有 ndisasm a.com 提供以下反汇编:

00000000  BA0801            mov dx,0x108
00000003  B409              mov ah,0x9
00000005  CD21              int 0x21
00000007  C3                ret
00000008  68656C            push word 0x6c65
0000000B  6C                insb
0000000C  6F                outsw
0000000D  24                db 0x24

00000000 to 00000007 are the instructions

所以您可以使用 ba0801 机器代码,使用一些十六进制编辑器,尝试将其更改为 ba0901,并且只会打印“hello”,您可以使用十六进制编辑器并使用 NOP 填充内容,即机器中的 0x90代码,例如:

00000000:  ba 50 01 90 90 90 90 90  90 90 90 90 90 90 90 90  .@..............
00000010:  b4 09 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000020:  cd 21 90 90 90 90 90 90  90 90 90 90 90 90 90 90  .!..............
00000030:  c3 90 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000040:  71 77 65 72 74 79 75 69  61 73 64 66 67 68 6a 24  qwertyuiasdfghj$
00000050:  61 73 64 66 67 68 6a 6b  61 73 64 66 67 68 6a 24  asdfghjkasdfghj$
00000060:  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --  ----------------

如果你用扩展名 .com 保存它,你可以在 DosBox 中运行它

于 2014-09-27T19:27:39.357 回答