Ash*_*eah 5 cpu assembly controls instruction-set
举例来说,想象一下我正在构建一个虚拟机.我有一个字节数组和一个while循环,我如何知道从字节数组中读取多少字节,以便下一条指令解释类似于intel 8086的指令?
编辑:(注释)cpu在指令指针处读取操作码,8086和CISC有一个字节和两个字节指令.我怎么知道下一条指令是F还是FF?
编辑:在http://www.swansontec.com/sintel.html上的这篇文章中找到了一个自己的答案
操作代码或操作码位于任何可选前缀之后.操作码告诉处理器执行哪条指令.此外,操作码包含描述期望操作数的大小和类型的位字段.例如,NOT指令具有操作码1111011w.在该操作码中,w位确定操作数是字节还是字.OR指令的操作码为000010dw.在该操作码中,d位确定哪些操作数是源和目的地,并且w位再次确定大小.某些指令有几种不同的操作码.例如,当OR与累加器寄存器(AX或EAX)和常量一起使用时,它具有特殊的节省空间的操作码0000110w,从而无需单独的ModR/M字节.从大小编码的角度来看,记忆精确的操作码位是没有必要的.大致了解特定指令可用的操作码类型更为重要.
cpu只是解码指令.在8086的情况下,第一个字节告诉处理器要获得多少.它不必是第一个字节必须以某种方式指示您需要获得更多的第一个字节,更多可以表明您需要更多.对于像x86系列这样的8位指令集,您从一个字节开始,然后查看您需要多少,并且还未对齐,您必须将指令流视为字节流以对其进行解码.
你应该自己编写一个非常简单的指令集模拟器,只需要一些指令,可能足以加载一个寄存器,向它添加一些内容然后循环.对于你想要了解的内容极具教育意义,如果要写的话,可能需要半个小时.
解决方案比固定大小的阵列更复杂.
这完全取决于上下文,这就是像IDA这样的反汇编程序具有复杂算法的原因.
说明是x86的可变长度.但是如果你知道指令的开始,你就会知道指令的结束位置.因此,您可能知道下一个开始的位置.我会尽快解释这些例外情况.但首先,这是一个例子:
ASM:
mov eax, 0
xor eax, eax
Machine:
b8 00 00 00 00
31 c0
Run Code Online (Sandbox Code Playgroud)
移动到eax后B8,接着是32位(4字节)值进入eax(因为eax是32位).换句话说,mov eax, immediate总是5个字节.因此,如果您知道您正在开始一条指令(并不总是一个安全的假设),并且该字节是B8,您知道它是一个5字节指令,并且下一条指令应该在5字节之后开始.
请注意,两个指令(mov eax, 0和xor eax, eax)有效地执行相同的操作,将eax清除为0.
跳跃/通话会让事情变得棘手.可以跳转到"指令中间"的地址空间......但仍然可以执行.
让我们来看看:
mov eax, 0x90909090
Run Code Online (Sandbox Code Playgroud)
机器代码:
b8 90 90 90 90
Run Code Online (Sandbox Code Playgroud)
如果我们以后有这样跳进上述指令的第3个字节的地址JMP指令(在它的中间某处),它只是做3个的NOP(无操作)和之后转到下一个指令(未设定eax到0x90909090).这是因为a NOP是由0x90组成的1字节指令.
| 归档时间: |
|
| 查看次数: |
3037 次 |
| 最近记录: |