« 8086なアセンブリ言語 | トップページ | 無限ループは仕様です »

2009/02/19

C++

最初に言っておくが、
『パンを尻にはさんで右手の指を鼻の穴に入れて左手でボク
シングをしながら「いのちをだいじに」と叫んではいけない。』
の事では無いので、その辺、宜しく。

興味心で、"Microsoft Visual C++ express edition 2008"をダウンロードして使ってみていました。
元々、アセンブリ言語使いなので、C++だけではプログラム組めないからと、コードリスティングしてアセンブリソースを吐くコンパイラオプションを設定しておきながら遊んでいたのです。

いやぁ、ぷらぷら様かしこいわ。
Pentium世代は、人間の手で最適化できるようなもんじゃないからCで書けとは言うが、確かに細かい所まで処理速度を最適化してくれている。

流石に、Cソースの書き方によっては遅くなるけど、どういうコードを吐くのか意識しながら(アセンブラレベルでどうなるのかな?という事。)、Cソースを書いておけば、下手にアセンブリ言語を書くより早くなる。
というより、アセンブリ言語で書くにも、あんなアセンブリ言語書きたくない。可読性がすごい悪い。

C++の最適化 気付いたこと編

(1) パイプラインを考慮した、命令の並べ替え
────────────────────
これは当然。例えば、ebxレジスタを変更した直後に mov eax,[ebx]をしたら1clock追加とか、
レジスタ変更直後に、そのレジスタをpushすると1clock追加とか。
自分がアセンブリ言語コード書くときも、気を付ける。

(2) 関数呼び出しが、レジスタ渡しになってる!!
────────────────────
すげー。普通のCだと、全部スタック渡しなのに。
ポインタで渡す引数に、ちゃんと edi, esiレジスタ使うんだよ!
まぁ、レジスタで足りない分は、スタックで渡されるけど。
どのレジスタを使うとか、どう決めているんだろう?


(3) 頻度に呼ぶ関数が!
────────────────────
  mov  ebx,offset _printf
  と、あらかじめ関数のポインタをレジスタに入れておいて、
  push 引数
  call ebx
  って、アドレス指定じゃなくて、レジスタ指定のcallしてるよ!

(4) 同じオブジェクト内の関数呼び出し
────────────────────
驚いた。
call命令使わないで、というか、機械語レベルでは関数にしないで、
呼び出し元に関数のコード書いてる。
たとえば、

void print(char *stMsg){
  printf(stMsg);
};

って関数つくって、

void main(){

  print("Hello world\n")

};

って感じで関数を呼ぶと、


.686P
.model c,flat

printf proto c stMSG:near32 ptr

.const

MSG db "hello world",0ah,0dh,0

.code

main  proc c
    invoke  printf,
    offset MSG
    ret
main  endp
    end


ってかんじのコード吐く。
# 実際のリスティングは、こんなmasmの擬似命令使わないで、
# ちゃんとプロテクトモードのコードを吐くが・・・。つまり、
# proto や、 invoke 擬似命令もつかわないで、ちゃんと
# extern と call 命令になります。

callでprint関数を余分なら、そのcall命令とret命令を実行する時間無駄なんで、呼ばないで、そんままやっちゃおう!という魂胆か!!

(5) while()の展開
────────────────────
いや、まぁ、理解はできるけど。
おれ、アセンブラでやるにもこういうことしたくない。

  i=10
  while(i!=0){
    そのた処理
    i++;
  };

こういう処理があったとしようか?
自分だったら、こう、書く。

  mov  ecx,10
  jmp  While_End
While:
  そのた処理
  dec  ecx 
While_End:
  or  exx,ecx
  jne  While


でも、C++は、こう書きやがった!!

  mov  ecx,10
  or  ecx,ecx
  je  While_End
While:
  そのた処理
  dec  ecx
  or  ecx,ecx
  jne  While
While_End:

たしかに、最初から i が 0 だった場合は、
条件ジャンプ命令が1回だけになるが…
"or ecx,ecx" 命令と、条件ジャンプ命令を、同じ事なのに2回書かないといけないのが、スマートじゃないような…

まぁ、後者のほうが、確かに処理速度は、速くなるが

|

« 8086なアセンブリ言語 | トップページ | 無限ループは仕様です »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/36969/44115009

この記事へのトラックバック一覧です: C++:

« 8086なアセンブリ言語 | トップページ | 無限ループは仕様です »