【问题标题】:Converting help: __asm__ __volatile__转换帮助:__asm__ __volatile__
【发布时间】:2012-01-26 17:38:05
【问题描述】:

我想将 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-Inline-Assembly-HOWTO

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

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

【问题讨论】:

    标签: c assembly d inline-assembly


    【解决方案1】:

    outb 指令只能称为outb %al, %dx,其中%al 是值,%dx 是端口。

    D 对 x86 使用 Intel 语法,而 GNU 汇编器默认使用 AT&T 语法。对应的 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);
    }
    

    【讨论】:

      【解决方案2】:

      第一件事可能让您感到困惑的是,D 编译器支持的操作码列表不包括您提供的 C 函数指定的 outb。经过一番挖掘,我发现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),第二个是字或短整数 (%w0)。

      输入参数列表的棘手之处在于每个函数参数的前缀字符串。根据 HOWTO,这些被称为约束。它们本质上是 GCC 在使用参数作为提供的汇编指令的参数时必须遵循的规则。应用于value 参数的约束"a" 指示变量的内容必须放在寄存器eaxaxal 中,具体取决于变量的大小。对port 变量"Nd" 的约束首先表明该值在0-255 的范围内,其次该值必须放在寄存器edxdx 或@987654341 中。 @,同样,基于变量的大小。

      D 编译器对汇编块中的变量提供的帮助不如 GCC 那么多;在 D 的内联汇编器中,您需要专门将参数的值移动到适当的寄存器中。对于outb,这些寄存器是dxal。按照 D 的内联汇编语法,您可以移动变量并调用out 操作码,如下所示:

      asm
      {
          MOV AL, value;
          MOV DX, port;
          OUT DX, AL;
      }
      

      请注意,因为 GCC 使用 AT&T 汇编语法,而 D 使用 Intel 汇编语法,所以提供给 OUT 的参数的顺序是相反的。

      【讨论】:

        猜你喜欢
        • 2013-02-03
        • 2016-11-24
        • 2010-11-26
        • 2011-05-17
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多