转换帮助:__ asm__ __volatile__

时间:2011-12-23 10:08:31

标签: c assembly d inline-assembly

我想将C的outb函数移植到D。

static __inline void outb (unsigned char value, unsigned short int port)
{
    __asm__ __volatile__ ("outb %b0,%w1"
                          :
                          :
                         "a" (value),
                          "Nd" (port));
}

这是D版。

extern(C) 
{
    void outb (ubyte value, ushort port)
    {
        // I couldn't figure out this part
   }

}

这些是关于这个主题的一些链接。

D内联汇编程序

http://dlang.org/iasm.html

GCC-串联装配-HOWTO

http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

但我不懂汇编语言,所以我需要一些帮助。任何帮助,将不胜感激。感谢。

2 个答案:

答案 0 :(得分:9)

outb指令只应调用为outb %al, %dx,其中%al为值,%dx为端口。

D使用x86的Intel语法,而不是默认使用AT& T语法的GNU汇编程序。相应的Intel语法为out dx, al,D中的相应代码如下所示:

void outb (ubyte value, ushort port)
{
    asm {
        mov AL, value;
        mov DX, port;
        out DX, AL;
    }
}

请注意,您根本不需要编写程序集,因为druntime具有执行相同指令的core.bitop.outp函数。

void outb (ubyte value, ushort port)
{
    import core.bitop;
    outp(port, value);
}

答案 1 :(得分:5)

第一件可能让你失望的事情是,D编译器支持的操作码列表不包括outb,正如您提供的C函数所指定的那样。经过一番挖掘后,我发现outb是一般操作码out的更具体的名称。 outb表示操作码的第一个参数将包含在字节寄存器中(与outwoutl相对,它分别表示一个字的第一个参数大小和一个但是,D编译器对所有操作使用操作码out,并根据您指定的参数的大小确定要编写的特定操作码。

有了这个,接下来要做的就是将GCC语法转换为D语法。根据GCC-Inline-Assembly-HOWTO,您提供的代码使用扩展汇编语法:

asm ( assembler template 
    : output operands                  /* optional */
    : input operands                   /* optional */
    : list of clobbered registers      /* optional */
    );

查看模板,该函数指定一个带有两个参数的汇编指令(outb),第一个是字节(%b0),第二个是字或短整数({{1 }})。

关于输入参数列表的棘手问题是为每个函数参数添加前缀的字符串。根据HOWTO,这些被称为约束。它们本质上是GCC必须遵循的规则,使用参数作为提供的汇编指令的参数。应用于%w0参数的约束"a"表示变量的内容必须放在注册valueeaxax中,具体取决于变量的大小。对al变量port的约束首先表示该值在0-255范围内,其次,该值必须放在寄存器"Nd"中,{ {1}}或edx,再次根据变量的大小。

D编译器不像GCC那样提供组装块中变量的帮助;在D的内联汇编程序中,您需要专门将参数值移动到适当的寄存器中。对于dx,这些寄存器为dloutb。遵循D的内联汇编语法,您可以移动变量并按如下方式调用dx操作码:

al

请注意,由于GCC使用AT& T汇编语法,而D使用英特尔汇编语法,因此提供给out的参数顺序相反。