繁体   English   中英

在程序集中创建Hello World库函数并从C#调用它

[英]Creating a Hello World library function in assembly and calling it from C#

假设我们在这个答案中使用NASM: 如何在windows下的汇编中编写hellow world

关于汇编,我得到了一些关于c#或任何其他.net语言的想法和问题。

首先,我希望能够创建一个具有以下函数HelloWorld的库,该函数接受以下参数:

  • 名称

在C#中,方法签名会像这样解释: void HelloWorld(string name) ,它会打印出类似的东西

Hello World来自名字

我已经搜索了一下但是找不到那么好的和干净的材料让我开始。 我知道一些基本的装配,然后大多是gas

因此,正确方向的任何指针都非常适用。

把它们加起来

  • 在ASM(NASM)中创建一个带有一个或多个参数的例程
  • 编译并创建上述功能的库
  • 以任何.net语言包含库
  • 调用包含的库函数

奖金功能

  • 如何处理返回值?
  • 是否可以内联编写ASM方法?

在程序集或c中创建库时,您确实遵循某种“预定义”方式,即c调用对话,是否正确?

像这样的东西应该让你一个工作的DLL:

extern _printf

section .text
global _hello
_hello:
    push ebp
    mov ebp, esp

    mov eax, [ebp+12]
    push eax
    push helloWorld
    call _printf
    add esp, 8
    pop ebp
    ret

export _hello

helloWorld: db 'Hello world from %s', 10, 0

然后你只需要使用P / Invoke调用'hello'函数。 它不会自行清理,所以你需要将CallingConvention设置为Cdecl; 你还需要告诉它你正在使用ANSI字符串。 未经测试,但它应该工作正常。

using System.Runtime.InteropServices;

namespace Test {
    public class Test {
        public static Main() {
            Hello("C#");
        }

        [DllImport("test.dll", EntryPoint="hello", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)]
        public static extern Hello(string from_);
    }
}

我将首先介绍做你想做的基本指导。然后我将尝试解释如何做Hello World示例。

第一步是编写一个函数,并从中创建dll。 程序集中的函数应该遵循一个调用标准,stdcall是最常见的一个(你可以在这里阅读更多关于stdcall和其他调用标准的内容)在这里可以找到用asm创建一个dll的例子

第二步是使用P / Invoke以托管语言导入方法。 你可以在这里阅读更多相关信息

就是这样......

现在,对于您提到的示例,您需要创建一个asm函数,它接受所有输入参数并将其传递给知道如何打印到stdout的其他函数(如上所述,从标准c lib中打印printf,或者使用像这里的 winapi调用)

之后,您需要将dll导入C#,如上所述。 您应该特别注意的事项是字符串的字符编码和数据清理。 它们都在我提供的第3个链接中提到(编组文本部分)。

奖金部分:

  • 处理返回值取决于使用的调用约定
  • 用C#编写内联汇编是不可能的。 但是,您可以使用托管C ++编写它们。

这是一个非常好的问题,值得我投票。 关于你的问题,Cody指出他的汇编程序例程的唯一方法是基于它构建一个DLL,并从那里使用p / Invoke使用interops如

[DllImport("mylib.dll")]

但是,遗憾的是,由于C#或任何其他语言的性质,CLR运行时环境正在使用托管代码。 让CLR或汇编程序设置堆栈框架,注册,然后从本地世界交叉跳​​转到托管世界会很尴尬。 这将是一件毛茸茸的工作,但如果有人见过这样的事情,请在我的答案结尾留下评论,我会相应地修改这个答案。

因此,据我所知,没有办法通过汇编程序在汇编程序中内联汇编程序,使用系统寄存器(如eax,ebx,堆栈帧等)转换为CLR代码,就像Cody的代码示例一样以上提供了他的答案。 在这种情况下,它将适用于C / C ++:

void foo(void){
   _asm{
     xor ecx, ecx
     mov eax, 1
     ....
   }
}

从CLR的角度来看这样做会很好,以便进一步优化代码,至少在理论上这对于CLR实际托管这类事情是一个不可逾越的工作,有一个例外。它可以使用Managed C ++编译器来完成,但不能从VB.NET / C#中完成:

private void mycsfunction(string s){
    // Managed code ahoy
    StringBuilder sb = new StringBuilder(s);
    ......
    _asm{
        push ebp
        mov ebp, esp
        lea edx, offset sb
        ....
        mov eax, 1
        pop ebp
    }
}

然而,在这个主题上,可以完成生成IL代码到本地汇编程序,现在,正如我写的那样,我不是100%确定是否可以反向完成,请参阅此处以获取详细说明可以发生

但是 ,处理CLR程序集的唯一方法是手写IL代码并改为编译它,即直接编译CLR运行时的汇编程序,与本机汇编程序可以被本机调用的方式非常相似(读取NON)二进制-CLR),看到这个文章在这里就如何也做到这一点。

在我看来,你的问题是双重的:

  1. 如何使用程序集编写函数并将其放入DLL中?
  2. 如何从托管C#调用非托管DLL中的函数?

2的答案是使用P / Invoke。 有关该主题的大量文档和教程,例如http://msdn.microsoft.com/en-us/magazine/cc164123.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM