Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly CPU/汇编程序如何知道下一条指令的大小?_Assembly_X86_Cpu_Instruction Set - Fatal编程技术网

Assembly CPU/汇编程序如何知道下一条指令的大小?

Assembly CPU/汇编程序如何知道下一条指令的大小?,assembly,x86,cpu,instruction-set,Assembly,X86,Cpu,Instruction Set,举个例子,假设我正在构建一个虚拟机。我有一个字节数组和一个while循环,如何知道下一条指令要从字节数组中读取多少字节来解释一条类似英特尔8086的指令 编辑:(评论) CPU在指令指针处读取操作码,使用8086和CISC,您有一个字节和两个字节的指令。如何知道下一条指令是F还是FF 编辑: 我自己在这篇文章中找到了答案 操作码或操作码位于任何可选前缀之后。操作码告诉处理器要执行哪条指令。此外,操作码包含描述预期操作数大小和类型的位字段。例如,NOT指令的操作码为1111011w。在此操作码中,

举个例子,假设我正在构建一个虚拟机。我有一个字节数组和一个while循环,如何知道下一条指令要从字节数组中读取多少字节来解释一条类似英特尔8086的指令

编辑:(评论) CPU在指令指针处读取操作码,使用8086和CISC,您有一个字节和两个字节的指令。如何知道下一条指令是F还是FF

编辑: 我自己在这篇文章中找到了答案

操作码或操作码位于任何可选前缀之后。操作码告诉处理器要执行哪条指令。此外,操作码包含描述预期操作数大小和类型的位字段。例如,NOT指令的操作码为1111011w。在此操作码中,w位确定操作数是字节还是字。OR指令的操作码为000010dw。在此操作码中,d位确定哪些操作数是源操作数和目标操作数,w位再次确定大小。有些指令有几个不同的操作码。例如,当OR与累加器寄存器(AX或EAX)和常量一起使用时,它具有特殊的节省空间的操作码0000110w,这就不需要单独的ModR/M字节。从尺寸编码的角度来看,不需要记忆精确的操作码位。更重要的是,对特定指令可用的操作码类型有一个大致的了解

TLDR: 解决方案比固定大小的数组更复杂


这都是关于上下文的,这就是为什么像IDA这样的反汇编程序有复杂的算法来实现这一点

x86的指令长度可变。但是如果你知道一条指令的开始,你就知道该指令在哪里结束。正因为如此,你可能知道下一个从哪里开始。我将很快解释例外情况。但首先,这里有一个例子:

ASM:
mov eax, 0
xor eax, eax

Machine:
b8 00 00 00 00
31 c0
说明: 移动到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
机器代码:

b8 90 90 90 90

如果我们后来有一条jmp指令跳入上述指令的第三个字节的地址(在它中间的某个地方),它将只执行3个NOP(无操作)并落在它之后的下一条指令(不将eax设置为0x9090)。这是因为
NOP
是由0x90组成的1字节指令。

cpu只是对指令进行解码。在8086的情况下,第一个字节告诉处理器还有多少。它不必是第一个字节,第一个字节必须以某种方式表明你需要得到更多,更多可以表明你需要更多。对于像x86系列那样的8位指令集,您可以从一个字节开始,然后查看需要的字节数,而且如果未对齐,则必须将指令流视为ByTestStream,以便对其进行解码


您应该自己编写一个非常简单的指令集模拟器,只有少量指令,可能足以加载寄存器,添加一些内容,然后循环。对于你试图理解的内容来说,这是非常有教育意义的,如果要写的话,可能需要半个小时。

你所说的“打断指令”是什么意思?你知道“中断”这个词是什么意思吗?至于最初的问题:CPU知道一条指令有多长,因为这些信息要么烧录到它的硬件中,要么编程到它的微码中。CPU在指令指针处读取操作码,使用8086和CISC,您有一个字节和两个字节的指令。如何知道下一条指令是F还是FF?编辑:对不起,它知道,因为每条指令都有固定的长度。如果指令是跳远指令,它知道它还必须读取接下来的4个字节。如果它是一个add,它知道它必须只读取下一个1字节。等等,等等,每一条指令都不是一个固定的长度?如何知道下一条指令是F还是FF?编辑:编辑过的问题,找到了ansewSorry,我解释得再好不过了。我并不是说每条指令都有相同的长度。我写道它们有固定的长度。例如。跳远总是5字节长,加法可能是2字节长,等等。从操作码中可以知道应该读取多少额外的字节。我已经自己解决了,你错了。您的过度思考和遗漏是cpu知道要读取多少字节的关键原因。对于一个字节的指令,有一个比特告诉CPU读取下一个字节作为指令的一部分。在应用程序的上下文中,我可能已经过度思考了,但是我描述的一些缺陷并不是错误的。跳转到指令中间的地址是恶意软件作者和混淆者将使用的策略。这绝对会通过线性分析引擎关闭。以下是有关执行此操作的算法的讨论:。除此之外,我阅读了您的参考(),它非常好,正如您所说,回答/解决了您的VM应用程序问题“TLDR:解决方案比固定大小的阵列更复杂。这都是关于上下文的,这就是为什么像IDA这样的反汇编程序有复杂的算法来实现这一点。x86的指令长度可变。但是如果你知道一条指令的开始,你就知道该指令在哪里结束。正因为如此,你可能知道下一个故事从哪里开始:“我是个新手,我有借口,但你却不知道。”