2

只是想知道汇编世界是如何工作的,我正在阅读wiki上的汇编语言,这句话让我印象深刻:

它实现了对特定 CPU 架构进行编程所需的数字机器代码和其他常量的符号表示。

我一直认为汇编是基于您的 CPU 的固定语言(基于所述 CPU 具有不同的编译器和语言),因此对于您的 CPU,您只能使用这种类型的汇编与您的硬件对话。

但是基于该引用,可能有其他语言使用其他符号来表示相同的数字机器代码。

那么,是否有任何其他语言可以直接与非汇编硬件对话?还是我弄错了?

4

10 回答 10

8

可以使用一组不同的符号来表示机器代码。但是没有人打扰,因为你不会得到太多。

ARM 有一条指令叫做 ADD。在 ARM 汇编器中,“ADD r0, r0, #1”表示 4 字节的机器码,它们构成了增加寄存器 0 的指令。

无论您如何称呼该指令,您都无法更改可用的指令集并仍将其称为 ARM 汇编程序。无论您将 ADD 操作称为“ADD”、“SUM”、“PLUS”还是“ADDITION”,它本质上仍然是相同的编程语言。如果每个人对所有内容都使用相同的名称,那么使用现有的引用会更容易,所以会发生这种情况。

一个有用的更改可能是将指令表示为“INC r0”,因为 ARM 没有 INC 指令,它是一种常见操作。这导致了汇编语言中的宏。这些确实确实改变了语言,但是一旦您拥有发出多个 ARM 指令的宏,您就会开始失去汇编的所见即所得性质。最终你开始认为也许你还不如只写 C。我是根据经验说话的(它不是 ARM,但它是一个宏化的汇编程序)。

一个常见的区别是大小写——如果你觉得自己很迂腐,你可以争辩说有两种不同版本的 ARM 汇编语言,一种是大写的,一种是小写的(或者争辩说存在一种语言,同一事物有多个符号) . 同一机器代码的不同反汇编程序有时会输出不同的格式。有时这些差异很大,以至于特定的汇编器无法处理所有这些,或者汇编器会提供自己的便利,而这些便利与同一平台上的另一个汇编器不兼容。但实际上,这都是一回事,如果你费心去区分,那通常是因为你被咬了屁股,而不是因为有好事发生……

于 2009-03-24T11:43:31.437 回答
4

您弄错了(或者可能是正确的-很难从您的问题中分辨出来)。汇编语言是用于特定 CP 架构的二进制指令模式的符号(易于人类阅读)表示。偶尔会遇到对“portabe assembler”(Scott Nudds,有人知道吗?)的引用,但这些实际上是更高级别的语言。

于 2009-03-24T11:20:48.483 回答
3

这是来自Clozure Common Lisp的示例。它允许在 Lisp 中编写内联汇编代码。下面定义了一个用 x86 汇编符号编写的函数 %safe-get-ptr:

(defx86lapfunction %safe-get-ptr ((src arg_y) (dest arg_z))
  (check-nargs 2)
  (save-simple-frame)
  (macptr-ptr src imm0)
  (leaq (@ (:^ done) (% fn)) (% ra0))
  (movq (% imm0) (@ (% :rcontext) x8664::tcr.safe-ref-address))
  (movq (@ (% imm0)) (% imm0))
  (jmp done)
  (:tra done)
  (recover-fn-from-rip)
  (movq ($ 0) (@ (% :rcontext) x8664::tcr.safe-ref-address))
  (movq (% imm0) (@ x8664::macptr.address (% dest)))
  (restore-simple-frame)
  (single-value-return))

它仍然是组装。除此之外,还有许多语言具有从内存或寄存器等设置/读取值的低级结构。

CPU 不执行汇编语言。汇编语言只是特定 CPU 机器代码的一些(或多或少直接的)文本表示。

于 2009-03-24T12:25:05.737 回答
2

汇编语言与目标系统的硬件架构密切相关。

在很大程度上,从 asm 代码到机器指令存在一对一的映射——这才是真正的重点——因此您可以在单个指令的级别上操作硬件。

它们还允许您以与机器内存架构(单体、分段、虚拟等)相匹配的方式访问和操作内存。

汇编程序差异很大,有些只是将三个字母代码翻译成 4 字节指令,而另一些,如古老的 OS/390 汇编语言本身就是复杂的编程环境。

话虽如此,所有这些最现代的芯片都在模拟古老的指令集,所以无论如何你实际上并没有那么接近线路,而且,更好的 C 编译器知道底层的微架构(比如管道,执行了多少整数指令每个周期等),所以一个好的 C 编译器几乎总是会执行平庸的汇编代码!

