【问题标题】:Closer-to-the-metal alternative assembler syntax for x86?x86 的更接近金属的替代汇编语法?
【发布时间】:2016-04-29 20:10:10
【问题描述】:

我正在尝试编写一个小型 8086+ 汇编程序,可能只是实模式,并且可以满足大部分可能的指令。

x86 指令很复杂,需要复杂的表解决方案,这很好,但我想要更小/更简单的东西。

我的一个想法是从操作码开始,制作一组与实际机器指令更密切相关的助记符/寻址模式/寄存器。

这已经完成了吗?我在哪里可以阅读到它?我的直觉告诉我这一定是已经这样做了,但是我在网上找不到任何东西。

我已经研究过的事情:

  • AT&T语法:不能解决问题,还是需要复杂的 查表;最后和Intel语法基本一致。

  • CRASM512.ASM:一个很酷的 512 字节特技汇编程序。非常令人印象深刻,但是 不可用(并且不应该)。语法仍然基于 英特尔也是。

  • 仅使用“同质编码”指令的一个子集。这是 我目前正在尝试什么,并使用一个更小、更简单的表 驱动方法比成熟的 x86 汇编器。

    问题是我仍然需要检查无效指令,而且 x86 足够复杂,我只能使表驱动方法 简单一点,不简单。所以它是复杂度的 90% 结果的 10%,因为与实际交易相比,变化的主要是表格。

【问题讨论】:

  • 8086 汇编器与大多数平台(和其他语言)相比很容易,那么您这样做的目标是什么?如果您只是想了解如何操作,那么我建议您构建一个 8086 汇编器的简化子集,然后继续扩展其功能,直到您拥有完整的 8086 汇编器。我能够用大约 1000 行 Python(大约 2008 年)编写一个 PIC16F 汇编器,并用大约 2500 行 C 语言(大约 2001 年)编写一个 80286 汇编器,所以这些都不大。您是否尝试在 8086 汇编器中实现此功能?即便如此,如果你把代码组织得很好,它应该是相当简单的。
  • 是的,常规的 x86 汇编器是直接的(使用表驱动的方法),但已经完成了。我想让我的更小,同时仍然可用/有用,所以我正在寻找任何可以削减的角落。无论如何,看看 x86 指令与助记符,关于替代助记符集(等)的问题只是被问到了。
  • 好的,所以你想更接近金属而不是......装配工?你知道它是裸机,对吧?它是数字指令编码的表示,它尽可能接近。也许您希望能够表示的示例有助于澄清这一点?
  • 您的实际问题是什么?
  • 没有表查找的汇编语言是机器语言。您至少需要在表格中查找指令助记符才能找到它们的操作码。

标签: assembly x86


【解决方案1】:

是一个大大简化的架构 (for teaching purposes),但实现了您的一个想法:与其拥有无数不同形式的 mov 来做根本不同的事情,它具有不同的助记符它支持三种不同的mov-like 操作码:

  • irmovl V, %rB: 立即 -> reg
  • rmmovl %rA, D(%rB): reg -> 内存(存储)
  • mrmovl D(%rB), %rA: 内存 -> reg (load)

这是 y86 的 AT&T 语法风格,其中目的地位于第二位。 AT&T 语法使用%$ 装饰来避免reg 名称和符号之间的混淆。 IDK 如果这会使解析器变小或变大。


将此想法应用到 x86,您可以对同一指令的不同形式使用不同的助记符。

如果您更关心易于解析而不是人类可读性以及与现有 asm 语法的相似性,那么您总是可以在 mod/rm 字节中按编码顺序列出操作数。例如

addbir  al, 5    ; b = byte, i = immediate, r = register.  opcode 80 /0 with al encoded in the mod/rm byte, imm8
addbia  al, 5    ; a = ax/al:  opcode 04 imm8

; w=word, m=memory
addwrm  cx, 0, bx,    ; add cx, [0 + bx + (no index)]   encoding: 03 mod/rm
addwmr  cx, 0, , si   ; add [0 + (no base) + si], cx   encoding: 01 mod/rm

注意最后两行:第一个操作数始终是 mod/rm 字节中的“r”,而不是目标。它是指令编码的一种文本表示,而不是人类可用的语法。我想这就是你的目标吗?

根据您希望汇编器的智能程度,您可以让它在 imm8 和 imm16 形式的立即指令之间进行选择。对于 disp8、disp16 或无位移内存编码,需要 0 而不是空条目可能更容易。


通常每个人都想要一个为您选择最佳编码的智能汇编器(例如,使用不使用 mod/rm 字节的 EAX 特定操作码)。尤其是对于 x86-64,在不需要时避免使用 REX 前缀,或者将 mov rax, 0x1234 优化为 mov eax, 0x1234,都很好。

对于加载和 mov-immediate 使用不同的助记符肯定是有价值的,因为那是 common source of confusion for asm beginners。 (尤其是因为 MASM 和 NASM 语法在 mov reg, symbol 的含义上有所不同)。

【讨论】:

  • 这正是我一直在想的,我想我得花一些时间在指令编码中寻找模式并找出一些聪明的东西。 y86 似乎是一个很好的资源,以前从未听说过,谢谢!
  • @JonathanJ.Bloggs:y86 过于简单化,除了婴儿步骤介绍到 asm 类的玩具示例。它甚至没有乘法、除法甚至移位指令(add same,same 左移除外),所以很多事情都无法有效地实现。它的某些版本有cmovso you can at least emulate setcc。它只有add、sub、and、xor,没有无符号分支条件(只有有符号)。
  • 两周过去了,不知道该不该接受你的回答;您的回答虽然有帮助,但主要说明了我已经想到的事情(并且问题中隐含了这些事情)。这就是为什么我还没有将您的答案标记为“已接受”的原因。不过还是谢谢!我只是简单地浏览了 y86 文档,现在我知道你是对的,它太基础了。
  • @JonathanJ.Bloggs:没关系。如果您最终没有使用我的想法来使用每种编码都不同的助记符,那么它并没有真正回答您的问题,因此您不应将其标记为已接受。现有的 x86 的 asm 方言不做的一件事是提供一种方法(除了db 指令)来反汇编成可以组装回完全相同字节的东西,而不仅仅是(通常)运行相同的东西.这就是我要设计的地方,因为这是一个潜在有用的东西。
  • 关于精确的可重新组装性非常好,你会认为一些聪明人现在已经想到了这一点并完成了工作。比如,呃,英特尔的某个人 :)
猜你喜欢
  • 1970-01-01
  • 2011-10-27
  • 2011-02-08
  • 2017-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 2017-10-20
相关资源
最近更新 更多