2011-12-23 79 views
8

我想C口的OUTB功能D.轉換的幫助:__asm__ __volatile__

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

但我不知道彙編語言,所以我需要一些幫助。任何幫助,將不勝感激。謝謝。

回答

8

outb指令應該只被稱爲outb %al, %dx其中%al是值和%dx是端口。

D使用x86語法的Intel語法,與GNU彙編程序默認使用AT & T語法相反。相應的英特爾語法將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); 
} 
4

這可能絆倒您的第一件事是,d編譯器所支持的操作碼的名單不包括outb,爲您提供的C函數指定。經過一番挖掘,我發現outb是通用操作碼out的更具體名稱。 outb表示操作碼的第一個參數將包含在一個字節寄存器中(而不是outwoutl,分別表示一個字和一個雙字的第一個參數大小),但是,D編譯器使用操作碼out,並根據您指定的參數的大小確定要寫入哪個特定的操作碼。

因此,接下來要做的就是將GCC語法轉換爲D語法。按照GCC-內聯彙編-HOWTO,你所提供的代碼使用擴展彙編語法:

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

在你的模板來看,該函數指定用兩個參數一個彙編指令(outb),第一個是字節(%b0),第二個是一個字或短整數(%w0)。

關於輸入參數列表的棘手一點是爲每個函數參數添加前綴的字符串。根據HOWTO,這些被稱爲約束。它們基本上是GCC必須遵循的規則,使用參數作爲提供的彙編指令的參數。應用於value參數的約束"a"指示變量的內容必須放置在寄存器eax,axal中,具體取決於變量的大小。對port變量"Nd"的約束首先指示該值在0-255的範圍內,其次指示該值必須再次放置在寄存器edxdxdl中,基於該變量的大小變量。

D編譯器不能像GCC那樣爲彙編塊中的變量提供儘可能多的幫助;在D的內聯彙編程序中,您需要特別將參數的值移動到正確的寄存器中。對於outb,這些寄存器是dxal。繼D的內聯彙編語法,你可以移動的變量並調用out操作碼如下:

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

需要注意的是,由於GCC使用AT &牛逼彙編程序語法,和d採用了Intel彙編語法,秩序提供給OUT的論據是相反的。