运行与调试=汇编程序中的不同结果

时间:2015-02-03 10:41:53

标签: c# assembly

我学习汇编程序。我练习这段代码:

ASM:

    ;-------------------------------------------------------------------------
.586 

.MODEL flat, stdcall
public srednia_harm 


OPTION CASEMAP:NONE

INCLUDE    include\windows.inc
INCLUDE    include\user32.inc
INCLUDE    include\kernel32.inc 

.CODE

    jeden dd 1.0

DllEntry PROC hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD

    mov eax, TRUE  
    ret

DllEntry ENDP

;-------------------------------------------------------------------------
;-------------------------------------------------------------------------


srednia_harm     PROC

    push ebp
    mov esp,ebp

    push esi
    mov esi, [ebp+8] ; address of array
    mov ecx, [ebp+12] ; the number of elements

    finit
    fldz ; the current value of the sum - st(0)=0

    mianownik:
    fld dword PTR jeden ;ST(0)=1, ST(1)=sum

    fld    dword PTR [esi] ;loading of array elements - ST(0)=tab[i], ST(1)=1 ST(2)=suma

    fdivp st(1), st(0) ; st(1)=st(1)/(st0) -> ST(0)=1/tab[i], ST(1)=suma

    faddp st(1),st(0) ; st(1)=st(0)+st(1) -> st(0)=suma+1/tab[i]

    add esi,4
    loop mianownik

    pop esi
    pop ebp
    ret


srednia_harm  ENDP


;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
END DllEntry

DEF:

LIBRARY "biblioteka"
EXPORTS
srednia_harm

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace GUI
{
    unsafe class FunkcjeAsemblera //imports of assembler's function
    {
        [DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern float srednia_harm(float[] table, int n);

        public float wywolajTest(float[] table, int n)
        {
            float wynik = srednia_harm(table, n);
            return wynik;
        }

    }
}

C#:

 private void button6_Click(object sender, EventArgs e)
        {
            FunkcjeAsemblera funkcje = new FunkcjeAsemblera();
            int n = 4;
            float[] table = new float[n];
            for (int i = 0; i < n; i++)
                table[i] = 1;
            float wynik = funkcje.wywolajTest(table, n);
            textBox6.Text = wynik.ToString();
        }

当我运行此代码时,一切都很好。结果是我预期的4。但我试着理解那段代码,所以我在ASM函数中设置了很多断点。然后问题就开始了。 Arrat确实应该在内存中,但是seond参数丢失了。地址指向内存中的空字段。我尝试了很多组合,我改变了类型,它仍然是相同的。 我做了一些研究,但我没有找到任何线索。怎么可能当我运行程序时一切正常并且在DEBUG中没有?

1 个答案:

答案 0 :(得分:1)

好的,我在调试和发布模式下对此进行了测试。我启用了Properties-&gt; Debug-&gt; EnableNativeCodedebugging。它适用于两种情况下的Step Into(F11)。正确访问'n'变量。

我注意到的一个问题是PROC设置不正确。上面的代码访问相对于EBP的两个变量,但不清理堆栈(stdcall [其中被调用者负责清理堆栈] @Wikipedia。)

push        ebp  
mov         esp,ebp  
push        esi  
mov         esi,dword ptr [ebp+8]  
mov         ecx,dword ptr [ebp+0Ch]  
wait  
...
add         esi,4  
loop        6CC7101F  
pop         esi  
pop         ebp  
ret         <-- two params not cleaned up

以下是PROC标题下面汇编的代码:

push        ebp  
mov         ebp,esp  
push        esi  
mov         esi,dword ptr [ebp+8]  
mov         ecx,dword ptr [ebp+0Ch]  
wait  
... 
add         esi,4  
loop        6CC7101F  
pop         esi  
leave       <-- restores EBP
ret         8     <-- two params cleaned up

我建议将PROC更改为

srednia_harm PROC uses esi lpArr: DWORD, num: DWORD
  mov esi, lpArr
  mov ecx, num
  ...
  ret
srednia_harm  ENDP

也许这是造成一些麻烦的原因。