在x86中,我理解多字节对象以小端方式存储在内存中。
现在一般来说,当谈到CPU指令时,OPCODE确定指令的目的,数据/存储器地址可以遵循其编码格式的操作码。我的理解是指令的操作码部分应该是最重要的字节,因此出现在任何给定指令编码表示的最高地址。
有人可以解释这个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指令甚至没有endian-ness并且正在考虑某种类型的字符串? (可能离开这里)
答案 0 :(得分:5)
x86是一个可变长度的指令集,你从一个没有字节序的字节开始,它就在任何地方。
然后,根据操作码,可能会有更多字节,例如可能是32位立即数,并且(如果该组字节是立即数或某种类型的地址),那么这些字节将是小字节。假设您有五个字节ABCDE(没有endianess,认为数组或字符串)。 A字节是操作码,B字节则是立即数的低8位,E是立即数的高8位。
操作码是一个难以使用的术语,在这些较旧的8/16位CISC处理器(如x86)中,整个字节是一个操作码,您基本上在表格中查找它的含义(并且在处理器内部使用了表,以弄清楚如何执行它)。当您查看MIPS或ARM或其他(当然是RISC)指令集时,只有32位的一部分是&#34;操作码&#34;并且在这两种情况下都不是从一条指令到另一条指令的相同位组,你必须查看指令中的各个位置(是的,有重叠使解码理智),MIPS更加一致你有一个blob在你看的一个地方,但其中一个模式需要你看另一个blob来完全解码。 ARM你从一个共同的位开始,当你在你的工作中进一步解码指令,然后你可能必须抓住一些随机观察点来完全解码。其余的位是操作数,要使用的寄存器或立即数或者在CISC中需要查找表的任何类型(由操作码隐含但未由操作码中的位定义)。
1)先前指令之后的下一个字节将被解释为操作码,即使不是一个操作码(如果执行继续到该字节并且不进行分支)。我不记得我的x86表了解是否有任何未定义的指令,如果未定义则会触及处理程序,否则它将解码它发现的机器代码,如果它没有正确形成指令可能会崩溃,有时候你会很幸运,它会让事情变得混乱并继续前进,甚至更加幸运,你无法说它几乎崩溃了。
2)你适合这些8/16位CISC或类似的指令集,它们被视为更像线性解析的字符串。