我被要求将以下机器代码转换为 Intel 语法中的汇编代码:
0x421a0770: 0D 00 3D 77
0x421a0774: AC 3D 11 2A
0x421a0778: 96 AB 77 04
0x421a077c: 90 2D 0D AB
0x421a0780: C3 77 2C C3
我知道
0d
是第一条指令的操作码,它是 or
的 eax
和立即数,这意味着接下来的 4 个字节代表立即数。但是,我不明白接下来的 4 个字节到底按什么顺序排列。我知道它使用小尾数,但我很困惑它在这种情况下意味着什么。
哪一条是正确的第一条指令?
or eax, 0x003D77AC
or eax, 0xAC773D00
or eax, 0x003D112A
or eax, 0x2A773D00
我使用了一些在线转换器,它给了我第二个选项,但据我了解,左列是 MSB,因此
AC
和 77
字节在内存中甚至不相邻。
我知道这是非常基本的问题,但我在其他地方找不到相关信息
不要强迫自己受到转储形状造成的约束,因为转储是概念内存内容的文本表示。
例如,以下转储是 100% 等效的。
0x421a0770: 0D 00 3D 77 AC 3D 11 2A 96 AB 77 04 90 2D 0D AB
0x421a0780: C3 77 2C C3
如下也100%等效:
0x421a0770: 0D
0x421a0771: 00
0x421a0772: 3D
0x421a0773: 77
0x421a0774: AC
0x421a0775: 3D
0x421a0776: 11
0x421a0777: 2A
...
我们怎么知道这一点? 这是因为转储是字节形式的转储。 字节转储不存在字节序问题。
仅供参考,字形式(16 位字)转储在小尾数中看起来像这样:
0x421a0770: 000D 773D 3DAC 2A11 AB96 0477 2D90 AB0D
像这样使用大端:
0x421a0770: 0D00 3D77 AC3D 112A 96AB 7704 902D 0DAB
无法以小端或大端进行字节形式转储。 因此,我们必须将每个字节(2 个十六进制数字的数字)视为占据下一个连续存储位置。 这部分是因为要应用字节序,我们必须给出一个大小来解释字节序,而我们没有给出一个大小(或者换句话说,我们一次给出 1 个字节的大小,而没有字节序)适用)。
这就是为什么单词转储呈现单词(4 个十六进制字节的数字),因此我们知道在哪里应用字节顺序。 长字转储将具有一次涉及 4 个字节的字节序(因此为 8 个十六进制数字),而四字转储将具有一次涉及 8 个字节的字节序(因此为 16 个十六进制数字)。
特别是对于little endian,这些较大的内存转储大小很难读取,因为我们的数据通常涉及混合大小,包括单词和字符串(字节),并且转储不知道哪个在哪里。
此外,由于 x86 指令的长度是可变的,它们必然会跨越字、双字和四字边界,因此以这些较大的尺寸转储文本(机器代码)也非常令人困惑。