masm x86 Assembly 如何使变量指向设置缓冲区中的值?

masm x86 Assembly How to make a variable point to a value in a set buffer?

假设我创建了一个大约 100 个 DWORD 的简单缓冲区,并且我还定义了一个变量,该变量应该指向该缓冲区中的给定 DWORD。

.DATA?
buffer DWORD 064h DUP(?)
my_ptr DD ?

在 .CODE 部分,我试图让 my_ptr 指向缓冲区中的第一个双字,因此 OFFSET 缓冲区 + 04h * 00h。 我想我可以让寄存器存储地址,然后将寄存器内的地址移动到 my_ptr.

.CODE
;for the sake of the example pretend that the values in buffer
; are initialized.
MOV EDI, OFFSET buffer
MOV EAX, EDI + 04h * 00h ; trying move the address of the first element in 
;the buffer into EAX
MOV my_var, EAX ;move the address that eax holds into my_var

所以基本上总结一下,有没有办法让数据变量指向缓冲区内的值?我不知道这是否可能,因为每次我查看寻址时它总是被取消引用,但在这种情况下我只想要地址,而不是地址处的值。

谢谢

.DATA?
buffer DWORD 064h DUP(?)
my_ptr DD ?

.CODE
;for the sake of the example pretend that the values in buffer
; are initialized.

它们是否是无关紧要,因为您不会在以下代码中对它们进行任何操作。

MOV EDI, OFFSET buffer

是的,这是保留内存的地址(在 edi 中)。

MOV EAX, EDI + 04h * 00h ; trying move the address of the first element in 
;the buffer into EAX

现在这在 x86 语法中是不合法的,你不能做 mov reg,reg+immediate,但是当你添加零时,它与 mov eax,edi 是一样的,这是合法的并且会做什么如您所料,将数组地址从 edi 复制到 eax。现在这当然没用了,因为您可以通过 MOV [my_ptr],edi

直接从 edi 存储地址

但是假设您想要第三个(索引 2)DWORD 的地址,那么您对 ​​mov eax, edi + 4*2 的想法可以这样写:

mov  eax,edi   ; copy the address first (no math expression possible)
add  eax,4*2   ; offset the address to point to third element
mov  [my_ptr],eax   ; store it

但是 x86 对此有更专门的指令,它允许您使用合法用于取消引用的相同表达式(如 mov eax,[edi+4*2])仅用于计算地址。该指令称为 LEA - load effective address。它的工作原理有点像“MOV 没有勇气”,所以:

lea eax,[edi+4*2]

将计算目标内存地址,如 MOV,但它不会联系内存获取值,而是将计算出的地址存储到目标寄存器中,因此在这种情况下将设置 eaxedi+8 值(这是第三个元素的地址)。

这也可以用于简单的数学计算,如果你忘记描述中的 "address" 措辞,比如你想计算 ecx = eax + 4*edi + 22,那么你可以这样做在 x86 上使用单个指令:lea ecx,[eax + 4*edi + 22](但这可能只是因为该表达式是 mov 指令族的有效内存操作数,如果您想要 eax + 5*edi + 22,则必须使用两个 lea 指令将该表达式分解为两个有效的内存寻址表达式,作为练习自己尝试)。如果您只使用普通的算术指令,则需要其中的四个 (mov ecx,edi shl ecx,2 add ecx,eax add ecx,22).

有时您还可以利用 lea 进行算术运算,同时为其他正在进行的计算保留标志,例如递增指针,而 CF 保留用于对值进行的持续加法。