Ami*_*mar 6 assembly arm machine-code instructions thumb
我真的很困惑,这个问题可能听起来很愚蠢,但是当我们说指令大小是 32 位或 16 位时,我真的不确定这意味着什么。
如果操作数大小是 32 位,那么我们说它是 32 位指令,如果操作数大小是 16 位指令。
或者每条指令都有操作码,如果操作码地址是 32 位,那么我们说指令是 32 位。
我也在浏览 ARM 架构,在那里我读到的所有拇指指令都是 16 位的,但 ARM 模式指令是 32 位的。
指令大小完全取决于所使用的架构还是取决于 CPU 的运行模式?
http://www.xgc-tek.com/manuals/m1750-ada/m1750/x524.html
给定的链接表明,16 位指令由 8 位操作码和 4+4 位两个通用寄存器组成。
ARM拇指指令集是怎么回事??
指令集(机器代码)的设计者,无论是一群人还是一个人,都会选择指令的大小。一些指令集,很多,是可变长度的,字面意思是一些指令比其他指令占用更多的位。操作码这个词适合那些遗留指令集,因为第一个字节通常决定这是哪条指令,并且从第一个字节开始添加更多的操作数字节。我想到的这些操作码,x86、6502、z80 等不一定有不同的字段。例如切换到 mips 看看我的意思,固定长度指令(虽然 mips 也有一个 16 位模式,你可以像 arm 一样跳入和跳出)。很容易看出一些位的初始解码决定了几类指令中的哪一类,然后从那里几位决定指令,也称为操作码位。但是这个术语对我们今天拥有的所有指令集都具有误导性。根据您所谈论的指令集和指令集,您将整个指令称为操作码是对是错。
所以有人会通过任何方法、经验、实验等来选择指令集是什么以及他们可以塞进这些位的内容。对于 arm 的情况,他们从 32 位指令开始,固定长度。就像 mips 使立即变得痛苦,但同时其他事情更容易(获取,解码等)。第一个拇指指令似乎是直接转换为它们的 arm 对应物(ARM ARM 中记录了 arm 等效项),并且可能作为 arm 指令输入管道。那是那时,现在是。但是,您定义指令集及其机器代码并不重要,您可以设计解析该指令集并根据需要执行它的逻辑,并且随着时间的推移,如果您幸存下来,您可能会像大多数公司所做的那样重新设计处理器使用不同的逻辑。让 100 名程序员给他们一个通用的 ascii 文件解析任务,你会得到 2 到 100 种不同的解决方案,从语言到样式再到算法,所有这些都已经或有潜力完成这项工作。与处理器一样,您可以根据设计周期为指令集发明尽可能多的不同功能处理器。
ARM 拥有不断发展的传统 32 位指令集。在这里和那里添加了一条新指令,但在 64 位之前没有太多重大变化。有原始的拇指指令集,它是严格的 16 位指令(是的,分支是两个单独的 16 位指令,请阅读文档)。然后他们添加了thumb2,它使用以前未定义的thumb 指令来扩展thumb 指令集以恢复arm 指令集的一些功能。这些指令必须成对使用,32 位,才能正确解释。还有jazelle,我仍然无法找到证据证明这是一个实际的指令集,从我所能确定的一切来看,它是一个您购买的软件包,而不是一个实际的指令集。也许有无证的手臂或拇指指令来支持 jazelle,但我看不到哪里有指令集。然后 arm 有许多浮点指令集,但它们实际上是协处理器指令,重命名了字段并添加了助记符。
各种 arm 处理器内核使用逻辑来解码这些东西中的每一个,也许有一个底层的通用指令集,上面的所有内容都被输入,微代码,但更像 vliw,或者它只是蛮力逻辑,如果这种模式然后解码这些位等,如果该模式等。
在这一点上,原始拇指指令集是整个 arm 系列中唯一通用的指令集。出于这个原因,除了其他人之外,我还需要一些时间来学习它。最困难的事情,一旦你养成习惯就不难了,就是让你的工具链按照你想要的方式构建东西,这在手臂模式下,拇指或所有拇指,或所有手臂。拇指加拇指 2 扩展,或仅拇指没有扩展。不幸的是,armv6 添加了 30 条左右的 thumb2 指令,armv7 又添加了 140 条左右。armv7m首先进入市场,armv6m之后,然后只有neon等发布,所有这些都在工具链和用户中造成混乱,试图为有问题的核心生成有效的代码,只生成它支持的指令,而不是它不生成的指令.
ARM ARMs, ARM Architectural Reference Manuals 和 ARM TRMs, ARM Technical Reference Manuals 描述了指令集(不幸的是一些内核文档在 ARM 中,其他在 TRM 中),从那里你可以很容易地看到编码以及它们的内容和位置已经把东西塞进了 ARM 指令和拇指指令中。我会从最古老的架构参考手册开始,也许他们称之为 ARMv5 ARM?我不记得了,但它是原始的 ARM ARM,包含 ARMv4T 的内容,包括 arm 指令集和原始拇指指令集。然后你需要更多的手册来了解它们是如何演变的。
编辑,您的链接(链接在堆栈溢出时很糟糕,它们经不起时间的考验)
MIL-STD-1750A 是另一个处理器系列/指令集,机器代码按该设计分解,并按该设计解码。带有thumb2 扩展的thumb 基本上是一个可变长度指令集,因为您必须检查前16 位以确定是否需要额外的16 位才能完全理解该指令,这在x86 系列等可变长度指令集中很常见。
就 arm 和 mips 而言,它是一种模式,您处于一种模式或另一种模式。就其他设计为可变长度的指令集而言,它不一定是一种模式,而是解码器始终如何工作。当从 16 位到 32 位再到 64 位时,x86 确实必须玩游戏。我还没有学习新的 arm 架构,很可能它可以在没有 64 位指令集的情况下支持 64 位寄存器(例如,x86 仍然是一个支持多达 64 位寄存器的 8 位指令集)但我不知道那是不是他们做了什么。
编辑 2
感谢@dwelch 的详细回答,你总是在那里帮助人们。我的疑问很简单。假设我们有 16 位指令添加 r1,r2 并且这里的操作码大小是 8 位,那么这是否意味着 r1 和 r2 可以没有超过 15 的值(r1 和 r2 只有 8 位可以在它们之间共享)。这是真的吗??——
我认为 auselen 试图以这种方式回答这个问题。
add r1,r2 的机器码只是告诉处理器一些事情,这是一个加法操作,操作数是寄存器 r1 和 r2 的内容,结果进入 r1。不管r1、r2和其他寄存器都是32位的。指令大小与此无关。将 r1 的所有 32 位添加到 r2 的所有 32 位,并将整个 32 位结果放在 r1 中。
困难之处在于直接价值。如果您想将立即数 1 添加到 r1,那么就有空间了。但是如果你想将值 0x100000 添加到 r1,那么你不能在一条指令中使用拇指模式来做到这一点,你可以使用 arm 指令,我认为使用拇指 2 扩展而不是拇指,因为指令集的设计没有考虑到这一点,无论指令集有多大,您都无法在一条指令中完成您想做的所有事情。为了拇指将该常量添加到寄存器中,您需要使用另一个寄存器,然后从内存中加载该常量(通过要求汇编程序在构建二进制文件时将该值放入内存中),或者您可以例如 mov 1 到一个寄存器,然后左移 20 位。
Mips 和 arm 使用不同的方式让它们的即时指令在固定长度的指令内工作,mips 基本上为您提供高 16 位或低 16 位,并且有一组指令,其中一半指令是立即数。Arm 通常将其分解为 8 位和一个移位操作数,以便您可以创建任何立即数,只要唯一位在 8 位簇中(加上一些其他规则)。要使用纯指令,mips 需要两条指令才能将任何可能的 32 位值加载到寄存器中,arm 在 arm 模式下最多需要 4 条。拇指模式需要的远不止这些。
回到主题,看看 x86 指令集,单个 8 位操作码可以告诉处理器在两个 64 位寄存器上执行一些操作。这不仅仅是一个 8 位的操作码,而是整个指令只有 8 位。有时 16 个,有时更多。但重点是指令指定哪个寄存器只需要几位。寄存器的大小是指令集设计的一部分,但不一定且通常与指令的大小无关。对于任何操作,r1 和 r2 可以具有介于 0x00000000 和 0xFFFFFFFF 之间的任何值。
ARM(不包括新发布的64位)有两个由固定大小的指令组成的指令集。经典的称为 ARM,每条指令都是 32 位。后来的一种称为 Thumb(实际上是 Thumb2),它可以有 32 位或 16 位指令。有仅支持 ARM、ARM+Thumb 和仅支持 Thumb 指令集的 ARM 内核。如果内核支持这两种模式,则它具有更改活动指令集选择的指令,并且指令流可以在不同集之间跳转(互通)。
ARM 指令可以包含固定操作数,但它们永远不能与指令大小一样大。有些指令还支持对操作数进行操作,例如移位、旋转,这给您的印象是可以使用单个指令加载 32 位值。
例子#1
a = 0x1;
Run Code Online (Sandbox Code Playgroud)
拇指
2001 movs r0, #1
Run Code Online (Sandbox Code Playgroud)
手臂
e3a00001 mov r0, #1
Run Code Online (Sandbox Code Playgroud)
例子#2
a = 0xC0000000;
Run Code Online (Sandbox Code Playgroud)
拇指
f04f 4040 mov.w r0, #0xC0000000
Run Code Online (Sandbox Code Playgroud)
手臂
e3a00103 mov r0, #0xC0000000
Run Code Online (Sandbox Code Playgroud)
例子#3
a = 0x12345678
Run Code Online (Sandbox Code Playgroud)
拇指
f245 6078 movw r0, #0x5678
f2c1 2034 movt r0, #0x1234
Run Code Online (Sandbox Code Playgroud)
手臂
e3050678 movw r0, #0x5678
e3410234 movt r0, #0x1234
Run Code Online (Sandbox Code Playgroud)