Visual C/C++ と MASM で作成されたサンプルプログラムを使用したビデオカードの動作検証とは

このQ&Aのポイント
  • Microsoft Visual C/C++ と MASM で作成されたサンプルプログラムを使用してビデオカードの動作検証をしていますが、アセンブラが解らない上ハード寄りのプログラミング経験が乏しく、取得/設定したい情報を思うように操作できません。
  • 今後、コードをカスタマイズするにあたり、可能な部分はCへ置き換えたいと思っています。MASMで記述されている動作をCでどのように記述すればよいかについてのアドバイスを求めています。
  • セグメントの取得についてFP_SEG(),FP_OFF()関数を使用することを考えていますが、上手く扱えません。質問者はC言語を使用してセグメント情報を取得・設定したいという目的を持っています。
回答を見る
  • ベストアンサー

Segment情報の取得と設定

始めまして,宜しくお願いします. 現在,Microsoft Visual C/C++ と MASM で作成された サンプルプログラムを使用してビデオカードの動作検証をしていますが, アセンブラが殆ど解らない上ハード寄りのプログラミング経験が乏しく, 取得/設定したい情報を思うように操作できません. 今後,コードをカスタマイズするにあたり, (特に高速動作を期待するわけではないので) 可能な部分はCへ置き換えたいと思っています. MASMで下記のように記述された動作をCで記述するにはどうすればよいでしょうか. ;------------------------------------------ move ax, xxxxxh move es, ax ; es -> VRAMセグメント xxxxxh assume es: nothing 中略 move es:[di], bl ; blに格納されているデータをVRAMに設定 ;------------------------------------------ セグメントの取得についてFP_SEG(),FP_OFF()関数 を使用すれば良いのかと考えていますが上手く扱えません. 宜しくご教授願います.

質問者が選んだベストアンサー

  • ベストアンサー
noname#30727
noname#30727
回答No.1

なんとなく、記憶が曖昧なのですが、 unsigned char far *di; のように di があって、これは 32ビットのポインタで、上位 16 ビットがセグメント、下位 16 ビットがオフセットです。 例えば、 di = (unsigned char far *)0xABCD0123; とすると、セグメントが 0xABCD で、オフセットが 0x0123 としてfar ポインタに代入できます。 このポインタを使って、 *di = bl; とすれば、0ABCDH:0123H に 何かを書き込めます。 確か、ポインタに対する演算は、オフセットの部分だけに対してされたと思います。 di = (unsigned char far *)0xA0000000; di--; // di == 0xA000FFFF; FP_SEG と FP_OFF が far ポインタのセグメントとオフセットを個別に書き換える事ができたかどうかは忘れましたが、そういうマクロがなければ、とにかく書き換えてしまえば動いたような気がします。 ((unsigned int *)&di)[0] = offset; ((unsigned int *)&di)[1] = segment;

redcyclone
質問者

お礼

有難うございました. 正常にセグメント情報を取得できました. 今後とも何かとお世話になる機会があるかと思いますが, 宜しくお願いします.

その他の回答 (1)

noname#30727
noname#30727
回答No.2

確認するのを忘れたのですが、 Microsoft Visual C/C++ は、Ver.1.0 の 16ビット版の奴ですよね?

redcyclone
質問者

お礼

そうです. Microsoft Visual C/C++ Ver.1.51 を使用しています.

