2017-09-10 9 views
0

私はリアルタイムクロックを読むためのインラインアセンブリコードを書いています。私は 'dl'に読み込まれるレジスタ番号(4)をロードし、これをポート0x70にロードしています。私はこのレジスタ値(4)をalに読み込もうとしています。詳細については - RTCGNUアセンブラの構文

asm(
"mov $4, %%dl;" 
"out 0x70, %%dl;" 
"in %%al, 0x71;" 
: 
: 
:"%al","%dl" 
); 

私はこのコードが含まれているCファイルをコンパイルするには、以下のエラーメッセージを取得しています。

Assembler messages:

Error: operand size mismatch for 'out'

Error: operand size mismatch for `in'

アセンブラバージョン:GNUアセンブラバージョン2.26.1(x86_64版 - のlinux-gnuの)(UbuntuのためにGNU Binutilsの)BFDバージョンを使用して2.26.1

誰かが問題を指摘していただけますか?

+3

エラーメッセージは、定数の前に '$'がないためです。つまり、asmに値を出力させたい場合は、最初のコロンの後に出力パラメータを設定する必要があります。あなたがUbuntuを実行しているときに 'in'または' out'を使うことができれば、私は驚くでしょう。 RTCを読む前に 'cli'するつもりはありませんか?そして、もしあなたが16ビットコードを構築しているなら、私は64ビットコンパイラを使うことがうまくいかないと思っています。また、ブート時にRTCを読み込もうとしている場合は、[こちら](https://stackoverflow.com/q/46074535/2189500)をご覧ください。 –

+2

AT&Tの構文では、通常、右側に宛先があります。私は、IN命令とOUT命令も同様に期待しています。 'IN 0x71、%% al'? –

+0

@DavidWohlferd 'iopl()'や 'ioperm()'システムコールを使って 'in'と' out'を使うことができます。 – fuz

答えて

4

多くの問題があります。まず、inoutの両方は、Aレジスタ(al,axeaxrax)でのみ動作します。第2に、オペランドの順序が間違っていて、第3に、即時は接頭辞$(AT & T構文)でなければなりません。プレーンアセンブリでは、あなたのコードは次のようになります。

mov $4,%al 
out %al,$0x70 
in $0x71,%al 

をだからあなたの修正アセンブリが、私はこのコードをアセンブル打ち鳴らす支援するために、明示的なサイズのサフィックスを追加した

asm(
"movb $4, %%al;" 
"outb %%al, $0x70;" 
"inb $0x71, %%al;" 
: 
: 
:"%al" 
); 

注だろう。私はさらに、正しい拡張インラインアセンブリを使用するには、このコードを変更することをお勧めいたします:

unsigned char result; 
volatile asm("outb %1,$0x70; inb $0x71, %0" : "=a"(result) : "a"((char)4)); 

これはgccがわずかに良いコードを生成作ることができます。たとえば、gccはこのコードをインライン化できます。

また、とoutb()のマクロを<sys/io.h>から使用することで、インラインアセンブリを完全に回避することもできます。これは典型的には非常に良いことです。

+0

このような詳細な回答ありがとうございました。このような構文エラーを避けるために、インラインアセンブリのAT&T構文に関する包括的なガイドを教えてください。 – SilentMonk

+0

@SilentMonk GNUアセンブラのマニュアルを読んでください。 – fuz

+0

また、ソースとしてdlの出力命令がないことを示す良い命令セット参照を取得する必要があります。私はIntelのマニュアル(https://software.intel.com/en-us/articles/intel-sdm)を使用しています。 – prl

関連する問題