转换帮助:__asm__ __volatile__

发布于 2024-12-22 18:08:18 字数 817 浏览 0 评论 0原文

我想将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-汇编-HOWTO

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

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

I would like to port C's outb function to D.

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

This is D version.

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

}

These are some links about the subject.

D Inline Assembler

http://dlang.org/iasm.html

GCC-Inline-Assembly-HOWTO

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

But I don't know assembly language so I need some help. Any help would be appreciated. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身以后 2024-12-29 18:08:18

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);
}

The outb instruction should only be called as outb %al, %dx where %al is the value and %dx is the port.

D uses Intel syntax for x86, as opposed to GNU assembler which uses the AT&T syntax by default. The corresponding Intel syntax would be out dx, al, and corresponding code in D would look like:

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

Note that you don't need to write the assembly at all, because druntime has the core.bitop.outp function which perform the same instruction.

void outb (ubyte value, ushort port)
{
    import core.bitop;
    outp(port, value);
}
小鸟爱天空丶 2024-12-29 18:08:18

可能让您困惑的第一件事是 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" 指示变量的内容必须放置在寄存器 eaxax 中al 取决于变量的大小。 port 变量 "Nd" 的约束首先表明该值在 0-255 的范围内,其次表明该值必须放置在根据变量的大小再次注册 edxdxdl

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

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

请注意,由于 GCC 使用 AT&T 汇编器语法,而 D 使用 Intel 汇编器语法,因此提供给 OUT 的参数被颠倒。

The first thing that's probably tripping you up is that the D compiler's supported list of opcodes does not include outb, as specified by the C function you provided. After some digging, I've found out that outb is a more specific name for the general opcode out. outb indicates that the first argument to the opcode will be contained in a byte register (as opposed to outw and outl, which indicate a first argument size of, respectively, a word and a double word), however, the D compiler uses the opcode out for all of the operations, and determines which specific opcode to write based on the size of the argument you specify.

With that out of the way, the next thing to do is to convert the GCC syntax to D syntax. According to the GCC-Inline-Assembly-HOWTO, the code you provided uses the extended assembly syntax:

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

Looking at your template, the function specifies one assembly instruction (outb) with two arguments, the first being a byte (%b0) and the second being a word or short integer (%w0).

The tricky bit about the input arguments list is the string that prefixes each of your function parameters. These, according to the HOWTO, are called constraints. They're essentially rules that GCC must follow in using the parameters as arguments to the provided assembly instructions. The constraint "a" applied to the value parameter indicates that the contents of the variable must be placed in either register eax, ax, or al depending on the size of the variable. The constraint on the port variable, "Nd", indicates first that the value is in the range of 0-255, and second, that the value must be placed in either register edx, dx, or dl, again, based upon the size of the variable.

The D compiler doesn't offer as much help with variables in assembly blocks as GCC does; in D's inline assembler, you'll need to specifically move the values of the parameters into the proper registers. For outb, these registers are dx and al. Following D's inline assembly syntax, you can move the variables and call the out opcode as follows:

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

Note that, because GCC uses the AT&T assembler syntax, and D uses the Intel assembler syntax, the order of the arguments provided to OUT is reversed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文