【发布时间】:2011-01-18 23:36:46
【问题描述】:
是否存在 ASM 不够底层的情况?毕竟汇编器还是要组装的。有没有人用二进制写过程序?我只是想知道是否有理论上的理由表明这样做可能是实用的,或者即使在现代计算机上也是可能的。
【问题讨论】:
-
也许你应该向 Intel/AMD 的人提出这个问题。
标签: language-agnostic binary computer-science
是否存在 ASM 不够底层的情况?毕竟汇编器还是要组装的。有没有人用二进制写过程序?我只是想知道是否有理论上的理由表明这样做可能是实用的,或者即使在现代计算机上也是可能的。
【问题讨论】:
标签: language-agnostic binary computer-science
早在 1997 年,我在学校时曾在 TI-83 计算器上执行此操作,但无法使用链接电缆。
通常在那个时候,你只需编写一个汇编程序,使用 TASM 构建它,然后通过链接电缆将其传输到计算器。但是如果我很无聊,想把一些小东西放在一起,我已经记住了足够多的字节指令,以便能够为某些事情输入它们。
旁注当然,如果程序中存在错误,这很有趣,因为它很容易损坏整个计算器的 RAM。因此,您将不得不按住 ON 按钮和/或取出 AAA 电池,并希望这足以恢复计算(不包括内存中的任何程序)。否则要进行硬重置,您将不得不使用螺丝刀拧下特殊的备用电池。好时光……
【讨论】:
历史原因:您运行的机器需要在前面板上切换启动代码。 (是的,这已经完成了。通常在前几代机器中。)
不是你在寻找的现代原因:当你编写汇编程序时,你必须弄清楚这个过程。
【讨论】:
你知道了——如果没有 [dis]assembler 可用的话。我一直处于固件黑客攻击的情况,我花了足够的时间查看原始 PowerPC 指令流,以便能够识别和手动组装几种指令。 (我最终移植了一个反汇编程序:http://homepage.mac.com/potswa/source/DisDave.sit,如果你能设法安装它。)
有些 ISA 比其他的要简单得多。 RISC 遵循简单的格式,并且很容易定位自己,因为指令通常长度相同并且与字边界对齐。而 x86-64 则充满了变长编码和前缀码。
在FPGA项目或涉及自定义电路时,设计某种指令流并将其手动编码为二进制是很常见的。
【讨论】:
当您手动破解二进制格式时,就像 A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux 所做的那样。
【讨论】:
动态代码生成:
如果您要解决一个非常简单的问题,并且性能很重要,那么分析问题空间并动态生成一个专门的函数来解决问题通常是一个好主意。
一个实际示例:稀疏矩阵的高性能数学。
这通常涉及将数字数组相乘数千到数百万次。由于许多矩阵元素可能为零或一,因此如果删除所有琐碎的乘法,您可以节省大量时间。
为此,一个小的代码生成器可以分析矩阵并动态生成用于矩阵算术的机器代码。如何做到这一点可以从使用 JIT 库(或内置语言功能)到非常简单的方案。
对于稀疏矩阵乘法的情况,您只需将针对不同情况的预构建代码 sn-ps 粘合在一起即可获得出色的性能。这可以在 50 行 C 代码中完成。
【讨论】:
当我在海军服役期间(大约在 1986 年左右)接受训练时,我们有一台计算机,用于学习电子故障排除,而不是编程故障排除,它是通过在计算机前面输入二进制信息来编程的,我们必须根据结果以及硬件故障排除告诉教练他们在机器上发生了什么故障。据我所知,周围可能还有一台这样的机器。
我希望我能找到它的源代码,我实际上为机器编写了一个模拟器,并为机器编写了一个语言编译器。使用 1024 字节的内存可以完成多少工作,真是令人惊讶! :)
【讨论】:
【讨论】:
我记得读过 Woz 用机器语言编写了第一个 Apple BASIC(Apple I?Apple II?)。在他们拥有存储设备之前,您需要在监视器中输入十六进制代码。
【讨论】:
即使您发现自己跳过汇编程序并直接使用机器代码,您也不会使用二进制,而是使用十六进制。
在学校里,我不得不在没有汇编程序的情况下使用调试器修补内存中的代码。虽然很有趣,但这是一项除了嵌入式系统调试之外几乎没有任何价值的技能。
另外,考虑到汇编中使用的操作码助记符应该与实际操作码具有 1:1 的对应关系(因此称为“助记符”),因此您将无法通过手动敲出机器码来做任何事情不能在汇编中做。汇编器的作用是将助记符转换为操作码(还确定应使用特定指令的哪个版本——例如立即与间接 MOV)、将标签转换为地址以及类似的任务。
很高兴知道汇编器内部发生了什么,但这几乎永远不会出现,除非您正在寻找汇编器中的错误,破解嵌入式小工具或 MacGyvering 以摆脱非常非常奇怪的情况.
【讨论】:
在世界末日后的世界里,所有的键盘和显示器都被摧毁了,而将俄罗斯方块编程到计算机中的唯一方法是通过前面板上的切换开关,是的。
但是说真的,为什么会有人想做这样的事情呢?
编辑:显然有些人设计的处理器必须以二进制编程,直到他们可以在他们的处理器上运行汇编程序,但他们只是一小部分人。
【讨论】:
我的 8 位 Atari 没有任何汇编程序,所以我直接编写了机器代码。要从 BASIC 开始代码,您可以将代码编写为十进制数据字节或字符串。 (是的,您实际上可以在字符串中编写代码,您无法输入的 256 中唯一的字符代码是 155 - 用于返回的代码。幸运的是,没有具有该值的 6502 机器代码指令,所以它只是当分支恰好向后 101 个字节(-101 = 155)时出现问题。)
我还记得一段常见的启动计时器的代码:
104 (pla)
169, 7 (lda #7)
162, 6 (ldx #6)
160, 10 (ldy #10)
76, 92, 228 (jmp 0xE45C)
近年来,我参加了一些尺寸优化装配比赛。尽管大部分代码都是汇编代码,但您仍然必须确切地知道汇编器生成了哪些指令,以便知道它们有多少字节。此外,有时您会使用一些技巧,例如将某些字节用作数据和代码,或者将某些字节用作不同的指令,具体取决于您是输入第一个字节还是在指令中间输入。然后你把指令写成数据字节在汇编代码的中间。
【讨论】:
您有时会受益于使用原始机器代码,而不仅仅是汇编语言。例如,考虑通过电子邮件发送二进制文件,但使用不知道如何解码附件的电子邮件程序。有一次,一些人编写了可以解码附件其余部分的小程序,但程序中的所有内容都是可打印的字符。因此,您解码附件,将电子邮件正文保存为whatever.com,然后执行它。它会解码附件并编写一个二进制文件,然后你可以执行。
再举一个例子,几年前在 Fidonet 上遇到了一个相当简单的挑战:编写一个程序,它只打印出一个每次运行时递增的数字——但是(让它变得棘手的部分)它不允许使用任何外部文件或其他存储来完成这项工作。为了不让这变得太无聊,这也是一种代码高尔夫之类的事情,尽管测量的大小是可执行字节,而不是源代码。这个挑战的相当多的条目使用了自我修改代码,这些代码在很大程度上取决于指令的编码方式等等。
稍等片刻,我发现我仍然有我尝试的源代码:
.model tiny,c
.286
.code
.startup
main proc
mov si,offset count
inc byte ptr [si]
mov al, [si]
mov bx,4090h
shr al, 4
call convert
lodsb
and al,0fh
mov byte ptr end_convert, 08bh
convert:
add al,bl
daa
adc al,bh
daa
int 29h
end_convert:
ret
db 0d6h
; mov dx, si
mov ah,3ch
xor cx, cx
int 21h
xchg bx, ax
mov dx,offset main
mov cx,offset the_end - offset main
int 21h
ret
main endp
count:
db 0
name:
db 'c.com', 0
the_end:
end
我最好现在就辞职,在我对任何人中风发作负责之前(希望我不会太晚......)
【讨论】:
对于一个大学项目,我必须用 VHDL(一种硬件描述语言)设计一个简化的微控制器。为了测试它,我用二进制编写了一个非常简单的程序,因为这是将程序输入模拟微控制器的最方便的方法。
【讨论】:
过去从二进制文件到汇编程序来理解转储的情况并不少见。
但不使用汇编程序?我想不出任何理由。 Assembler 已经在对裸机进行编程。唯一的好处是为实际(二进制)指令启用诸如“add”之类的标签。等等
【讨论】:
好吧,如果您是芯片开发人员,您可以使用十六进制在 RAM 或 ROM 中编写一些基本的引导加载指令,而不是使用汇编程序。我已经为我写的软核这样做了。
实际上,在你完成之后,下一步就是用 Perl 或其他东西编写一个基本的汇编程序。
【讨论】:
如果您正在创建解释器。也许你已经完成了解释器,但没有完成解析器。您可以通过用纯二进制编写要解释的程序来测试解释器。
【讨论】:
新团队成员的欺凌仪式。
【讨论】:
一个非常酷的例子是这个著名的多语言,它是一个有效的 DOS .COM 文件,因为它的源代码中的 ASCII 兼作二进制 x86 指令! http://ideology.com.au/polyglot/polyglot.txt
更多无聊的例子...
许多处理器将 ISA 指令实现为更原始的微指令序列(基本上是数据路径控制信号的集合),这些微指令在微码 ROM 中“微编码”。
对于足够简单的处理器,您可以直接以二进制形式编写微代码,而不是从助记语言汇编它。或者,如果您正在对处理器进行逆向工程,您可能不知道它的微指令集,而只需要猜测微指令的格式……在这种情况下,您可能也在使用二进制文件。无论哪种方式,这都比汇编语言级别低。
有时,6502 等旧处理器的代码使用未记录的指令,这些指令没有官方助记符,因此您必须编写二进制值而不是汇编指令。
【讨论】: