gpt4 book ai didi

assembly - CPU如何正确解码变长指令?

转载 作者:行者123 更新时间:2023-12-02 07:28:21 24 4
gpt4 key购买 nike

在大多数架构上,指令都是固定长度的。这使得程序加载和执行变得简单。在 x86/x64 上,指令长度可变,因此反汇编程序可能如下所示:

File Type: EXECUTABLE IMAGE

00401000: 8B 04 24 mov eax,dword ptr [esp]
00401003: 83 C4 04 add esp,4
00401006: FF 64 24 FC jmp dword ptr [esp-4]
0040100A: 55 push ebp
0040100B: E8 F0 FF FF FF call 00401000
00401010: 50 push eax
00401011: 68 00 30 40 00 push 403000h
00401016: E8 0D 00 00 00 call 00401028
0040101B: 83 C4 08 add esp,8
0040101E: 33 C0 xor eax,eax
00401020: 5D pop ebp
00401021: 83 C4 04 add esp,4
00401024: FF 64 24 FC jmp dword ptr [esp-4]
00401028: FF 25 00 20 40 00 jmp dword ptr ds:[00402000h]

Summary

1000 .data
1000 .rdata
1000 .reloc
1000 .text

似乎很难想象 CPU 如何“知道”一条指令在哪里结束和下一条指令在哪里开始。例如,如果我将字节 0x90 ( NOP ) 添加到 XOR EAX,EAX 的中间对程序进行操作码,然后反汇编为:
File Type: EXECUTABLE IMAGE

00401000: 8B 04 24 mov eax,dword ptr [esp]
00401003: 83 C4 04 add esp,4
00401006: FF 64 24 FC jmp dword ptr [esp-4]
0040100A: 55 push ebp
0040100B: E8 F0 FF FF FF call 00401000
00401010: 50 push eax
00401011: 68 00 30 40 00 push 403000h
00401016: E8 0D 00 00 00 call 00401028
0040101B: 83 C4 08 add esp,8
0040101E: 33 90 C0 5D 83 C4 xor edx,dword ptr [eax+C4835DC0h]
00401024: 04 FF add al,0FFh
00401026: 64 24 FC and al,0FCh
00401029: FF
0040102A: 25
0040102B: 00 20 add byte ptr [eax],ah
0040102D: 40 inc eax

Summary

1000 .data
1000 .rdata
1000 .reloc
1000 .text

可以预见的是,它在运行时会崩溃。

我很好奇指令解码器看到的额外字节是什么,让它认为行 0040101E长度为 6 个字节,该行最初位于 00401028是四个单独的指令。

最佳答案

当获取一条指令时,CPU 首先分析它的第一个字节(操作码)。有时知道指令的总长度就足够了。有时它会告诉 CPU 分析后续字节以确定长度。但总而言之,编码没有歧义。

是的,如果您在中间随意插入随机字节,命令流就会被搞砸。这是意料之中的;并非每个字节序列都构成有效的机器代码。

现在,关于您的特定示例。原来的命令是 XOR EAX, EAX (33 C0)。 XOR 的编码是依赖于第二个字节的编码之一。第一个字节 - 33 - 表示 XOR。第二个字节是 ModR/M 字节。它对操作数进行编码——无论是寄存器对、寄存器和内存位置等。32位模式下的初始值C0对应操作数EAX、EAX。您插入的值 90 对应于操作数 EDX、[EAX+偏移量],这意味着 ModR/M 字节后跟 32 位偏移量。命令流的下四个字节不再被解释为命令——它们是损坏的 XOR 命令中的偏移量。

因此,通过弄乱第二个字节,您将一个 2 字节的命令变成了一个 6 字节的命令。

然后 CPU(和反汇编器)在这四个之后恢复获取。它在 ADD ESP, 4 的中间指令,但 CPU 无法知道。它以 04 字节开始,即 ADD 编码中的第三个字节。那个时候的前几个字节作为命令仍然有意义,但是由于您已经在中间结束,原始指令序列完全丢失了。

关于assembly - CPU如何正确解码变长指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25129165/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com