【问题标题】:What do square brackets mean in x86 assembly?x86 汇编中的方括号是什么意思?
【发布时间】:2018-07-14 11:22:45
【问题描述】:

我是组装新手,有一些非常基本的问题。

这四个命令有什么区别?

mov ebx, eax
mov [ebx], eax
mov ebx, [eax]
mov [ebx], [eax]

他们说括号的意思是“获取地址的值”。但是,那么,第一行真的有什么作用呢?它不会将eax的值移动到ebx中吗?如果是这样,那么括号的意义是什么?

【问题讨论】:

  • 括号的重点是访问内存。你可以把它想象成C语言中的*运算符。另外,最后一个是无效的。
  • 但是第一个例子不是没有括号就访问内存吗?
  • @ineedahero:最后一行无效,因为没有办法从内存复制到内存。在[ebx],[eax] 中,ebx 和 eax 包含地址,即两者都在引用内存。而且你不能直接从内存复制到内存:处理器没有指令。
  • @RudyVelthuis:不太正确:指令集没有提供使用两个 显式 内存操作数对任何指令进行编码的方法。但是movspush [mem]pop [mem] 都将内存复制到内存,其中一个或两个操作数是隐式的。 x86 指令最多有一种 modrm + 可选的位移显式寻址模式。 这就是为什么mov不起作用但其他指令起作用的原因。
  • MASM 中括号的含义:stackoverflow.com/questions/25129743/…

标签: assembly memory x86 intel-syntax


【解决方案1】:

让我们做一个非常简单的例子,假设我们有一个只有两个寄存器 EAX 和 EBX 的 CPU。

mov ebx, eax

只需将eax 中的值复制到ebx 寄存器中

 | EAX : 0123456 |   ---->   | EAX : 0123456 |
 | EBX : 0000000 |   ====>   | EBX : 0123456 |

现在让我们添加一些内存空间

ADDRESS         VALUE
000000          6543210
000004          5189784
000008          1698791
00000C          9816517
000010          9816875
000014          5498156

mov [ebx], eax

eax 中的值移动到ebx 中包含的内存地址。

 | EAX : 0123456 |   --no-->   | EAX : 0123456 |
 | EBX : 0000008 | --change--> | EBX : 0000008 |

ADDRESS         VALUE           VALUE
000000          6543210   ----> 6543210   
000004          5189784   ----> 5189784   
000008          1698791   ====> 0123456
00000C          9816517   ----> 9816517   
000010          9816875   ----> 9816875   
000014          5498156   ----> 5498156   

mov ebx, [eax]

将值从包含在eax 中的内存地址移动到ebx

 | EAX : 0000008 |   ---->   | EAX : 0000008 |
 | EBX : 0123456 |   ====>   | EBX : 1698791 |

ADDRESS         VALUE    
000000          6543210    
000004          5189784  
000008          1698791  
00000C          9816517   
000010          9816875    
000014          5498156    

mov [ebx], [eax]

最后,您会认为会将值从包含在eax 中的内存地址移动到包含在ebx 中的内存地址。

 | EAX : 0000008 |   --no-->   | EAX : 0000008 |
 | EBX : 000000c | --change--> | EBX : 000000c |

ADDRESS         VALUE           VALUE
000000          6543210   ----> 6543210   
000004          5189784   ----> 5189784   
000008          1698791   ----> 1698791   
00000C          9816517   ====> 1698791   
000010          9816875   ----> 9816875   
000014          5498156   ----> 5498156 

但是 x86 架构不允许这种组合。 You cannot move from memory to memory.

因此,括号的使用等同于dereferencing 操作。

【讨论】:

  • 那么为了让第二行有意义,ebx 的 VALUE 必须是内存中的 ADDRESS?
  • @ineedahero 是的,它必须是有效的内存地址。
  • 好的,谢谢。这就是我遗漏的秘密,而你的答案是唯一能解决它的人。
  • 怎么别人都说最后一行无效?
  • @DannyS 9.16.7 - Memory References,在第 9.16 节(80386 相关功能)下。
【解决方案2】:

您在说明中缺少操作数分隔符 ,。我不知道(还)没有它的任何汇编程序。我在引号中修正了它。

在 x86 汇编中,一些寄存器可以用作数据寄存器用作地址寄存器(与其他架构不同)。这些寄存器称为 GPR(“通用寄存器”)。它们可以包含 32 位值 32 位地址。他们的“名字”是EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP

mov ebx, eax

确实将EAX 中的值移动到EBX

mov [ebx], eax

确实将EAX中的值移动到EBX中的32位地址所指向的32位DWORD值

mov ebx, [eax]

确实将EAX中的32位地址指向的32位DWORD值移动到EBX

mov [ebx], [eax]

是 32 位 Intel 汇编中的无效指令,因为基本的 x86 汇编不支持在一个(双操作数)指令中使用两个内存操作数。具有三个或四个操作数的较新指令(SSE、AVX)能够使用多个内存操作数。这是更复杂的指令编码(使用指令前缀)的结果。

【讨论】:

  • “EAX中的值”和“EAX中32位地址指向的32位DWORD值”有什么区别?也就是说,前两行有什么实际区别?
  • 怎么会是最后一行无效而不是第二行呢?
  • 最后一行包含两个内存引用,第二行只有一个。
猜你喜欢
  • 2011-01-03
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-15
  • 1970-01-01
相关资源
最近更新 更多