让我们说我已经制作了一个大约100个DWORDS的简单缓冲区,并且我还有一个定义的变量,它应该指向该缓冲区中的给定DWORD。
.DATA?
buffer DWORD 064h DUP(?)
my_ptr DD ?
在.CODE部分,我试图让my_ptr指向,比如缓冲区中的第一个dword,所以OFFSET buffer + 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
所以基本上总结一下,无论如何使数据变量指向缓冲区内的值?我不知道这是否可行,因为每次我查看它时,它总是被解除引用,但我只想要这个地址的地址,而不是地址的值。
由于
答案 0 :(得分:2)
.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
。现在这当然没用了,因为你可以直接从edi
存储地址:MOV [my_ptr],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
,但不是将内存与值联系,而是将计算出的地址存储到目标寄存器中,因此在这种情况下,eax
将设置为{ {1}}值(以及第三个元素的地址)。
这也可以用于简单的数学计算,如果你忘记了描述中的“地址”措辞,比如你想要计算ecx = eax + 4 * edi + 22,那么你可以用单指令来做x86:edi+8
(但这可能只是因为该表达式是lea ecx,[eax + 4*edi + 22]
指令族的有效内存操作数,如果您需要mov
,则必须使用两个eax + 5*edi + 22
指令将该表达式分解为两个有效的内存寻址表达式,可以自己尝试将其作为练习)。如果您只使用普通的算术指令,则需要其中的四个(lea
mov ecx,edi
shl ecx,2
add ecx,eax
)。
有时你可以利用add ecx,22
进行算术运算,同时为其他正在进行的计算保留标志,比如递增指针,而CF则保留用于对值进行的持续加法。