• ベストアンサー

アセンブラでWindowsAPI

アセンブラだけでWindowsAPIを叩いてウインドウを表示させることはできるのでしょうか。C言語で普通にできるので、相当複雑になるとは思いますが、当然アセンブラでもできると思います。C言語だと変数の型の名前なども変な名前がいろいろ付いていて裏で何をやっているのかさっぱりわかりません。普通に使う分には問題ないのですが、ブラックボックスのような感じで気持ち悪いのです。どのような命令でAPIが呼び出されているのかCPUレベルで知りたいです。C言語の呼び出し規約ということで、MS-DOSのシステムコールみたいなものとは違うと思うのですが、どうなのでしょうか。

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

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.6

> アセンブラだけでWindowsAPIを叩いてウインドウを表示させることはできるのでしょうか。 可能です。MS-DOSでは直接int命令を発行しますが、 Windowsはstdcall規約で関数をcallするだけですから他の関数と大差ありません。 コンパイラでCソースのアセンブリリストが出せると思いますので、ご覧になってみればいかがでしょうか。 > C言語だと変数の型の名前なども変な名前がいろいろ付いていて > 裏で何をやっているのかさっぱりわかりません。 補足等読んでいる限り、アセンブリ云々では多分解決しないと思いますが。 型名を独自に定義しているのは裏で何をやっているかをブラックボックスにして、 もっと抽象度を上げようとしているのであって、わざわざ隠そうとしているものです。 C言語より抽象度が下がれば理解できるという考えはずれているように思います。(後述) > __stdcall → WINAPI 例えばこの記述は、「呼び出し規約」ではなく「意味役割」に抽象度をあげています。 つまり、Windowsでのコールバックされる関数を示すのがWINAPIであって、 単に__stdcallと書くこととは意味的に等価ではありませんし、可読性や検索性も違います。 # ついでに書けば、__stdcall自体もコンパイラ独自であって、C/C++の言語仕様では規定してませんので、常に動く保証がありません。 > char* → LPSTR これも、(ゼロ終端の)文字列を示すことを暗示しており、char*より抽象度があがります。 例えばLPBYTEとは意味的に区別して使われていますし、また、 LPTSTRになると、UNICODE(WCS)とMBCSの切り替えにも意味を持ちます。 > unsigned int → UINT Win16時代のintとWin32時代のintの差異吸収という意味での抽象度上げでしょう。 C言語の仕様上、マルチプラットフォームを意識した開発ではよく見る手法です。 他の型も、抽象度アップや統一感維持のためにそうなっています。 「わざわざブラックボックスにする」ために定義されているものですから、 本来はあまり気にしなくていいお話ですが、知りたい局面も確かにあります。 ただ、それはアセンブリよりもwindows.h中の(C言語の)定義を見るべきでは? > WinMainの宣言も、 「Windowsの規約」を無視すれば、HINSTANCEもvoid*と書けなくはないです。 # 但し、これはSTRICTの有無で実際の型が変わって通らなくなりますし、普通はそんなことしませんが。 > 単なる書き方の好みの問題とは考えづらいです。 型名に意味/付加情報を与えて抽象度を上げるためであって、好みではないでしょう。 > このような何バイトの情報なのかもよくわからない型名が余計に処理をブラックボックス化させている気もします。 ブラックボックスにするためのものなので、多分そうだと思いますが、 それは意図的なものですし、別に混乱を誘っているわけでもありません。 Windowsの規約に従う処理は、Windowsの型を使うべきであり、 C/C++ネイティブの型と安易に混ぜて使うべきではありません。 Win16⇒Win32や⇒Win64の移行などをやってみれば分かります。

kiyotani
質問者

補足

ありがとうございました。わざわざブラックボックスにしている訳ですね。 確かにUnicodeの切り替えなどでは必要なものだとは思います。 でもやはりMS-DOSのプログラミングをやっていた人がいきなりWindowsをやると混乱しそうです。

