2017-11-24 23 views
3

アセンブリの深さはわかりません。以下のコードは、ハードウェアポートに書き込むためのコードです。私はコンパイルused.Whenインラインasm: 'out'のオペランドタイプの不一致

コンパイラがインラインアセンブラがあるすべての行にオペランドの型の不一致エラーを与える私はこれらのエラーを取得:

port.cpp: Assembler messages: 
port.cpp:27: Error: operand type mismatch for 'out' 
port.cpp:34: Error: operand type mismatch for 'in' 
port.cpp:51: Error: operand type mismatch for 'out' 
port.cpp:69: Error: operand type mismatch for 'out' 
port.cpp:75: Error: operand type mismatch for 'in' 
port.cpp:94: Error: operand type mismatch for 'out' 
port.cpp:100: Error: operand type mismatch for 'in' 

port.h

#ifndef __PORT_H 
#define __PORT_H 

#include "types.h" 


class Port 
{ 
    protected: 
     Port(uint16_t portnumber); 
     ~Port(); 
     uint16_t portnumber; 
}; 


class Port8Bit : public Port 
{ 
    public: 
     Port8Bit(uint16_t portnumber); 
     ~Port8Bit(); 

     virtual uint8_t Read(); 
     virtual void Write(uint8_t data); 
}; 



class Port8BitSlow : public Port8Bit 
{ 
    public: 
     Port8BitSlow(uint16_t portnumber); 
     ~Port8BitSlow(); 

     virtual void Write(uint8_t data); 
}; 



class Port16Bit : public Port 
{ 
    public: 
     Port16Bit(uint16_t portnumber); 
     ~Port16Bit(); 

     virtual uint16_t Read(); 
     virtual void Write(uint16_t data); 
}; 



class Port32Bit : public Port 
{ 
    public: 
     Port32Bit(uint16_t portnumber); 
     ~Port32Bit(); 

     virtual uint32_t Read(); 
     virtual void Write(uint32_t data); 
}; 

#endif 

port.cpp

#include "port.h" 


Port::Port(uint16_t portnumber) 
{ 
    this->portnumber = portnumber; 
} 

Port::~Port() 
{ 
} 



Port8Bit::Port8Bit(uint16_t portnumber) 
    : Port(portnumber) 
{ 
} 

Port8Bit::~Port8Bit() 
{ 
} 

void Port8Bit::Write(uint8_t data) 
{ 
    __asm__ volatile("outb %0, %1" :: "a" (data), "Nd" (portnumber)); 
} 

uint8_t Port8Bit::Read() 
{ 
    uint8_t result; 
    __asm__ volatile("inb %1, %0" : "=a" (result) : "Nd" (portnumber)); 
    return result; 
} 



Port8BitSlow::Port8BitSlow(uint16_t portnumber) 
    : Port8Bit(portnumber) 
{ 
} 

Port8BitSlow::~Port8BitSlow() 
{ 
} 

void Port8BitSlow::Write(uint8_t data) 
{ 
    __asm__ volatile("outb %0, %1\njmp 1f\n1: jmp 1f\n1:" :: "a" (data),  "Nd" (portnumber)); 
} 





Port16Bit::Port16Bit(uint16_t portnumber) 
    : Port(portnumber) 
{ 
} 

Port16Bit::~Port16Bit() 
{ 
} 

void Port16Bit::Write(uint16_t data) 
{ 
    __asm__ volatile("outw %0, %1" :: "a" (data), "Nd" (portnumber)); 
} 

uint16_t Port16Bit::Read() 
{ 
    uint16_t result; 
    __asm__ volatile("inw %1, %0" : "=a" (result) : "Nd" (portnumber)); 
    return result; 
} 





Port32Bit::Port32Bit(uint16_t portnumber) 
    : Port(portnumber) 
{ 
} 

Port32Bit::~Port32Bit() 
{ 
} 

void Port32Bit::Write(uint32_t data) 
{ 
    __asm__ volatile("outl %0, %1" :: "a" (data), "Nd" (portnumber)); 
} 

uint32_t Port32Bit::Read() 
{ 
    uint32_t result; 
    __asm__ volatile("inl %1, %0" : "=a" (result) : "Nd" (portnumber)); 
    return result; 
} 

どうすれば修正できますか?プログラムの構造に何か問題はありますか?

+0

あなたのクラスに 'portnumber'がどのように宣言されているかを教えてもらえますか? –

+1

あなたは 'portnumber'を' uint16_t'以外のものに定義した可能性があります。レジスタ_DX_を使用する必要があります(_EDX_、_RDX_、_DL_ではなく)。 –

+2

'' Nd(portnumber) ''を '' Nd '((uint16_t)portnumber) 'に変更したり、' 'portnumber'を' uint16_t'に変更したり、 '%1'を変更したりすると、 '%w1'になります。私は個人的に 'portnumber'のタイプをuint16_tに変更したいと思います。 –

答えて

0

OPにはtypes.hが表示されませんでしたが、実際には1つの可能性があり、16ビットタイプとしてはuint16_tは定義されていませんでした。 x86/x86-64の上にそのようなタイプで定義することができる。

typedef unsigned short int uint16_t; 

拡張インラインアセンブリテンプレートのレジスタを選択するために、GCCが制約に渡されたタイプのサイズを使用しているため、誤差が約来選択されたレジスタが16/32/64ビットレジスタでなければならないかどうかを決定する。サイズが16ビットでない場合、誤ったサイズのレジスタが選択され、生成されたアセンブリはオペランドの不一致を有する。

この場合、明らかにOPは自分自身のuint16_t定義を作成したときに間違ったサイズタイプを指定しました。ポート・コマンドは(アウト等で)のみレジスタオペランドとしてDX(16ビット)、ないEDX、又はRDX又はDLを取ります。生成されたレジスタがDXではない場合、コードはOPが見ているエラーでコンパイル/アセンブルされていました。