c#with Assembler dll

时间:2015-12-03 01:05:25

标签: c# arrays string assembly dll

我使用汇编程序dll编写程序并尝试将汇编程序中的函数添加到我的c#程序中,这将从c#中返回字符串中的字符数量。

c#program:

[DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int zlicz(string tab);

 private void button4_Click(object sender, EventArgs e)
        {

             int pom=0;
            string tab = "1111111fdgsdgdgd";

            pom = zlicz(tab);


        }

和我的汇编代码:

myprocedure proc 


push ebp
mov  ebp, esp

mov  ebx, [ebp+8]           ; begin of char array

xor eax, eax

check:

cmp byte ptr[ebx],0    ; if end of array 
je endprocedure
inc ebx
inc eax 
jmp check
endprocedure:    

pop ebp

ret 

myprocedure endp

但它仅适用于具有超过100个元素的字符串,例如7个元素,此程序崩溃并出现错误:

  

GUI.exe中出现未处理的“System.ExecutionEngineException”类型异常

有人可以帮我解决这个问题,因为我想使用少于100个元素的字符串。

1 个答案:

答案 0 :(得分:0)

动态链接库需要一个以null结尾的ansi字符串,并且您传递的是一个前缀为BSTR的长度

根据MSDN documentation, Default Marshaling for Strings,以下签名:

DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure(string tab);

将字符串变量选项卡封送为UnmanagedType.BStr

虽然根据这张表:

UnmanagedType.BStr (default)
    A COM-style BSTR with a prefixed length and Unicode characters.  
UnmanagedType.LPStr
    A pointer to a null-terminated array of ANSI characters.  
UnmanagedType.LPWStr
    A pointer to a null-terminated array of Unicode characters.

您需要将标签变量标记为UnmanagedType.LPStr

这可以通过以下方式轻松实现:

DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure([MarshalAs(UnmanagedType.LPStr)] string tab);

然而,

这会将字符串编组为每个字符一个字节,这意味着,您传递的是ANSI字符串,而不支持unicode。

要支持unicode字符,只需将非托管类型规范更改为UnmanagedType.LPWStr

即可
DllImport("bibliotekaASM.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int myprocedure([MarshalAs(UnmanagedType.LPWStr)] string tab);

但是,在这种情况下,您还应该更新汇编代码以读取unicode字符(我可以想象这不是一个简单的任务)

注意:我通过使用MASM32编译dll并从C#调用它来复制该问题,并成功测试了建议的解决方案LPStr。