その他の回答 (5)

  • iriyak
  • ベストアンサー率48% (40/82)
回答No.5

こんにちは。 私も、先達の残してくれたドキュメントを手がかりに、ブラックボックスにぶつかっていっています。後は msdn library でしょうか。 光成さん x86アセンブリ言語入門 http://homepage1.nifty.com/herumi/prog/prog.html x64 アセンブリ言語プログラミング http://homepage1.nifty.com/herumi/prog/x64.html Jun Mizutaniさん Linux でアセンブリプログラミング http://www.nk.rim.or.jp/~jun/lxasm/asm00.html msdn library http://msdn.microsoft.com/en-us/library/default.aspx ご参考まで。

kiyotani
質問者

お礼

ありがとうございます。参考になりました。

  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.4

>>いえ、ハンガリー記法ではなく、 Windowsプログラミングでは、 __stdcall → WINAPI char* → LPSTR unsigned int → UINT というように普通の型名を別の(Windowsプログラム用?)型名で置き換えていますよね。 それのことですか?そういうコーディングは、Windowsに限らずUnixのソースでも目にしますね。できるだけソースコードの抽象度を上げて、32,64Bitのビット数の違いとかコンパイラ間での相違を受けず、移植性を高めるためみたいです。 たとえば、共通のinclude file内で #ifdef A_CPU typedef unsigned int UINT; #else typedef unsigned long UINT; #endif なんて記述をするとか、最初からinclude fileを環境ごとに切り替えるってことをするようです。 以前読んだ100以上もの環境に移植されているという商用データベースのソースコードも、そういう書き方になっていました。

kiyotani
質問者

お礼

ありがとうございます。移植性を上げたり、わざとブラックボックス化(抽象化)しているのですね。

  • 64ema
  • ベストアンサー率44% (4/9)
回答No.3

直接な回答ではありませんが、下記のHPの書籍に掲載されています。 http://book.mycom.co.jp/book/4-8399-1718-3/4-8399-1718-3.shtml

kiyotani
質問者

お礼

ありがとうございます。詳しく調べるにはよさそうで、なかなか興味深そうな内容でした。

  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.2

>>C言語のWindowsプログラムでは、やたらと大文字の長い型名やトークンを使用しますが、構造体の名前でもないただの unsigned intやvoid *などの一般的な型名や__stdcallなどをあんなにわかりにくいものに置き換えてしまうのでしょうか。 タイプ型のハンガリアン記法のことでしょうか?以下にあるように、現時点では、それは「誤った有害な命名方法」と評価されてマイクロソフトでも使用を禁止しているようですよ。 http://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E8%A8%98%E6%B3%95 でも、「過去の遺産」のソースを引きついで利用するとき、それまでの命名法を崩すのも、それはそれで問題になるので、現時点で禁止されていても、そのままの流儀でいっているのでしょうね。

kiyotani
質問者

補足

いえ、ハンガリー記法ではなく、 Windowsプログラミングでは、 __stdcall → WINAPI char* → LPSTR unsigned int → UINT というように普通の型名を別の(Windowsプログラム用?)型名で置き換えていますよね。 WinMainの宣言も、 int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, char* lpCmdLine, int nShowCmd) という風に、LPSTRやWINAPIを使わなくても書けるならこう書けばいいと思うのですが、なぜ実際はLPSTRやWINAPIといったキーワードを使用するのでしょうか。単なる書き方の好みの問題とは考えづらいです。このような何バイトの情報なのかもよくわからない型名が余計に処理をブラックボックス化させている気もします。

  • aigaion
  • ベストアンサー率47% (287/608)
回答No.1

かな~りコアなお話ですね 本気でやるとすごく長くなるのでこのあたりの記事を読んで雰囲気をつかんでみては? http://codezine.jp/a/article/aid/420.aspx

kiyotani
質問者

補足

