如果不是,它们有何不同,它们的关系是什么?
谢谢并恭祝安康!
我想每个人都会给你相同的答案。指令集是处理器可以执行或理解的所有指令的集合(在数学中)。汇编语言是一种编程语言。
让我根据您提出的一些问题尝试一些示例。我将使用我手头的任何代码从一个处理器跳到另一个处理器。
指令或操作码或二进制或机器语言,无论您想使用什么术语来表示加载到处理器中以进行解码和执行的位/字节。一个例子
0x5C0B
汇编语言将是
add r12,r11
对于这个特定的处理器。在这种情况下,这意味着 r11 = r11 + r12。所以我把那个文本,添加 r12,r11 放在一个文本文件中,并使用一个汇编器(一个编译/汇编汇编语言的程序)将它汇编成某种形式的二进制文件。像任何编程语言一样,有时您创建目标文件然后将它们链接在一起,有时您可以直接进入二进制文件。并且有许多形式的二进制文件,它们是 ascii 和二进制形式,还有很多其他的讨论。
现在你可以在汇编程序中做什么而不是指令集的一部分?它们有何不同?对于初学者来说,你可以有宏:
.macro add3 arg1, arg2, arg3
add \arg1,\arg3
add \arg2,\arg3
.endm
.text
add3 r10,r11,r12
宏就像内联函数,它们不是被调用的函数,而是在行中生成代码。例如,与 C 宏没有什么不同。因此,您可以使用它们来节省一些输入,或者您可以使用它们来抽象您想要一遍又一遍地做的事情,并希望能够在一个地方进行更改,而不必触及每个实例。上面的例子本质上产生了这个:
add r10,r12
add r11,r12
指令集和汇编语言之间的另一个区别是伪指令,例如,对于这个特定的指令集,没有弹出指令用于从堆栈中弹出东西,至少不是那个名称,我将解释原因。但是您可以保存一些输入并在代码中使用弹出:
pop r12
没有弹出的原因是寻址模式足够灵活,可以从源寄存器中的地址读取,将值放入目标寄存器,并将源寄存器增加一个字。该指令集的汇编程序是
mov @r1+,r12
pop 和 mov 都导致操作码 0x413C。
指令集和汇编程序之间的另一个差异示例,切换指令集,是这样的:
ldr r0,=bob
对于这种汇编语言来说,这意味着将 bob 的地址加载到寄存器 0 中,没有相关指令,汇编器对它的作用是生成一些看起来像这样的东西,如果你要在汇编器中手动编写它:
ldr r0,ZZ123
...
ZZ123: .word bob
本质上,在从该指令可到达的地方,而不是在执行路径中,创建了一个字,链接器将用 bob 的地址填充该字。汇编器或链接器的 ldr 指令也将使用 pc 相关指令的 ldr 进行编码。
这导致了指令集和汇编语言之间的一整类差异
call fun
机器代码无法知道什么是乐趣或在哪里可以找到它。对于这个具有多种寻址模式的指令集(请注意,我特意并有意避免命名我正在使用的指令集,因为这与讨论无关)可能是汇编器或链接器(取决于 fun 函数在哪里结束相对于本指令)。
汇编器可以选择将该指令编码为相对于 pc 的指令,如果 fun 函数比 call 指令提前 40 个字节,它可以使用相当于 call pc+36 的方式对其进行编码(取消四个,因为 pc 在执行时是前一个指令这是一个 4 字节的指令)。
或者汇编器可能不知道在哪里或有什么乐趣,并将其留给链接器,在这种情况下,链接器可能会将函数的绝对地址放在类似于调用 #0xD00D 的位置。
加载和存储也是如此,一些指令集具有远近 pc 相对地址,有些具有绝对地址等。你可能不关心选择,你可能只是说
mov bob,r1
汇编器或链接器或两者的组合负责其余的工作。
请注意,对于某些指令集,汇编器和链接器可能在一个程序中同时发生。现在我们已经习惯了编译成对象然后链接对象的模型,但并不是所有的汇编程序都遵循这个模型。
汇编语言可以采取一些捷径的更多情况:
hang: b hang
b .
b 2f
1:
b 1b
b 1f
1:
b 1b
2:
hang: b hang 有意义,分支到名为 hang 的标签。本质上是自我的一个分支。顾名思义,这是一个无限循环。但是对于这种汇编语言 b 。意味着分支到自我,一个无限循环,但我不必发明一个标签,输入它并分支到它。另一个快捷方式是使用数字 b 1b 表示返回到 1,汇编器在指令后面或上面查找标签号 1。b 1f 不是到 self 的分支,表示向前分支 1,这是该汇编程序完全有效的代码。它将向前或在代码行下方寻找标签编号 1:并且您可以在此汇编程序的汇编语言程序中疯狂地重复使用编号 1,而不必为简单的短分支发明标签名称。第二个 b 1b 分支到第二个 1. 并且是自我的分支。
重要的是要了解创建处理器的公司定义了指令集,机器代码或操作码或他们或您用于处理器解码和执行的位和字节的任何术语。很多时候,该公司会为这些指令生成带有汇编语言的文档,即语法。该公司通常会生成一个汇编程序来编译/汇编该汇编语言……使用该语法。但这并不意味着地球上选择为该指令集编写汇编程序的任何其他人都必须使用该语法。这对于 x86 指令集非常明显。同样,任何伪指令(如上面的 pop 或宏语法或其他捷径(如 b 1b)都必须从一个汇编程序到另一个汇编程序)。很多时候不是,你在 ARM 上看到了这个,例如 ; 的通用注释符号。不适用于 gnu 汇编器,您必须使用 @ 代替。ARMs 汇编器确实使用 ; (注意我用 ;@ 编写我的 arm 汇编器以使其可移植)。使用 gnu 工具会变得更糟,例如,您可以将 C 语言的内容(如 #define 和 /* comment */)放入您的汇编器中,并使用 C 编译器而不是汇编器,这样就可以工作了。我更喜欢尽可能保持纯粹以实现最大的可移植性,但您自然可以选择使用该工具提供的任何功能。使用 gnu 工具会变得更糟,例如,您可以将 C 语言的内容(如 #define 和 /* comment */)放入您的汇编器中,并使用 C 编译器而不是汇编器,这样就可以工作了。我更喜欢尽可能保持纯粹以实现最大的可移植性,但您自然可以选择使用该工具提供的任何功能。使用 gnu 工具会变得更糟,例如,您可以将 C 语言的内容(如 #define 和 /* comment */)放入汇编器中,并使用 C 编译器而不是汇编器,这样就可以工作了。我更喜欢尽可能保持纯粹以实现最大的可移植性,但您自然可以选择使用该工具提供的任何功能。
汇编语言将包含指令的助记符,但通常会添加更多内容,例如:
编辑:一条指令(本身)将以二进制编码,供 CPU 读取。助记符是指令的名称。例如,在汇编语言中,我可能会写“mov ax, 1”。相应的指令将(在 x86 的情况下)编码为 B8 00000001(十六进制)。
定义数据、宏、函数名称等不是实际的指令。宏(很像 C 中的宏等)允许您在汇编过程中定义名称。它可能(通常会)导致生成一些指令,但这些指令与宏定义本身是分开的。就像在 C 中一样,当您定义一些数据时,这些数据通常会导致目标文件中的记录为名称 X 指定一定量的空间,但不会直接生成任何指令。
汇编语言不仅仅是指令集的超集:它是一种生成目标文件、符号、调试信息、链接的方式,并且即使在这个级别也有一些最小的结构化编程。(有点建立在其他答案/评论的基础上)
大多数 C 编译器生成程序集,然后将其传递给汇编器以创建目标文件。如果您在使用标志“-S”运行时查看 gcc 的输出,您会看到上面的大部分内容都在使用。如果你打开了调试('-g')和任何动态链接(这些天默认),你会看到大量的程序集不仅仅用于指令。
计算机(更准确地说是处理器)只能进行计算,即执行算术和逻辑运算。
单个算术或逻辑操作称为指令。
所有指令的集合称为该计算机(更准确地说是处理器)的指令集。
指令集要么硬连线在处理器中,要么使用称为微码的技术实现。
计算机只能被编程,如果它有一种语言,即它可以理解的东西。二进制代码不是计算机的语言。基于二进制代码的指令集是计算机的语言。
语言不过是纸上的规范。第一种在纸上设计的语言是机器语言。它在计算机中的实现只能通过硬件(或最新的技术微码)实现。该实现称为指令集。所有其他语言都将在机器语言之上设计。
机器语言很难使用,因为我们在日常生活中主要使用字母表。因此,决定在机器语言之上引入一种称为汇编语言的助记语言。汇编语言的实现被命名为Assembler。
[您可能想知道第一个汇编程序是如何编写的。第一个汇编程序可以用机器语言编写,也可以不用机器语言编写。为了简单起见,我没有在这里提到引导的概念]
概括:
汇编语言由汇编程序转换为指令集。两者都是硬币的不同面,它们之间有一层抽象或助记符。机器语言是处理器指令集的“位编码”。汇编语言是处理器指令集的“符号编码”。
当您查看您在问题中链接到的关于汇编语言的维基百科文章时,下面有一个示例显示了汇编语言说明和相应的目标代码。两者都是同一事物的不同表示:来自处理器指令集的指令。但只有标题为“指令(AT&T 语法)”的列包含汇编语言。
希望这能让它更清楚。
一切都在分层架构中,具有“严格(大部分时间)和定义良好的接口”。
从硬件开始
在您到达处理器之前,有很多层。
层我的意思是我们从“物理->设备(电子)->模拟(放大器)->门->数字电路->微架构->架构(ISA,处理器)开始
称为 ISA(指令集架构)的软件部分
它具有受人尊敬的处理器可以支持的所有指令。这意味着 ISA 只绑定到一个处理器(像 x86 这样的硬件)。
重要的是为什么需要这个 ISA?就像我之前所说的那样,它是严格且定义良好的接口。处理器无法运行任何超出 ISA 的指令[严格]
但是任何想要使用这个处理器的人都可以使用 ISA 的这些命令来完成他的工作。 [定义良好的接口]
现在来到Assembly,C,Assembler,Compiler ....
分层架构你知道我们在硬件中使用它(分层拱门)为你实现一个处理器
您可以阅读更多关于为什么使用这种分层架构的信息。一步一步地处理一个大问题很容易。
我们想要什么?我们的目标是什么?
我们希望用户可以轻松使用该处理器。这里用户是程序员。
现在看看程序员的难度。
程序员能否记住所有二进制格式的处理器指令。并且处理器可能会在下一个应用程序中从 Intel 更改为 IBM(现在不是特定版本)。
汇编器也是它所拥有的一个层——两个接口。与编译器相同。
例如:您用 C 编写代码。处理器无法理解此代码。它理解以二进制格式编写并由 ISA 中给出的指令定义的任何内容。但是在ISA指令中编写(维护|修改)程序很困难。
1)所以用户用C写了一段代码。这段代码是C编译器可以理解的。因为用户仅限于使用 C 中给出的语法。这意味着 C 编译器在一端为用户提供标准且定义良好的接口。另一方面,它可以直接使用ISA指令或另一个称为“Assembler”的接口。
2) 现在,如果您使用的是 Assembler,那么 Compiler 会将所有 C 代码转换为 Assembler 给出的语法。而Assembler 提供给Compiler 的语法称为汇编语言。它也是定义良好的接口,任何人都可以用它来用汇编语言编程。而在另一端,Assembler 将其所有语法(助记符|指令,ISA 中不存在的)转换为 ISA 中的二进制代码指令。
这里有这个翻译的一些例子。
在这个文件中,一行是“Machine: Advanced Micro Devices X86-64”,它提供了有关处理器的信息,因此我们正在使用 ISA 和汇编程序。而C程序员并没有意识到这一点,他可以自由地用C编写代码。这就是“定义良好的接口”的好处。
比较只是看
你好.c(C程序)
hello.asm2bin(目标文件表:直接映射助记符和二进制指令)
hello.asm2bin_exe(二进制文件表:链接后的更多映射)
你会在这些文件中看到一行“段的反汇编..” 因为汇编程序做什么:它从汇编语言汇编 ISA 指令(位模式),所以这里我们看到第一个 ISA 指令,然后反汇编为助记符。
所有文件都在此链接 [下载并打开]
https://www.dropbox.com/sh/v2moak4ztvs5vb7/AABRTxl7KQlqU2EkkMkKssqYa?dl=0