関連するQ&A

  • NASMかNASKの文法の本

    NASMかNASKのアセンブラを使っているのですが、MASMと構文が異なっている?せいか、エラーなりました。 MASMでは DW offset ADR_KOKO DW seg ADR_KOKO でOKだと思いますが、NASM/NASKではどうするのでしょうか? NASM,NASMの文法など詳しく載っている本などありますか?(洋書でも構いません。) DW 0 ; A---> オフセット DW 0 ; B---> セグメント ADR_KOKO: ;ここのオフセットとアドレス値をA,Bにセットしたい mov eax, 1  ... RET

  • マクロアゼンブラが分かる人

    MASMを勉強していて困っています。 指定されたセグメントのコードを表示するプログラムを作成中ですがオフセットアドレスとセグメントアドレスが取得できません。 あと表示方法を ADDRESS |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ---------+----------------------------------------------- 0000:0000 |9E 0F C9 00 69 04 70 00 16 00 F0 11 69 04 70 00 0000:0010 |69 04 70 00 54 FF 00 F0 FF 90 00 F0 53 FF 00 F0 のようにしたいのですが ADDRESS |00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ---------+----------------------------------------------- 0000:0000 |9E  0000:0000|0F  0000:0000|C9 0000:0000|00 のようになっていて困っています助けてください。

  • 回路の設計 教えて

    宿題の課題で7セグメントデコーダの回路をVerilog HDLというもので設計してきてくださいと言われて宿題をやったのですが、正直よくわからなくて教科書のものを映して提出してしまいました。 よくわからなかったというのは、Verilog HDL文の動作レベルでの記述で何が何のことを言っているのかわかりませんでした。だれか下の動作レベルでの記述はここではこうなんだよと教えてくれると助かります。 `define SEG_OUT_0 7'b011_1111 `define SEG_OUT_1 7'b000_0110 `define SEG_OUT_2 7'b101_1011 `define SEG_OUT_3 7'b100_1111 `define SEG_OUT_4 7'b110_0110 `define SEG_OUT_5 7'b110_1101 `define SEG_OUT_6 7'b111_1101 `define SEG_OUT_7 7'b010_0111 `define SEG_OUT_8 7'b111_1111 `define SEG_OUT_9 7'b110_1111 `define SEG_OUT_ERR 7'b111_1001 /*7SEG_DECODER*/ module SEG7_DEC (IN,OUT); input [3:0]   IN; output [6:0] OUT; assign OUT = FUNC_SEG7_DEC (IN); function[6:0] FUNC_SEG7_DEC ; input [3:0] IN; case(IN) 0:  FUNC_SEG7_DEC = `SEG_OUT_0; 1:   FUNC_SEG7_DEC = `SEG_OUT_1; 2:  FUNC_SEG7_DEC = `SEG_OUT_2; 3:   FUNC_SEG7_DEC = `SEG_OUT_3; 4:   FUNC_SEG7_DEC = `SEG_OUT_4; 5:   FUNC_SEG7_DEC = `SEG_OUT_5; 6:   FUNC_SEG7_DEC = `SEG_OUT_6; 7:   FUNC_SEG7_DEC = `SEG_OUT_7; 8:   FUNC_SEG7_DEC = `SEG_OUT_8; 9:   FUNC_SEG7_DEC = `SEG_OUT_9; default: FUNC_SEG7_DEC = `SEG_OUT_ERR; endcase endfunction endmodule

  • アセンブラできません。

    初心者です。 アセンブリ言語で1~9の数字を連続的に表示するプログラムを書いたのですが、アセンブラする時 「error A2016 expression expected」というエラーメッセージが出てアセンブラすることができません。 プログラムの内容は下記↓のものです。 何が原因でしょうか? CODE SEGMENT ASSUME DS:CODE,CS:CODE,ES:CODE,SS:CODE ORG 100h START: mov bl,30h jmp aa aa: mov ah,02h mov dl,bl int 21h mov ah,06h mov dl,0ffh int 21h jnz bb: mov ah,02h mov dl,08h int 21h inc bl cmp bl,39h ja START jmp aa bb: int 20h CODE ENDS END START

  • DirectX&Win32API&C++ ドライブ情報の取得方法について

    Windowsプログラム(Win32API)と、DirectX9(2007January)と、C++を使用してゲームを制作しています。 ですがDirectXは環境によっては動作しないものも多く、 どんな環境では動かないかというのもを手軽に調べるために ゲーム起動前にドライブ情報を表示するようにしたいのです。 (例えば、グラフィックボードだとか、VRAMや、HDD容量や  メインメモリの容量など、DirectX診断ツールのようなもの) それを調べる関数が有りそうな気もしたのですが、 C#やJavaだといくつかありましたが意外と見つからず、 (調べ方が悪いだけかもしれませんが)難儀しています。 もしドライブ情報の取得方法をご存知の方がいらっしゃいましたら どうかアドバイスをお願い致します。

  • NASMアセンブリの構文でわからない、書式があります。

    いつも、お世話になっております。 小生、只今、WindowsXPSP3上でnasm0.99.6を使いアセンブリ言語を勉強しています。 今回質問させて頂き点を、ピックアップすると以下の構文です。 12行目のmov ax, word [msgBack] 16行目のmov word [es:di], ax 23行目のmov byte [es:edi], 'A' 50行目times 510 - ($ - $$) db 0 そして以下にソースコード全体を記述させて頂きます。 1[org 0] 2[bits 16] 3 jmp 0x07C0:start ; far jmpする。 4 5start: 6 mov ax, cs ; csには0x07C0が入っている 7 mov ds, ax ; dsをcsと同じくする 8 9 mov ax, 0xB800 ; ビデオメモリのセグメントを 10 mov es, ax ; esレジスタに入れる 11 mov di, 0 ; 一番上の頭の部分から書く 12 mov ax, word [msgBack] ; 書く予定のデータの住所を指定する 13 mov cx, 0x7FF ; 画面全体に書くためには 14 ; 0x7FF(10進数 2047)個のWORDが必要 15paint: 16 mov word [es:di], ax ; ビデオメモリに書く 17 add di,2 ; 1つのWORDを書いたので、2を加える 18 dec cx ; 1つのWORDを書いたので、CXの値を1つ引く 19 jnz paint ; CXが0じゃないと、paintにジャンプし、 20 ; 残りを書く 21 22 mov edi, 0 ; 一番上の頭の部分に書く 23 mov byte [es:edi], 'A' ; ビデオメモリに書く 24 inc edi ; 1つのBYTEを書いたので、1を加える 25 mov byte [es:edi], 0x06 ; 背景色を描く 26 inc edi ; 1つのBYTEを書いたので、1加える 27 mov byte [es:edi], 'B' 28 inc edi 29 mov byte [es:edi], 0x06 30 inc edi 31 mov byte [es:edi], 'C' 32 inc edi 33 mov byte [es:edi], 0x06 34 inc edi 35 mov byte [es:edi], '1' 36 inc edi 37 mov byte [es:edi], 0x06 38 inc edi 39 mov byte [es:edi], '2' 40 inc edi 41 mov byte [es:edi], 0x06 42 inc edi 43 mov byte [es:edi], '3' 44 inc edi 45 mov byte [es:edi], 0x06 46 47 jmp $ ; ここで無限ループに入る 48 49msgBack db '.', 0xE7 ; 背景に使う文字 50 51times 510-($-$$) db 0 ; ここから509番地まで0で詰める 52 dw 0xAA55 ; 510番地に0x55を、511番地に0xAAを 53 ; 入れておく 以下、私の憶測でコードの動作を記述させて頂きます。 12行目のmov ax, word [msgBack] ・axレジスタに、wordで表された、msgBackのアドレスを格納している。 16行目のmov word [es:di], ax ・wordのデータになる、es:di(esに対して、diがオフセットアドレスと見て)、axのデータを格納している。 23行目のmov byte [es:edi], 'A' ・byteのデータになる、es:ediに対して、'A'と言う値を格納している。 50行目times 510 - ($ - $$) db 0 ・これに関しては全くわかりません。$がそのそもよくわかりません。 お忙しい中、誠に恐縮ではありますが、以上をご確認して頂き、 先輩方、ご教示宜しくお願い致します。

  • 8086アセンブラで、メモリ間のデータをストリング命令でブロック転送したい

    ソースが長めなので、簡潔に書きます。ご無礼の段、ご容赦ください。 【目的】PC-9801本体のCバス(汎用拡張スロット)に挿したサウンドボード上の ROM BIOSを読み出し、バイナリファイルに落としたい。既にエミュレータ用に実機からの 吸出しツールは存在するが、ソースが無いので、自作することにした。 その前段階としてアセンブラの修行も兼ねて、ROM BIOSの先頭3ワード(6バイト)を メモリ上のバッファにコピーし、比較して値の合致を確認したい。 将来的にはSCSI ROM BIOSの解析等を試みたい。 【方針】8086のストリング命令でダイレクトにメモリtoメモリでブロック転送を する。具体的にはrep movsbを用い、6バイトを転送する。 【備考】PC-9801-26K互換音源のROM BIOS(少なくとも先頭8バイト)は一意であり、 その並びは、0001h, 0000h, 00d2h である。例外はありません。 86音源でも同様で、下位互換性があることは、拙作ツール(OPNCHK.COM)にて確認済み。 なお、上記バイト列は、セグメントCC000h:オフセット2E00hから読み出し 可能である。 なお実行にあたり、所謂メモリマネージャの類(MELEMM.386等)は一切 組み込まない状態で行なう(EMSメモリマネージャ等との同居対応は将来の課題とします)。 【開発環境】PC-9801DA2(Cyrix Cx486DLC-25MHzに載せ換え; 13.6MB RAM; HA-55BS4 SCSIボード + 240MB SCSI HDD + SONY CPD-17SF9 CRT + NASM 2.06rc10 on NEC DOS 5.0A-H + Turbo Debugger v3.2 と、 秋葉で買ったジャンクFDに入ってたMASM ver 3.00; 予備機 VX41/RS21/EPSON 286VF/EPSON 486HX2/Xv13R16[K6-2 400MHz]/ AT互換機上のNekoIIエミュ/Cygwin上のnasmw.exe) 【参考書】PC-98、8086アセンブラ、テクニカルデータ、古雑誌等 定番本100冊ほど 【拙作コードの失敗点をご指南いただきたい。NASMコードですが、MASM/TASMでも構いません】 ; PC-9801-26K compatible Sound ROM BIOS Copy Program (i/o address 0188h) ; Programmed by OrzHacker666 ; Date 2009-07-13 for NASM 2.06rc10 [Bits 16] org 100h ; COM program section .text start: push es ; これを保存しないと、 push ds ; 画面がめちゃくちゃになる mov ax, 0cc00h ; Sound ROM セグメントアドレス mov es, ax mov ds, ax ; DS:SI -> ES:DI 無意味か? mov bx, 2e00h ; Sound ROM オフセットアドレス lea si, [es:bx] ; ES:BX がSound ROMの開始点 lea di, [ds:sbuff] ; sbuffは仮に確保したバッファ。 ; どこにあるかは、当たり前ですが、不明。そこら辺はCの変数宣言と同じですが。 mov cx, 8 ; とりあえず、アタマ8バイトをコピー cld rep movsb CompareWithOriginal: cmp word [es:bx+4], 00d2h ; これは通る。当たり前。 jne FailedCpyRom cmp word [ds:sbuff+4], 00d2h ; ここで失敗判定。なぜ? jne FailedCpyRom ; sbuffにes:bx~が正しく ; 転送されていないのか? SuccessCpyRom: ; これを拝めれば…。 pop ds pop es mov ah, 9 lea dx, [SUCCESSMsg] int 21h mov ax, 4c00h int 21h FailedCpyRom: ; 見飽きましたOrz pop ds pop es mov ah, 9 lea dx, [FAILEDMsg] int 21h mov ax, 4c00h int 21h section .data SUCCESSMsg: db 'Succeeded !!', 0dh, 0ah, '$' FAILEDMsg: db 'Failed(--;)', 0dh, 0ah, '$' section .bss sbuff: resb 8 ; Cで書くと、差し詰め unsigned char sbuff[8]; であろうか…。 識者の方、よろしくお願いいたします。気になって夜も眠れません。

  • このアセンブラの意味を教えて下さい

    アセンブラ初心者です。「はじめて読む486」を読んで勉強しているのですが、いくら調べても分らないのでどうぞ教えて下さい。次の2つのプログラムが分りません。 ------------------------------------------ db 0eah dw offset set_cs_desc2 dw 20h set_cs_desc2: 以下プログラムが続く --------------------------------- セグメント間ジャンプ命令によってCSレジスタに0020hをロードすると本にあるのですが、先ずdb、dwとは何を意味するのでしょうか。単にバイト、ワードを指定しているのでしょうか?そうだとしたらなぜdb、dwと指定しているのか分りません。 また0eah,20hが何を意味しているのか分りません。 出来れば1行ごとに詳しく教えて戴ければ嬉しいです。 また ------------------------------ db 0eah dw offset set_cs_desc3 dw seg set_cs_desc3 set_cs_desc3: move命令などが続く _text ends end ------------------------------------ セグメント間ジャンプ命令によってCSレジスタに_textをロードすると本にはあるのですが、上のプログラムと同様、0eah,db,dwが分りません。 またsegは何を意味するのか分りません。お手数だとは思いますが、これも1行ごとに詳しく解説していただけないでしょうか? そして2つのプログラム共通に分らないのが、なぜこのコードでCSレジスタにロードする事になるのか分りません。 多分意味している事は簡単な事なのだろうと思うのですが、いろいろ調べても全く手がかりがネットや他の本にもなく苦労しています。 初心者なので出来れば簡単な言葉で教えて戴ければ幸いです。 よろしくお願いいたします。

  • Windowsでファイルのフルパスを簡単に取得する方法

    Windowsでファイルのフルパスを簡単に取得する方法 こんにちは。 Windowsでファイルのフルパスを簡単に取得する方法はありますでしょうか? たとえば、 C:\Windows\Downloaded Program Files\FP_AX_CAB_INSTALLER.exe をメールに転記(ペースト)したい場合、 (1)エクスプローラのフォルダのアドレスをコピーして、 (2)F2キーを押してファイル名を変更の状態にして、その名前をコピー という手順でやっています。 これを簡単に実現したいのですが、フリーソフトか、Windows標準の機能であれば 教えて頂けますでしょうか。 OSはWindows XPと、Windows7の両方です。 すみませんが、よろしくお願いします。

  • PC-9801 MS-DOSでの実行ファイル形式、COMかEXEか、線引き・基準は?

    PC-9801実機上で、NASMやDJGPP(GCC v4.3.2)を使用しプログラミングを しています。ハードウェア・ソフトウェア(DOS関連)資料も40冊ほど 買い込み、実機も7台揃えて80286/V30~Pentium初代まで互換をもたせるよう がんばっています。 念のためフリーでダウンロードしたBorlandのTurbo C(英語版パッチ済み)と TASM(BCC5.5に同梱)はありますが、まだ入れてません。 箱物の日本語版 PC-98用MASMや日本語版 PC-98用Turbo Cが欲しいんですが、 オクでもめったにないので…(not MASM32。 あれ[MASM32]はライセンス的にヤバいと聞きました)。 さて、質問ですが、標題の件。MS-DOSでは実行ファイル形式として、 COMとEXEがあり、 1)COMはセグメントを気にせずコーディングできる反面、64KBまでの制約があり、 大型のプログラミングには向かない。フルアセンブルのコードが当たり前。 速度重視(極論ですが)。I/Oポートやデバイスを直に叩く、ことが多い。 2)EXE型プログラムは、セグメントを意識しなければならないが、 64KB以上の実行ファイルを生成可能であり、Cとアセンブラオブジェクトとの 連携が可能。Cでのインラインアセンブルも活用できる。構造化。可読性。 可搬性。AVRマイコンのライタなどでもEXEのものがある。 実際にDOSディレクトリ以下を見ますと、いったい何を基準に COMとEXEを使い分けたのか、いまいちつかみかねています。 所有バージョンは日電版 DOS3.3C/3.3D/5.0A/6.2、EPSON版 DOS3.3/6.2ですが、 具体的には日電版 DOS6.2では 1)DISKCOPY.EXE サイズ: 63.1KB 2)ATTRIB.EXE サイズ: 11.2KB 3)MORE.COM サイズ: 2.76KB 4)MEM.EXE サイズ: 32.3KB 5)EDLIN.EXE サイズ: 13.9KB 6)MOVE.EXE サイズ: 18.9KB 7)UNFORMAT.COM サイズ: 24.1KB などです。 C + インラインアセンブラ(もしくはアセンブラオブジェクトと Cオブジェクトとのリンク)ではなく、フルアセンブルであればなおさら 上記実行ファイルは全部.COMにして差し支えないように思えるのですが、 所望の結果がセグメントをまたぐ・またがないに関わることで基準があるのでしょうか (セグメントの概念にいま取り掛かったばかりのヒヨッコですが)。 しかしそれだと、DISKCOPY.COMとか、FreeDOSなどでは.EXEではなく、 .COMになっていたり、その逆もあるので説明がつかないような気もしますが…。 詳しい方、ご教示ください。