2016-10-31 7 views
0

VGA用のI/Oポートに書き込みおよび読み取りを行うコードがあります。私はインラインアセンブラで作業Cコード機能を実装しようとしています。私はOpen Watcom 2.0を使い、DOS 16bit用にコンパイルしています。structワイドコムインラインアセンブリを使用して構造体ポインタからstructメンバーにアクセス

VGAのカラーパレットに書き込むには、これを考え出しました。これは正しく動作しません。

EDIT:setPaletteColorのコードは完全に正確ではありません。私は実際のコードを反映するように更新しました。

void setPaletteColor (unsigned char index, rgbColor *p_color) 
{ 
    _asm 
    { 
     ; tell VGA card we are going to update a palette register 
     mov dx,PALETTE_MASK 
     mov al,0xff 
     out dx,al 

     ; tell VGA which register we will be updating 
     mov dx,PALETTE_REGISTER_WR 
     mov al,index 
     out dx,al 

     ; update the color in the register at index 
     mov dx,PALETTE_DATA 
     mov al,*p_color 
     out dx,al 
     mov al,*p_color // this is actually *(p_color+1) but this actually gets the next structure not the next data member, so I left it out of the code I typed for my question. 
     out dx,al 
     mov al,*p_color // same here, actually is *(p_color+2) 
     out dx,al 
    } 
} 

また、私はこれを持っています。これも正しく動作しません。

void getPaletteColor (unsigned char index, rgbColor *p_color) 
{ 
    unsigned char *p_red = &p_color->red; 
    unsigned char *p_green = &p_color->green; 
    unsigned char *p_blue = &p_color->blue; 
    _asm 
    { 
     ; tell VGA card we are going to read a palette register 
     mov dx,PALETTE_MASK 
     mov al,0xff 
     out dx,al 

     ; tell VGA which register we will be reading 
     mov dx,PALETTE_REGISTER_RD 
     mov al,index 
     out dx,al 

     ; read the data into the color struct at 'p_color' 
     mov dx,PALETTE_DATA 
     in al,dx 
     mov *p_red,al 
     in al,dx 
     mov *p_green,al 
     in al,dx 
     mov *p_blue,al 
    } 
} 

ここでは、動作する純粋なCバージョンがあります。

void setPaletteColor (unsigned char index, rgbColor *p_color) 
{ 
    outp(PALETTE_MASK,0xff); 
    outp(PALETTE_REGISTER_WR, index); 
    outp(PALETTE_DATA,p_color->red); 
    outp(PALETTE_DATA,p_color->green); 
    outp(PALETTE_DATA,p_color->blue); 
} 

読んでください。

void getPaletteColor (unsigned char index, rgbColor *p_color) 
{ 
    outp(PALETTE_MASK,0xff); 
    outp(PALETTE_REGISTER_RD, index); 
    p_color->red = inp(PALETTE_DATA); 
    p_color->green = inp(PALETTE_DATA); 
    p_color->blue = inp(PALETTE_DATA); 
} 

注: '。'は使用できません。演算子もインラインアセンブリの ' - >'演算子もサポートしていないためです。

ここにrgbColor構造体の定義を示します。

typedef struct rgbColorTag 
{ 
    unsigned char red; 
    unsigned char green; 
    unsigned char blue; 
} rgbColor; 
+0

は助けるhttp://bos.asmhackers.net/docs/vga_without_bios/docs/palettesetting.pdfしていますか?あなたと同じことをしているように見えます。 –

+0

*注: '。'は使用できません。コンパイラはそれをサポートしていないため、インラインアセンブラの ' - >'演算子も ' - >'演算子も使用できません。* Cのローカル変数にデータを割り当て、インラインasmで読み書きします。コンパイラは実際にスタックにコピーするための余分な命令を出すような愚かなことをするかもしれません。純粋なCバージョンで何が問題になっていますか?コンパイラはそれに対して遅いコードを出しますか?インラインasmを使ってより速いコードを自分で実行することができるのはなぜだと思いますか?あるいは、 'outp'は、本来の関数ではなく、呼び出される実際の関数ですか? –

+1

@PeterCordes私のアセンブリ "getPaletteColor()"を見てください。ローカルポインタ変数を使用して、カラー構造体のメンバのオフセットを取得します。純粋なCバージョンは問題ありませんが、私はこのようなことをすべて行う方法を知りたいのです。だからこそ私は最初にDOSプログラムを書いています。これはすべての学習経験であり、これまで多くのことを学んできました。 'outp'はI/Oポートへの書き込みのためにコンパイラが提供する関数です。 'inp'と同じです。 – SeanRamey

答えて

1

どのようにうまくいかないのか良い質問がありました。ちょうどそれが "動作しない"と言って、私はWatcomスタイルのインラインasmを知らないので、それは構文エラーであると仮定しました。私はそれがMSVCスタイルと似ていると仮定し、asmでCの逆参照演算子を使用するのは構文エラーです(例:mov al,*p_color)。

明らかにこれはOpen Watcomの有効な構文ですが、は同じバイトを3回ロードしています。 2番目のバイトにmov al, *(p_color+1)を試してみてください。それはちょうどCのポインタの数学を行うかもしれませんが、次の構造体の開始点を取得します。利用可能な構文オプションについては、コンパイラのマニュアルを参照してください。


また、単にレジスタへのポインタをロードし、(mov al, [si+1]などのアドレッシングモードで)それから身をオフセットを使用することができます。これは、3つの構造体がパディングなしでレイアウトされているかどうかによって異なりますが、これは安全な前提です。コンパイラのasm出力をチェックして、構造体がどのようにレイアウトされているかを確認することができます。

構造体が正しい順序でレイアウトされているので、OUTSを使用して構造体内の3バイトをループすることができます。またはREP OUTSですら、ループを書く必要はありません。

cld 
    mov si, p_color  ; get the function arg in a register 
    mov dx, PALETTE_DATA 
    mov cx, 3 
    rep outsb    ; OUT 3 times, to port DX, using data from DS:[SI] (and do SI++ post-increment) 

同様に、読書のために、

cld 
    mov di, p_color 
    mov dx, PALETTE_DATA 
    mov cx, 3 
    rep insb    ; IN 3 times, to port DX, using data from DS:[DI] (and do DI++) 
+0

実際、私のコードはエラーや警告なしでコンパイルされ、実行されます。それは単に私が期待したことをしません。しかし、このコードをありがとう。私はそれを適応させ、それがうまくいくかどうかを見ようとします! :) – SeanRamey

+0

@SeanRamey:オハイオ州オクラホマ、私はWatcomインラインアシストがMSVCと違うと思う。これは、この方法を学ぶことが、16ビットコード以外のものでは使用できないツールや構文を学ぶために多大な時間を費やすことを意味するので、現代のC++からのasm出力を見るのを助けません。パフォーマンスカウンターのプロファイルを見ながらコードを作成したり、2016年にasmを知っておくと便利なこともあります。 –

+0

これで試しました。それは実行されますが、決して書かれていないはずの2つのランダムなピクセルを書き込むという信じられないほど奇妙な副作用で、これまでとまったく同じことをします。また、実際には、これは現代のCコードではasmでかなり役に立ちます。余計なことをすべて取り除くと、私はもっとはっきりと分かります。私もこの物の歴史的な部分が好きです。そして、私は実際のハードウェアについて信じられないほどの金額を学びます。私はこれらの本当に奇妙な状況に陥るので学びます。私がそれらを理解するまでには、私は間違いなく何かを学びました。 – SeanRamey

関連する問題