是否可以在装配中取消引用某些内容?

时间:2017-07-19 23:31:59

标签: assembly x86 masm dereference

考虑使用以下值填充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处的双字是数组的索引。
有没有办法真正将EDI移到地址ESI + 4 * the dword at address EBP - 4的双关语中?或者我是以错误的方式看待这个?

3 个答案:

答案 0 :(得分:4)

你使这个程序过于复杂。您需要做的就是:

 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易变,但如果你需要保留它们,一定要。

答案 1 :(得分:3)

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]处的值将在您的双字阵列中保存递增索引。我看到了这个小问题的两个解决方案:

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

    mov eax, [ebp-4]
    mov [esi+eax*4], edi
    inc [ebp-4]
    
  2. 您根本不使用本地变量,并将索引保​​存在寄存器中:

    mov [esi+eax*4], edi
    inc eax
    
  3. 要考虑的错误:

    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
    

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

答案 2 :(得分:2)

它需要两条指令:

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

您还可以考虑在功能的前导码和尾声中保存/恢复EAX。在大多数环境中,不需要保留EAX。