于 2009-03-24T11:25:40.780 回答
2

澄清有关 Burroughs B5000 和 B6000 系列机器的一些答案,没有汇编程序,因此没有汇编语言编程。也完全没有链接加载器。单程 Algol 编译器(由 Donald Knuth 编写)直接生成机器代码。硬件参考手册描述了使用汇编程序员可以识别的助记符的指令,但这是我们最接近它的。

您可以要求 Algol 编译器在编译期间将生成的代码与源代码内联打印。

主控制程序的叙述性描述很好地描述了堆栈架构和主要指令。

于 2020-06-10T13:29:16.240 回答
1

大量使用与 C 混合的程序集。一些 CPU(如 8052 芯片)带有在 ROM 中刻录的高级语言。这些语言具有允许在低级别与硬件交互的特殊语句。

CPU 系列通常设计为使用相同的机器代码,这意味着相同的汇编语言。一个特定的 CPU 可能有更多的缓存、管道等,但除此之外可以运行与同一系列中的其他 CPU 相同的机器代码。

因此编译到一个 CPU 上的软件将在所有这些 CPU 上运行。最受欢迎的指令集之一是 i386 指令集,它几乎为所有 Windows 机器提供动力。有一个 16 位的前任和一个 64 位的后继。

于 2009-03-24T11:21:31.630 回答
1

...因此,对于您的 CPU,您只能使用这种类型的程序集与您的硬件通信。

所有语言最终都会转换为在真实硬件上执行的指令,无论是像汇编程序一样直接完成,还是像 C 那样通过高级抽象完成。棘手的一点实际上是让机器指令以如下方式操作硬件:您想要,因为高级语言的一点是使您免受硬件细节的影响。

某些语言(例如 C)旨在直接操作硬件,因此它们包含诸如 volatile 之类的关键字,以防止编译器以其他方式优化对设备寄存器的引用。这些可以被写入而不是读回,以便编译器认为保存的值永远不会再次使用。或者可能需要读取设备寄存器,尽管该值从未使用过。对于诸如启用和禁用普通程序不会产生的中断之类的操作,还有杂项指令。

这可能还需要链接器支持,以便内存位置(用于内存映射 I/O)可以位于设备寄存器的正确地址。然而,一些处理器对 I/O 使用不同的指令,并且必须有一些工具可以将它们插入到代码流中,因此在许多情况下,除非有明确的语言支持,否则可能无法访问 H/W。

最后,对于大多数现代操作系统,如 Windows 和 Linux,应用程序在虚拟内存中运行,其中程序地址与物理地址不匹配,并且程序通常被拒绝访问硬件。当操作系统未授予其特定权限时尝试访问硬件的代码将生成中断,返回操作系统并不再执行。

于 2009-03-24T12:20:23.627 回答
1

当然,有很多语言直接与非汇编硬件对话。例如,在 Burroughs B5000 上,CPU 使用 ALGOL 的变体进行编程,在 Lisp 机器上,CPU 直接执行 Lisp 代码,在早期的 Smalltalk 工作站上,CPU 直接执行 Smalltalk 字节码。研究人员已经基于直接执行 Lambda 演算的图形缩减引擎构建了 CPU。构建 Java 处理器的公司不止一家,它们当然是用 JVM 字节码编程的。

于 2009-03-24T21:35:56.163 回答
1

是的,它叫 FORTH,只要你把硬件看成是虚拟的!FORTH 堆栈机器的原始寄存器操作的机器代码是 FORTH。但如果你模拟这个硬件,也许它很重要?看看http://www.greenarraychips.com/了解 Leo Brodie 1984 年“Thinking Forth”中的前沿和经典,它可能对您有所帮助……即使您从未使用过 Forth。

于 2020-08-25T02:48:48.040 回答
0

你的问题是:

那么,是否有任何其他语言可以直接与非汇编硬件对话?还是我弄错了?

我很惊讶没有人提到Register Transfer Language或任何硬件描述语言,例如VerilogVHDL

RTL本身不是一种编程语言,通常是硬件中立的(汇编绝对不是中立的,它针对特定的架构)。

VHDL 和 Verilog 最常用于可编程逻辑,我认为这可以称为“直接与硬件对话”。软核通常以可编程逻辑实现,因此您可以使用其中之一来实现(例如)ARM 处理器,该处理器本身可以在汇编中进行编程......

有趣的东西……让我希望我能回去重新做我所有的 EE/CE 工作……

于 2009-03-24T17:29:54.693 回答