理解x86 MOV语法

5

我认为这是一个容易(也许太容易)回答的问题,但在Google上搜索了近两个小时后,我没有找到答案。我相信我的问题在于我不理解这个语法正在做什么。

我正在查看IDA中的一些反汇编代码,我不知道以下代码在做什么:

mov dl, byte_404580[eax]

如果我跳转到byte_404580,我会发现.data:00404580 byte_404580 db 69h,告诉我这个值是0x69。但我不知道它的用途。
让我提供一下这段代码出现的上下文:
mov eax, 0x73             ; Move hex 73 to EAX
and eax, 0x0F             ; Keep lower half of EAX
mov dl, byte_404580[eax]  ; MAGIC

假设EAX最初为0x73,那么我得到DL=0x76。我尝试改变EAX的值以找到一些模式,但是我还没有弄清楚正在发生什么。


byte_404583 的值是多少? - slavemaster
1
这相当于计算表达式 0x404580 + (eax & 0x0F),将其视为地址,并从该地址中取一个字节。这表明 0x404580 处的数据是一个字节数组(根据掩码很可能有 0x10 个元素),而不是单个字节。与 C 语言的 2["hello"] == "hello"[2] 进行比较。 - DCoder
@slavemaster byte_404583=0x76 - CatShoes
我认为在原帖中,当我说“DL=ox65”时写错了。我很确定自己是在看EAX错误的值。 - CatShoes
@DCoder,感谢您的解释。看着0x404580处的数据,它是一个字节数组(确切地说是16个字节)。然后,我将EAX初始化为最不重要的半字节,以获取DL的值。非常感谢您的帮助。如果您将其写成答案,我会为您标记的。 - CatShoes
1个回答

4
这种语法用于表示内存寻址,类似于C中的数组语法(array[index])。您的示例等同于计算表达式0x404580 + (eax & 0x0F),将其视为地址,并从该地址取一个字节。这表明0x404580处的数据是一个字节数组(根据掩码,很可能有0x10个元素)。
如果这回答了您的问题,您可以停止阅读了。
如果您进入“选项”>“常规”,并将“显示操作码字节”设置为非零值,则可以看到指令字节的实际值,并能够与处理器文档进行交叉引用,以了解发生了什么。通常情况下不需要这样做,但它可以具有教育意义。例如:
mov dl, byte_404580[eax]

可以表示为一系列字节:
8A 14 05 80 45 40 00

使用Intel架构手册,卷2A,可以按照以下方式进行解码:
8A - instruction opcode for MOV r8, r/m8 - determines the operand sizes

14 - the Mod R/M byte:
         | 00010100b
     Mod | 00
     R/M |      100
     Reg |   010

     Mod R/M combination 00-100 is specified as "followed by the SIB byte".
     Reg 010 stands for register DL/DX/EDX, the destination operand.

05 - the SIB byte:
           | 00000101b
     Scale | 00
     Index |   000
     Base  |      101

     This combination is specified as [scaled value of EAX] + a 32 bit displacement.

80 45 40 00 - the displacement itself, 0x404580

将它们相加,您将得到:
该指令从“EAX + 0x404580”中取出一个字节,并将其移入“DL”寄存器。
IDA使用这些信息推断出在0x404580处有一个字节大小的值数组,如果该位置没有名称,则尝试为其命名,尝试调整该位置的命名项以跨越正确数量的字节(它不一定知道此数组中有多少元素,因此它实际上并没有在那里创建数组),并将显示的表达式转换为byte_404580[eax]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接