请考虑以下过程,该过程用值填充dword数组,并接受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
处的 dword 是数组的索引。
有没有办法在地址ESI + 4 * the dword at address EBP - 4
处实际将EDI
移动到dword中?还是我看错了?
你使这个过程过于复杂。您需要做的就是:
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]
处的值将在 dword 数组中保存一个递增索引。我看到这个小问题的 2 个解决方案:
-
您继续使用局部变量,并通过 2 个步骤编写有问题的指令:
mov eax, [ebp-4] mov [esi+eax*4], edi inc [ebp-4]
-
您根本不使用局部变量,并将索引保存在寄存器中:
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
使用的寄存器更少也意味着需要保留的寄存器更少!
它需要两个指令:
MOV EAX, [EBP - 04h]
MOV [ESI + 4*EAX], EDI
您还可以考虑在函数的前言和尾声中保存/恢复 EAX。 在大多数环境中,不需要保留 EAX。