是否可以在汇编中的取消引用中取消引用某些内容?

Is it possible to dereference something inside of a dereference in assembly?

考虑以下用值填充双字数组并接受 2 个参数的过程:EBP + 08h 是数组的大小,EBP + 0Ch 是给定数组的偏移量. (即 OFFSET myarray):

MyProc PROC
PUSH EBP
MOV EBP, ESP
SUB ESP, 04h
PUSH EDI
PUSH ESI
PUSH EBX
MOV EBX, [EBP + 08h] ;move the size of the array into EBX
MOV [EBP - 04h], 00h ;EBP - 04h will be the counter (or the index.)
MOV ESI, [EBP + 0Ch] ;move the offset of the array into ESI
MOV EDI, 01h
INC EBX
@@:


MOV [ESI + 04h * [EBP - 04h]], EDI ;How can I actually move EDI into
;the dword found at address ESI + 4 * the value found at address EBP - 4?


INC [EBP - 04h] ;increment the counter and the value to be stored.
INC EDI
CMP [EBP - 04h], EBX
JNE @B
POP EBX
POP ESI
POP EDI
MOV ESP, EBP
POP EBP
RET
MyProc ENDP

我尝试将 EDI 移动到 [ESI + 04h * [EBP - 04h]] 的地方是我正在尝试做的一个例子,因为地址 EBP - 4 处的双字是数组的索引。
有什么方法可以将 EDI 实际移动到地址 ESI + 4 * the dword at address EBP - 4 的双字中吗?还是我看错了?

需要两条指令:

MOV    EAX, [EBP - 04h]
MOV   [ESI + 4*EAX], EDI

您还可以在函数的序言和尾声中考虑 saving/restoring EAX。在大多数环境下,EAX不需要保留。

你把这个过程搞得太复杂了。您需要做的就是:

 push  ebp
 mov   ebp, esp

 xor   eax, eax            ; Fill buffer with nulls
 mov   ecx, [ebp+8]        ; Number of dwords to fill
 push  edi
 mov   edi, [ebp+12]
 rep   stosd
 pop   edi

 leave
 ret   8                    ; Pop arguments passed by caller

大多数 ABI 认为 EAX、ECX 和 EDX 是易变的,但如果您需要保留它们,一定要保留。

MOV [ESI + 04h * [EBP - 04h]], EDI ;How can I actually move EDI into
       ;the dword found at address ESI + 4 * the value found at address EBP - 4?
INC [EBP - 04h] ;increment the counter and the value to be stored.

[EBP-4] 处的值将在您的双字数组中保存递增索引。我看到这个小问题有 2 个解决方案:

  1. 您继续使用局部变量并分两步编写有问题的指令:

    mov eax, [ebp-4]
    mov [esi+eax*4], edi
    inc [ebp-4]
    
  2. 你根本不用局部变量,把索引保存在一个寄存器中:

    mov [esi+eax*4], edi
    inc eax
    

要考虑的错误:

INC EBX

这个inc会给你太多的1次迭代!


假设您想用递增的值填充数组,这些值恰好比元素的索引大 1 (a[0]=1, a[1]=2, a[2]=3,. ..) 您可以通过预先增加索引并通过从地址中减去 4 来补偿此操作来编写更好的例程:

MyProc PROC
PUSH EBP
MOV  EBP, ESP
PUSH ESI

xor  eax, eax         ;EAX will be the counter (or the index.)
mov  esi, [ebp + 12]  ;move the offset of the array into ESI
@@:
inc  eax              ;increment the counter and the value to be stored.
mov  [esi + eax * 4 - 4], eax
cmp  eax, [ebp + 8]   ;Compare index to size of the array
jb   @B

POP ESI
MOV ESP, EBP
POP EBP
RET
MyProc ENDP

使用的寄存器越少也意味着要保留的寄存器越少!