我学习汇编程序。我练习这段代码:
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中没有?
答案 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
也许这是造成一些麻烦的原因。