【问题标题】:Linux x86 CPU Instruction Layout ConfusionLinux x86 CPU 指令布局混乱
【发布时间】:2016-07-20 00:27:31
【问题描述】:

在 x86 中,我了解多字节对象以小端方式存储在内存中。

现在一般来说,当涉及到 CPU 指令时,操作码决定了指令的用途,并且数据/内存地址可能会跟随操作码的编码格式。我的理解是指令的操作码部分应该是最高有效字节,因此出现在任何给定指令编码表示的最高地址。

有人可以解释这个 x86 linux gdb 示例的内存布局吗?我想操作码 0xb8 会出现在更高的地址,因为它是最重要的字节。

(gdb) disassemble _start

Dump of assembler code for function _start:
0x08048080 <+0>:    mov    eax,0x11223344

(gdb) x/1xb _start+0
0x8048080 <_start>:     0xb8
(gdb) x/1xb _start+1
0x8048081 <_start+1>:   0x44
(gdb) x/1xb _start+2
0x8048082 <_start+2>:   0x33
(gdb) x/1xb _start+3
0x8048083 <_start+3>:   0x22
(gdb) x/1xb _start+4
0x8048084 <_start+4>:   0x11

似乎指令 mov eax, 0x11223344 被编码为 0x11 0x22 0x33 0x44 0xb8。

问题。

1.) 如果它看到的第一个字节不是操作码,CPU 如何知道该指令将占用多少字节?

2.) 我想知道 x86 cpu 指令是否甚至没有字节序并且正在考虑某种类型的字符串? (可能离这里很远)

【问题讨论】:

标签: linux assembly x86 endianness


【解决方案1】:

x86 是一个可变长度指令集,你从一个没有字节序的单字节开始,无论它在哪里。

然后根据操作码,可能会有更多字节,例如,这些字节可能是 32 位立即数,并且(如果该组字节是立即数或某种地址)这些字节将是小端。假设您有五个字节 ABCDE(没有字节序,请考虑数组或字符串)。 A字节是操作码,B字节是立即数的低8位,E是立即数的高8位。

操作码是一个难以使用的术语,在这些较旧的 8/16 位 CISC 处理器(如 x86)中,整个字节都是一个操作码,您基本上可以在表格中查看它的含义(在处理器内部,它们确实使用了表来弄清楚如何执行它)。当您查看 MIPS 或 ARM 或其他类似的(当然是 RISC)指令集时,32 位中只有一部分是“操作码”,在这两种情况下,从一条指令到另一条指令都不是同一组位,您必须查看指令中的各个位置(是的,存在重叠以使解码正常),MIPS 更加一致,您在一个地方看到一个 blob,但是其中一个模式需要您查看另一个 blob位来完全解码。 ARM 你从一个共同的位开始,随着你的工作,你正在进一步解码指令,那么你可能必须抓住一些随机的点来完全解码。其余位是操作数,使用什么寄存器或立即数,或者在 CISC 中您需要查找表的任何类型的东西(由操作码隐含,但不是由操作码中的位定义)。

1) 前一条指令之后的下一个字节将被解释为操作码,即使它不是一个操作码(如果执行继续到该字节并且不分支)。我不记得我的 x86 表不知道是否有任何未定义的指令,如果未定义,那么它将命中一个处理程序,否则它将解码它找到的机器代码,如果它的格式不正确,指令可能会崩溃,有时你很幸运,它只是搞砸了一些东西并继续前进,或者更幸运的是,你不能说它几乎崩溃了。

2) 您对这些 8/16 位 CISC 或类似指令集是正确的,它们更像是您线性解析的字符串。

【讨论】:

  • 是的,我很清楚 ARM 和 MIPS 在它们的某些内核中具有 16 位交替指令集,而 ARM 更糟糕的是具有可变长度的 16 位指令集(thumb2 扩展为 thumb)。加上所有浮点的东西,也许是一个 JAVA 的东西,等等。为了解释上面的目的,只谈论一个固定的 32 位指令就可以了。如果您进行谷歌搜索,您应该找到 mips 和 arm 的编码,也许您可​​以“看到”它们是如何解码的,它们都有不同的设计方法。
  • 谢谢 dwelch,感谢您的洞察力。
  • 我想我可能没有回答问题 1)。 cpu 如何知道它读取的操作码确实告诉了它。它从操作码和/或附加字节中知道该指令需要多少总字节。它是可变长度的,因此一些指令短至一个字节,而其他指令可能相对较长。我认为最长的英特尔指令是什么这个问题已经被多次问过,不是很有趣的 IMO,但有些人一直在玩。
  • 你在 IMO 基本上是正确的。操作码讲述了这个故事,诸如立即数、地址和偏移量之类的东西都是小端序的。但是它们被视为小字节字符串,它们不会在任何边界上对齐,因为它们的长度取决于指令和该指令的选项。英特尔文档对此进行了说明,文档很容易通过在线或印刷版获得。
  • 因此,当我们将一个数据字从内存传输到寄存器 EAX 时,该字的 LSB(最低地址)被传输到 EAX 的低 8 位。简单地说就是 AL。 CPU的指令寄存器是不是类似把一条指令传进去,指令寄存器的“最高字节”指的是传入指令的Opcode?​​span>
猜你喜欢
  • 1970-01-01
  • 2021-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 2013-10-01
相关资源
最近更新 更多