ありがとうございます。そもそもWindowsAPIはDLLを呼び出してると思うのですが、アセンブラからDLLを読み込みその関数を呼び出すという操作が特に気になります。 もうひとつ聞きたいこととして、C言語のWindowsプログラムでは、やたらと大文字の長い型名やトークンを使用しますが、構造体の名前でもないただのunsigned intやvoid *などの一般的な型名や__stdcallなどをあんなにわかりにくいものに置き換えてしまうのでしょうか。新しい型が出てくるたびに正体が何なのか気になって仕方がありません。

関連するQ&A

  • アセンブラ言語がわかりません。

    初心者です。まとを得ていない質問でしたらすみません。 C言語は理解できる程度なのですが、アセンブラのコードを書く事ができません。 今アセンブラ言語を学び始めた所ですが、「jr」「jarl」「jmp」などの分岐命令の指定の方法がわかりません。 C言語でいうとどういうコードを書いた時に、このような命令を出力できますでしょうか。 本を読んでも、この上記の命令の意味は書いてあるのですが、実際出力が出来なかったもので。 またアセンブラ言語を学ぶためにいい方法などありましたらお教えく頂けないでしょうか。 よろしくお願いします。

  • 組み込みアセンブラとは何ですか?

    私はx86でアセンブラを勉強中ですが、ネットでアセンブラ関係のことを検索していて組み込みアセンブラという記述をを見ました。 C言語から利用する場合インラインアセンブラより良いとかなんとか。 組み込みアセンブラという名前も怪しく合っているかわかりません。 掲示板のようなところで組み込みアセンブラの方が良い、早いと書いてありました。いろいろ検索して見かけたのでどこの掲示板かもわかりません。後から探したのですが見つけることができませんでした。 そこで質問なのですがそのその組み込みアセンブラとは何なんでしょうか? C言語からアセンブラを利用する場合、今読んでいる本「やさしいアセンブラ入門」にはインラインアセンブラとアセブラ言語モジュール(オブジェクトファイル)をCプログラムでリンクする方法の2種類が書いてありますが。組み込みアセンブラはモジュールで使うということでしょうか? 違うとすればどのような方法でアセンブラを利用することでしょうか? わかる方教えてください。ヨロシクお願いします。

  • C言語とアセンブラ言語による計算プログラミング

    "AB間の距離を求めなさい。" 下の画像において、AC=r1、BC=r2、∠ACB=α°とするとき、AB間の距離dを求めなさい。 上記の問題について困っております。 この問題の解答については、C言語とアセンブラ言語によるプログラミングで考えるようになっており、FPU(MATH COPROCESSOR)を使用し、C言語側で変数や関数宣言、printfなどでの計算結果出力を記述し、アセンブラ言語側で計算するプログラム問題です。 原則として、C言語側で計算してはいけない仕様になっています。 そして、2つのオブジェクトファイルをリンクさせ、実行可能ファイル(.exe)を作成し、コマンドプロンプト に計算結果を表示する。とういう問題です。 ・アセンブラ言語側での使用する命令のプロセッサアーキテクチャのタイプは「.386」 ・作成するオブジェクトのメモリモデルは、Windowsなので「FLAT」 図の画像は添付してあるので、どうかご回答のほどよろしくお願い致します。

  • C言語のvoid型ポインタ変数について。

    C言語のvoid型ポインタ変数について。 C言語のvoid型ポインタ変数について質問があります。 組み込み系の開発を行っているのですが、現在使用しているシステムで、 提供されている "API" を介してアプリケーション部のソフト作成を行っています。 この "API" ですが、引数の多くはvoid型ポインタとなっています。 ある人がこの引数がvoid型となっているのを見て、 『なんでvoid型なんや??、C言語でアセンブラと違うんやから、void型なんかにしない方が良い』 とおっしゃいました。 この意味がよくわからなかったのですが、なぜ void型はよろしくないんでしょうか? -- 僕が思うに、APIなんやから引数を void型ポインタ にすることでどんな型にも対応できる 汎用的であると感じ、逆にこの方が良いのではと感じたのですが。。 -API例---- int _exApiKannsuu( char in_data, void* out_data ) "in_data" をもとに "out_data" を取得する。 どーやらこの "out_data" が void型 であるのががよくないらしい・・

  • WindowsAPIからC言語関数への代替について

    ウィンドウズOSのプログラムから、Linuxプログラムへ移植するにあたり、ウィンドウズプログラムで使用していたAPIをLinuxで使用可能な関数に変更しなければいけなく、「API/C言語関数・Linuxシステムコール対応表」のようなものを探しています。知っている方教えてください。

  • アセンブラでの即値の引き算

    アセンブラで変数から即値を引く場合(ex. x - 4)は subi rt, rs, 4 とかでできますが、逆に即値から変数を引く場合(ex. 4 - x)はどうなるのでしょうか? neg rs, rs addi rt, rs, 4 みたいに符号を反転してから計算するのでしょうか? もしそうなら、C言語とかでi-4の計算は4-iより遅いということでしょうか? 同様に割り算の場合などはどうなのでしょうか? よろしくおねがいします。

  • GASアセンブラのテストプログラムの作り方について

    現在、アセンブラのテストプログラムの作り方に困っています。 入力された値を関数palindへ渡し、結果を出力する様にしたいのですが、考え方がよく解りません。 関数を呼び出すには、       movl 引数, %eax       pushl %eax       call 渡す関数の名前       popl %eax とすると思うのですが、これだけでは結果を戻しただけだになると思います。 この後結果を出力するにはどのようにしたら良いでしょうか? 宜しくお願いしますm(_ _)m ・回文を作るアセンブラの関数(palind.s) 例えば8と入力した場合に2進数(1000)の回文(上から読んでも下から読んでも同じもの)、10000001と00011000を作ります。(abcd)→(abcddcba),(dcbaabcd) 答えは2個あるので、入力とは別の変数を持ってきて、その変数の値によってどちらかを返すようにします。 (2個の答えを出すには変数を変えて呼び出せば問題ないと思います)

  • WindowsAPIでシリアル通信プログラム(RS232C)

    Windowsで、VC++やVBを使わずに普通のC言語で簡単な文字列(コマンド)を外部機器に送信するプログラムを書きたいのですが、WindowsAPIというものの存在は知っているものの全くもって触れたことがありません。 取り合えず、パソコンから外部機器に文字列を送信することが出来ればよいのですが、すぐ実装に役立つような書籍などはありませんでしょうか? VCやVBでシリアル通信プログラムの解説をしている書籍は見つかるのですが、WindowsAPIで行っているものが見受けられません。 もし、ご存知でしたらよろしくお願い致します。

  • アセンブラ初心者です。

    アセンブラ初心者です。 MacOs上のターミナルでgccをつかいアセンブラのソースコードを表示させてみたら .cstring LC0: .ascii "%d \0" .text .globl _main _main: pushl %ebp movl %esp, %ebp pushl %ebx subl $36, %esp call L9 "L00000000001$pb": L9: popl %ebx movl $1, -16(%ebp) jmp L2 L3: movl $1, -12(%ebp) jmp L4 L5: movl -16(%ebp), %eax imull -12(%ebp), %eax movl %eax, 4(%esp) このようになったのですが1つ疑問があります。それはjmp命令のところでjmp L2またはjmp L4とありますがL2とL4のソースコードは表示されていません....。この部分はどうして表示されないのでしょうか?またどのようになっているのでしょうか?教えてください><ちなみにfor文をつかった単純なかけ算のプログラムをCで書きました。

  • アセンブリ言語について。

    CPUを直接操作するうなプログラムは高水準言語では作れないので低水準言語が必要になります。 CPUをスリープ状態にするHLT命令はアセンブラにはありますがC言語などの高水準言語には無い機能ですから、アセンブラを使ってプログラムを書かないと実現できません。というのは、合っていますでしょうか?教えていただけないでしょうか?すみません。