トップページ⇒tech
1001コメント316KB

アセンブラ… (・∀・)イイ!

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
めくるめく16進数。
機械語萌え。20 D4 FF FF 50 E8 8A DC FF FF 68 10 20 00 00 8D
45 B4 50 8D 85 B4 FB FF FF 50 6A 00 E8 7B DC FF
FF 8B E5 5D C3 00 00 00 FF FF FF FF 02 00 00 00
0D 0A 00 00 55 8B EC 83 C4 F4 84 D2 74 08 83 C4
F0 E8 82 C4 FF FF 89 4D F4 88 55 FB 89 45 FC 8B
45 FC 83 C0 04 8B 55 F4 E8 2B CD FF FF 8B 45 FC
80 7D FB 00 74 0F E8 B5 C4 FF FF 64 8F 05 00 00
00 00 83 C4 0C 8B 45 FC 8B E5 5D C3 55 8B EC 83
C4 F0 53 33 DB 89 5D F0 84 D2 74 08 83 C4 F0 E8
34 C4 FF FF 89 4D F4 88 55 FB 89 45 FC 33 C0 55
68 61 69 40 00 64 FF 30 64 89 20 8D 45 F0 50 8B
0159デフォルトの名無しさんNGNG
>>156
何様のつもりだ。
0160デフォルトの名無しさんNGNG
textはコードセグメント
dataはデータセグメント
bssは初期化されていないデータセグメント
データセグメントはスタックセグメントと重なる場合もある。(DS=SS)
セグメントは物理メモリをリニアに見た時の覗き窓で、
8086のレジスタ仕様の64kByteまでしか一度に(効率的に)
アクセスできない制限を緩和する役目をはたす。
64kというのは、レジスタの長さが16bitなので、65536バイトまで。
0161デフォルトの名無しさんNGNG
>>158
結構知っとるやんけ
自分はLinuxをメインに使っている
Linuxの全てを知り尽くしたい
それでカーネルソースというわけ
そのうちemacsとかxwindowのソースも読んでみたい
口の聞き方は直らんのでゆるせ
くるしゅうない
0162デフォルトの名無しさんNGNG
>>160
おいおい、セグメントって何だよ。
セクションだろ
0163デフォルトの名無しさんNGNG
>>161
直らないんじゃなくて、直そうとしないだけ.
0164デフォルトの名無しさんNGNG
厨は本でも読んどけ
0165デフォルトの名無しさんNGNG
アセンブリブリウンコ
0166デフォルトの名無しさんNGNG
大回転アセン・ブリブリウンコーーーーーーーーーーー!!!!!!!!!!
0167デフォルトの名無しさんNGNG
CPUアーキテクチャを知らないのに
アセンブラっていうのもね・・・
動くコードしかかけないじゃん
x86系じゃ、わかってても高速化は無理みたいだけど
ところで、インテルのコンパイラよりも最適化できる人って
いるの?
0168デフォルトの名無しさんNGNG
どういうとこ直したのか教えてください
x86系じゃない人も
具体的にどこらへんを直した時に
どの程度早くなったのか教えてください
当然比較したコンパイラを書いてもらえないと、
かなり意味ないんですが・・・
0169デフォルトの名無しさんNGNG
>>167
動くコード以外に何を書くというのだ?

Intelのコンパイラもたいしたこと無い。
アレが完璧ならVTuneなんて売れるわけ無い。
つーか、VCよりも遅いこともあるし。
0170166NGNG
少しはからんで欲しかった(泣
0171デフォルトの名無しさんNGNG
ネタはプログラマ板でやれよな

>160
補足すると
 コンパイラが
text に コンパイルしたコードを吐く

data に static int x=0; みたいな変数を確保して かつ初期値を置く

bss には 初期化しなくていい変数を確保する
0172デフォルトの名無しさんNGNG
>動くコード以外に何を書くというのだ?
誰が読んでも、コンパイラよりも最適化されたコードって意味だろ

>Intelのコンパイラもたいしたこと無い
Pentiumに最適化するしたい時って・・・他に方法あるの?

で、Intelのコンパイラに問題があるなら
どのへんが問題なのか教えてくれよ
0173デフォルトの名無しさんNGNG
>>172
別に問題はないよ。
ただ、Intelのコンパイラが特別優れているというわけでもない。
0174デフォルトの名無しさんNGNG
>>172
>>動くコード以外に何を書くというのだ?
>誰が読んでも、コンパイラよりも最適化されたコードって意味だろ

それを言いたいのなら「動くコードしかかけない」ではなく
「動くだけのコードしかかけない」と書くべきだろ。

172の文も日本語的におかしいし駄目だこりゃ。
0175デフォルトの名無しさんNGNG
>>160-171
うわっ、とっても解りやすいです。
ありがとうございました。
0176デフォルトの名無しさんNGNG
日本語大事だよ。仕事でプログラムやるならプログラミング言語以上に。
0177デフォルトの名無しさんNGNG
>176 そりゃそうなんだけど、そういう話ふるなら プログラマ板でやってね

>>157
 それ 8086 のコードじゃ無いじゃない 386以後のコードだよね?
0178デフォルトの名無しさんNGNG
レベル低い
0179デフォルトの名無しさんNGNG
アセンブラで書くような処理を 低レベルって言うんだよ>>178
0180デフォルトの名無しさんNGNG
>>176
他のやつがソフトウエア工学をあまり知らなかったせいだと思われ
単なる動くコードっていうのは、
ソフトウエア工学でいう、まともな設計がなされてないコードの事
慣用表現のひとつだよ
0181デフォルトの名無しさんNGNG
>>180
じゃぁ、優良なコードは動くとは言わんのか?
ソフトウェア工学には 動くコード なんていう言葉の定義があるのか?
0182デフォルトの名無しさんNGNG
>>181
おい、あほまるだしだぞ?
0183デフォルトの名無しさんNGNG
3流童貞大学院生802警報です。すいませんが非難おねがいしまーす。(ワ
0184デフォルトの名無しさんNGNG
>>180
「単なる動くコード」と「動くコード」では意味合いが違うぞ。
もったいぶらないで「動くだけのコード」とか書こうぜ?
0185デフォルトの名無しさんNGNG
Windowsで目覚まし時計作りたいんです
アセンブラで作れますか?
0186デフォルトの名無しさんNGNG
802、童貞3流大学院生なら作れるのだが、、、うーん。どうだろう俺には無理だ。
802師匠に作ってもらうとイイ
0187デフォルトの名無しさんNGNG
>185 パソコンの電源入れっぱなしでいいなら作れますよ 
0188デフォルトの名無しさんNGNG
http://hp.vector.co.jp/authors/VA000124/index.htm

こことってもいいのですがちょっと古めですよね。
似たようなアセンブラ初心者向けのページがあれば教えてください。
0189デフォルトの名無しさんNGNG
>>188
3日経つと古いのか?
0190七誌興奮型NGNG
CASL !! CASL !! CASL !! CASL !!
CASL !! CASL !! CASL !! CASL !!
CASL !! CASL !! CASL !! CASL !!
CASL !! CASL !! CASL !! CASL !!
0191 NGNG
>185
いくらなんでもWindowsでは無理。
カシオやセイコーに就職しましょう。
0192デフォルトの名無しさんNGNG
>>147
gas のニーモニックは NASM, MASM などとは違いますが、基本的に一対一に
対応します。変換規則も単純ですから、どっちで勉強しても良いです。

> セグメントとかページングとかはかなりの部分がx86がやってるらしいね
Linux の仮想記憶のコードは x86 アーキテクチャにべったり依存していて極めて
ダサい(他のアーキテクチャでは、頑張ってソフトウェアで x86 をエミュレートして
いる)ので、勉強のために読むのは薦めませんけど。
0193 NGNG
MOVZX ECX,word ptr [EDI]
は、
mov ecx, 0
mov cx,[edi]
という意味なのですか?
0194デフォルトの名無しさんNGNG
アセンブラスレここしか
ねーじゃねーかよ!!!

いかにマイナー言語かがわかるな。
0195デフォルトの名無しさんNGNG
マイナーか否かなんて大した問題ではないのにな。
アセンブラ以外でMMXのコード書いてくれよ
0196デフォルトの名無しさんNGNG
>193 その理解で可

使う道具としてのアセンブラだけ で食うなら
1)DSPの類 ただしコーデング技術よりノウハウで食べるんだけどね
2)4ビット系 ただし競争相手は世界なんで・・・・

かな・・・ まあご飯食べたい為の仕事なら外の仕事がいいかも
0197デフォルトの名無しさんNGNG
>>195

ホラヨ。今は組み込み関数でも書けるんだよ。

__m64 m1;
m1 = _mm_xor_si64(m1, m1);

ちなみに、IntelC/C++Compilerもしくは、
VisualC/C++ + VisualC/C++ ProcessorPackでコンパイル可能。
GCCとかも最近は似たようなのを搭載しつつある。

肝心の性能だが、MMXでは、
適当にインラインアセンブラで書いたコードよりは速いのを吐いてくれる。
アセンブラできちんとパイプライニングしたものよりは多少遅い。

SSEに関しては、はっきり言ってとりあえずインラインアセンブラで書いてみました
程度の投げやりなコードでもアセンブラの方が断然速い。
まだコンパイラが成熟してないのか。

ただし、組み込み関数といえど、ほとんどアセンブリとニーモニックなので、
速度を追求してかいていくと
__m64 mm0,mm1,mm2,mm3,mm4,mm5,mm6,mm7;
とかレジスタ分の変数用意して、それだけしか使わず、
パイプラインも考慮して書いたりとかするようになるから、
結局アセンブラで書いた方が楽だったりする。
0198デフォルトの名無しさんNGNG
>>195

ホラヨ。今は組み込み関数でもかけるんだ。

__m64 m1;
m1 = _mm_xor_si64(m1, m1);

IntelC/C++Compilerまたは、
VisualC/C++ + VC ProcessorPackで使える。
最近は、GCCとかでも似たようなのを実装しつつあるらしい。

気になる性能のほうは、
MMXに関しては、何も考えずに適当に書いたインラインアセンブリのコードよりは
高速なコードを吐き出してくれる。
ちゃんとパイプライニングしたアセンブリコードの方が少し速い。
SSEに関しては、はっきり言って何も考えずに書いたアセンブリコードの方が
大分高速に動作する。まぁ、どうしてもアセンブリが理解できない人向け?

この手の組み込み関数使ってても、
速度を追求して逝くと、結局はレジスタの数とか
ニーモニックとの対応やパイプラインを考えていくと、
ほとんどアセンブラと変わらん内容になってしまうので、
あんまり使い物にならんが。
0199197==198NGNG
むぅ、回線切れたので書き込めてないと思ったが、
ちゃんと書き込めてたのか。2重投稿(しかも微妙に内容違う)スマソ。
0200デフォルトの名無しさんNGNG
>>197
インテルコンパイラに入ってる ivec.h なんかのベクタクラスライブラリを使うと

Is16vec4 m1; // 16bit符号付き整数×4
m1 = m1 ^ m1;

こんな風に直感的に書けるね。
0201197NGNG
>>200

そだね。でも、所詮は↑の組み込み関数のラッパーに過ぎないから、
直で組み込み関数使った方が実行速度は速いかな?
あと、実際には同じmmレジスタを8bitx8で扱ったり16bitx4で扱ったりとか
する場面が結構出てくるから、そういうときベクタクラスだとやりにくいかも。
02021NGNG
しかし、このスレ結構伸びてるな。
アセンブラスレに飢えていたのか?
0203デフォルトの名無しさんNGNG
>>191
なんでやねん!!
0204デフォルトの名無しさんNGNG
MASMとVC++のDOSでのコンパイラをリンクさせるにはどうすればいいんだろうか
入門以前の事について書いてるページとかないよね
0205デフォルトの名無しさんNGNG
>>204
DOSでって、16ビットコンパイラの話をしているのか?
0206デフォルトの名無しさん ?NGNG
>>203 なんでやねん禿堂。
秋月で買い物すればいいような気が。
0207デフォルトの名無しさんNGNG
>>204
ふつーにOBJファイルを生成したあとにリンクさせればいいじゃn
0208デフォルトの名無しさんNGNG
>>204
public
_
呼び出し規約
とか、その辺?
0209デフォルトの名無しさん ?NGNG
>>208
「MASMと…コンパイラをリンク」って書いてあるから
オブジェクトファイルをリンクさせるのとは
違う意味らしいよ。

>>204
Makefile を作っておいて、
nmake に Makefile を食わせればよい。
「入門以前」というより、ビルドを速くやるための浦和座というか…
裏技かよ?>漏れ
0210デフォルトの名無しさんNGNG
>>204
まず日本語入門サイトを探せ
0211204NGNG
おお、レスありがとうございます。

>209
そうなんです、それなんです。
でもlink.exeが上手く動かずに必ずエラーが出るんです。
C++をvcvars32やってDOSで使ってたんですが、DOSではclしかできないんでしょうか…

>210
すみません。
プログラム始めたばかりなので質問しようにも知識が足りなくて。
0212デフォルトの名無しさんNGNG
下のコードはDelphiのインラインアセンブラですが、
なぜloop1の方が速いのでしょうか?
命令数はLoop2の方が少ないのに。
loop1は↓にあります。
http://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=049229

@@loop1:
MOVZX EAX, byte ptr [ESI]
MOVZX EBX, byte ptr [ESI+1]
MOV DL, byte ptr [EDI + EAX]
MOV DH, byte ptr [EDI + EBX]
MOV byte ptr[ESI], DL
MOV byte ptr[ESI+1], DH

DEC ECX
LEA ESI, [ESI + 2]
JNZ @@loop1

@@Loop2:
mov ax, [esi]
mov ax, [edi + eax]
mov [esi], da
add esi, 2

dec ecx
jnz @@Loop2;
0213デフォルトの名無しさんNGNG
>212
?
loop2のdaってなんだ?
あと、処理が全然等価に見えないのだが?
俺がバカなだけか?

しいて言うならloop2はPpro系(Ppro,P2,P3等)のCPUだと部分レジスタストールに
該当するので遅くなる

あとloop2は486とクラシックPentiumでアドレス生成インターロックも
発生するかな?

Pproの部分レジスタストールは確か5クロックぐらいだったと思うので
JNZを除くloop1のクロック数が8として
同様にJNZを除くloop2のクロック数がまぁ見えてる範囲で9クロックだな

P2、P3のみに限ればloop1は十分な速度だ
それ以外のcpuも考慮する場合は
MOVZX EAX, byte ptr [ESI]
MOVZX EBX, byte ptr [ESI+1]
を
XOR EAX,EAX
MOV AL, byte ptr [ESI]
XOR EBX,EBX
MOV BL, byte ptr [ESI]
にするべきだ

まぁなんにしろ>212よ
お前にはアセンブラは向かないから理解するのを諦めろ
0214213NGNG
グハ…ミスった
MOV BL, byte ptr [ESI]→MOV BL, byte ptr [ESI+1]
逝ってくるわ
0215デフォルトの名無しさんNGNG
>>212
ediには64KB(256x256)の置換テーブルがあるってことかな。
これによるキャッシュ溢れも原因かもね。

loop1もloop2もそうだけど、1ループあたりの処理データ量が少ないなあ。
一回分ぐらいはunrollしてもいいと思うけど。
0216212NGNG
>loop2のdaってなんだ?
axの間違いでした。

>処理が全然等価に見えないのだが?
リンク先を見れば分かりますが、
loop1は1バイトX256個 のテーブルを使っています。
そこで
loop2では2バイトX65536個のテーブルを使ってやってみたのです。

Delphiのコードはこんな感じです。

// Sの長さは偶数とする。
procedure Test7(var S : string );
var
 ConvTbl: array[Word] of Word;
 I: Integer;
 P: PWord;
begin
 for I := low(ConvTbl) to High(ConvTbl) do
  ConvTbl[I] := I;

 ConvTbl[PWord(PChar('AC'))^] := PWord(PChar('CA'))^;
 // スキップ...

 P := Pointer(PChar(S));
 for I := 1 to length(S) div 2 do
 begin
  P^ := ConvTbl[P^];
  Inc(P);
 end;
end;
0217212NGNG
関数の全ソースを載せておきます。
Test8(下のソース)を20回ぐらい連続して呼び出すと、
Test6と同じぐらいの速度になりました。
さっぱり分かりません。 Test6は↓にあります。
ttp://www2.big.or.jp/~osamu/Delphi/delphi-browse.cgi?index=049229

procedure Test8(var S : string );
var
 ConvTbl: array[Word] of Word;
 I, Count, Len: Integer;  P: PWord;
begin
 for I := low(ConvTbl) to High(ConvTbl) do   ConvTbl[I] := I;
 ConvTbl[PWord(PChar('AC'))^] := PWord(PChar('CA'))^;
 ConvTbl[PWord(PChar('AT'))^] := PWord(PChar('TA'))^;
 ConvTbl[PWord(PChar('AG'))^] := PWord(PChar('GA'))^;
 ConvTbl[PWord(PChar('CA'))^] := PWord(PChar('AC'))^;
 ConvTbl[PWord(PChar('CT'))^] := PWord(PChar('TC'))^;
 ConvTbl[PWord(PChar('CG'))^] := PWord(PChar('GC'))^;
 ConvTbl[PWord(PChar('GA'))^] := PWord(PChar('AG'))^;
 ConvTbl[PWord(PChar('GC'))^] := PWord(PChar('CG'))^;
 ConvTbl[PWord(PChar('GT'))^] := PWord(PChar('TG'))^;
 ConvTbl[PWord(PChar('TA'))^] := PWord(PChar('AT'))^;
 ConvTbl[PWord(PChar('TC'))^] := PWord(PChar('CT'))^;
 ConvTbl[PWord(PChar('TG'))^] := PWord(PChar('GT'))^;

 P := Pointer(PChar(S));
 Count := Length(S) div 2;
 asm
  pusha
  mov ecx, Count
  mov esi, P
  lea edi, ConvTbl
  xor eax, eax
 @@Loop:
  mov ax, [esi]
  mov ax, [edi + eax]
  mov [esi], ax
  add esi, 2
  dec ecx
  jnz @@Loop
  popa
 end;

 Len := Length(S);
 if not Odd(Len) then
 begin
  case S[Len] of
   'A': S[Len] := 'T';
   'T': S[Len] := 'A';
   'G': S[Len] := 'C';
   'C': S[Len] := 'G';
  end;
 end;
end;
0218212NGNG
>Test8(下のソース)を20回ぐらい連続して呼び出すと、
>Test6と同じぐらいの速度になりました。

毎回違う文字列でテストしたら、Test8は速くなりませんでした。
0219212NGNG
>215
>ediには64KB(256x256)の置換テーブルがあるってことかな。
Loop1は256バイトの置換テーブルです。

Loop2は64K*64Kバイトの置換テーブルを用意して、
2バイトづつ置換しています。
0220213NGNG
まずテーブルの生成ルーチンは外に出して静的にしろ
デカイテーブルをボトルネックになる関数内で作ってりゃ世話がない
アセンブラ以前の問題だ

あと128kのテーブルはキャッシュあふれする可能性が高い
というかあふれるだろ
テーブルはでかけりゃいいってモンじゃないぞ
CPUの1次キャッシュや2次キャッシュに巧く乗るように(極力1次キャッシュに乗るように)
してメモリ読込による遅延を隠蔽してやらんと場合によっちゃCPU演算した方が早くなるぞ

あとアセンブラ箇所のみ関しては部分レジスタストールしてるつってんだろ
それだけ聞いてわかんなかったら諦めろ
お前にはアセンブラは向いてないって言ってるだろ?
どうして『部分レジスタストール』でgoogle引くぐらいしないんだよ?
取り合えずfnami氏のHPでも見てこい
ttp://www.csl.sony.co.jp/person/fnami/asm.htm#PARTIAL
ttp://www.csl.sony.co.jp/person/fnami/asm.htm#STALL
CPUにもよるがちゃんと今のx86で手動最適化する技能を持った人間は
お前みたいなペアリング無視ペナルティー無視のコードは書かない
最近のCPUは短いコードを書けば速くなるわけじゃないんだよボウヤ
(無論無意味に長いのは問題外だが)
0221212NGNG
なぜ、Test8を同じ文字列で20回ぐらい連続して呼び出すと速くなるのでしょうか?

部分レジスタストールについては今やっています。
220さんありがとうございます。
0222212NGNG
@@Loop:
xor eax, eax
mov ax, [esi]
mov ax, [edi + eax]

これだけで部分レジスタストールは回避されるのでしょうか?
0223213NGNG
純粋にキャッシュヒットしてるんじゃないか?>連続呼び出し
実はCPUがクルーソーとかいうオチを期待しているぞ(藁

>222
まぁ部分レジスタストールしてるのはそこだけだね
ただレジスタ衝突もしてるんで
 @@Loop:
  mov ax, [esi]
  mov ax, [edi + eax]
  mov [esi], ax
↓
 @@Loop:
  xor eax,eax
  mov ax, [esi]
  mov bx, [edi + eax]
  mov [esi], bx
とするべき
対象CPUがP2以降ならAGIストールは発生しなかったはずなんで
AGIストールは無視する?
番地をレジスタに生成直後にその番地へアクセスするとストールする<AGIストール
上記なら
  mov ax, [esi]
  mov bx, [edi + eax] <ここでAGIストール
となる
なのでまずこういうコードは書かないよ<真にチューニングするべきルーチンでは
0224デフォルトの名無しさんNGNG
繰り返すことで
プログラム/テーブル/入力文字列/出力バッファ
の全てが1次あるいは2次キャッシュに乗るからでないの?

テーブルは全体でなく、
入力文字列を処理するのに必要な分だけ乗ればいいことに注意。
0225213NGNG
ちなみに言っておくと俺ならP2ではloop1以上の最適化はできない
(asm部分では考えうる限り最速のチューニングしてるよ
逆に言うとloop2をloop1に近い形にもっていくのが速度の秘訣だ)

あ〜ebpまで使えばなんとかなるかな?>loop2でも

Count := Length(S) div 4;
 asm
  pusha
  mov ecx,Count
  mov esi,P
  lea edi,ConvTbl
  mov ebp,ecx
 @@Loop:
  xor eax,eax
  mov ax,[esi]
  xor ebx,ebx
  mov bx,[esi+2]
  mov dx,[edi+eax]
  mov cx,[edi+ebx]
  mov [esi],dx
  mov [esi+2],cx
  add esi,4
  dec ebp
  jnz @@Loop
  popa
 end;

つーかdec ebpって美しくないなぁ(´Д`;)
4byte/10クロックでペナルティーは見受けられないから
loop1の2byte/8クロックよりは速いかな(ただし要大容量キャッシュ)

はっきり言ってアレだけど真面目な話
コンパイラの最適化に任せるべきだよ>212君
ペアリングとレジスタ衝突、様々なペナルティーとキャッシュ周りを
きっちり考えて最適化しないと逆に遅くなるからね>今のCPUは
コンパイラはその辺考えたコード結構吐いてくれるんで
現行のCPUに関する詳しい知識がないならアセンブラによる最適化はお奨めできないよ
0226デフォルトの名無しさんNGNG
あちゃーsageそこねた
0227デフォルトの名無しさんNGNG
loop1はまだunrollする余地があるので最適でないね
0228213NGNG
まぁアンロールできるけど
実質的なチューニング的には殆ど終わったも同然でしょ?>loop1
0229デフォルトの名無しさんNGNG
そうだね。 すでに1回アンロールしてるようなもんだし、さらにやっても1割かな

 それに、こういう場面じゃアセンブラで書いても 頑張っても2〜3倍程度しか
変わらない。
 同じ時間を割くなら もっと生産的な部分に注力した方がいいと思うな

それでも、どうしてもなんとか高速にしたいなら PCMPEQBで8バイト
同時に比較してはXOR・ANDマスクして置換すれば・・・・うーん
でも英大文字を英小文字にするとか一方向置換にしないといけないし
1ループで4回の置換作業が必要だから 速くなるかどうか判らないな
0230213NGNG
>229
漏れも思って取り合えず考えはしてたんだが余計遅くなった(´Д`;)>pcmpeqb
movq mm0,[esi]

movq mm1,mm0
movq mm2,mm0
pcmpeqb mm1,mm4
pcmpeqb mm2,mm5
pand mm1,mm5
pand mm2,mm4
por mm1,mm2
movq mm3,mm1

movq mm1,mm0
movq mm2,mm0
pcmpeqb mm1,mm4
pcmpeqb mm2,mm5
pandn mm1,mm0
pandn mm2,mm0
por mm1,mm2
por mm3,mm1

movq mm1,mm3
movq mm2,mm3
pcmpeqb mm1,mm6
pcmpeqb mm2,mm7
pand mm1,mm7
pand mm2,mm6
por mm1,mm2
movq mm0,mm1

movq mm1,mm3
movq mm2,mm3
pcmpeqb mm1,mm6
pcmpeqb mm2,mm7
pandn mm1,mm3
pandn mm2,mm3
por mm1,mm2
por mm0,mm1

movq [esi],mm0
add esi,8
dec ecx
色々突っ込みどころ満載な上に動作確認もしてないんで
これに関する言及は勘弁してくれ(取り合えず並べただけなんで
最大の敗因は文字列に4本も使ってしまいmmxレジスタが足りなくなったことだ……
0231pcode 本人NGNG
懐かしいね。
もう一度アンロールしても手間の割には早くならない。

「アセンブラで書けば速くなる」という迷信を砕くのが目的だった
から、アセンブラグルの方々、212 の無知を許してやってくれや。
0232デフォルトの名無しさんNGNG
あと、MMX化すれば何でも速くなると思っている人も多い。
最近では「P4はSSE2最適化すれば何でも速くなる」と思っている人が多い。
0233197NGNG
>>232

ある意味真でもあるんぢゃない?
少なくとも浮動小数点演算に関しては、
x87命令つかうよりもSSE/SSE2のスカラ演算命令の方が速いと
インテルが主張していたような。
その証拠(?)に、インテルのコンパイラには、浮動小数点演算を
x87命令を使わずにSSE/SSE2のスカラ命令を使うってオプションがついてた。

ちなみに、Pentium!!!で試したところ、実行速度に差違は見られなかった。
誰かPentium4で試してみてよ。
0234デフォルトの名無しさんNGNG
>その証拠(?)に、インテルのコンパイラには、浮動小数点演算を
>x87命令を使わずにSSE/SSE2のスカラ命令を使うってオプションがついてた。

そんなオプションないよ。
x87とSSE/SSE2を併用するというオプションはあるけど。
またx87,SSE/SSE2併用オプションでコンパイルしてもほとんど速くならないケースは多い。
あとP4の場合、SSE/SSE2スカラの加算命令は、2クロック毎に1つしか実行できないから、
x87の加算命令の半分のスループットしか出ない。
0235229NGNG
>>230 なるほどねえ。 で1方向置換じゃなくても出来そうだね


1回の交換が

1) @1 := @0 XOR "AAAAAAAA"
2) @2 := @0 XOR "TTTTTTTT"
3) @3 ;= pcmpeqb(@1,all0)
4) @4 ;= pcmpeqb(@2,all0)
5) @2 := @2 AND @3
6) @1 := @1 AND @4
7) @1 := @1 OR @2
8) @0 := @0 XOR @1

 でこれが1ループで2回必要だから、やっぱり改善にはならないかもねえ
0236229NGNG
書いてみたら 230さんより少し短くてスムけど あんまり変わらない

movq mm0,[eax]

movq mm1,mm0
movq mm2,mm0
pXOR mm1, qword ptr tblA
pXOR mm2, qword ptr tblT
movq mm3,mm1
movq mm4,mm2
pCMpeqB mm3,qword ptr tbl0
pCMpeqB mm4,qword ptr tbl0
pAND mm2,mm3
pAND mm1,mm4
pOR mm1,mm2
pXOR mm0,mm1
{ 略 tblA/tblT のみ置換して繰り返し}
movq [eax],mm0

 tblAは'A'が8バイト続くデータ tbl0は値0のqwordデータ
0237229NGNG
人にはアセンブラで時間を潰すなんて無駄と言いながらついやってしまう・・・

ちょっと短くなった

procedure ATCGchg8( p:PChar;cnt:integer);
const tblA:array[0..7] of Char=('A','A','A','A','A','A','A','A');
const tblT:array[0..7] of Char=('T','T','T','T','T','T','T','T');
const tblG:array[0..7] of Char=('G','G','G','G','G','G','G','G');
const tblC:array[0..7] of Char=('C','C','C','C','C','C','C','C');
const tbl0:array[0..7] of byte=($00,$00,$00,$00,$00,$00,$00,$00);
label lp;
asm
movq mm0, qword ptr tbl0
movq mm6, qword ptr tblA
movq mm5, qword ptr tblT
movq mm4, qword ptr tblG
lp:
movq mm7,[eax]
movq mm1,mm7
movq mm2,mm7
pXOR mm1, mm6
pXOR mm2, mm5
movq mm3,mm1
pCMpeqB mm3,mm0
pAND mm3,mm2
pCMpeqB mm2,mm0
pAND mm1,mm2
pOR mm1,mm3
pXOR mm7,mm1

movq mm1,mm7
movq mm2,mm7
pXOR mm1,mm4
pXOR mm2, qword ptr tblC
movq mm3,mm1
pCMpeqB mm3,mm0
pAND mm3,mm2
pCMpeqB mm2,mm0
pAND mm1,mm2
pOR mm1,mm3
pXOR mm7,mm1
movq [eax],mm7
dec cnt
lea eax,[eax+8]
jnz lp;
end;

呼び出し方
var buf:string;
begin
buf:='AGCT AGCT AGCT AGCT AGCT AGCT';
SetLength(buf,length(buf)+(8-length(buf) mod 8) );
ATCGchg8(@buf[1],length(buf) div 8);
0238197NGNG
>>234

漏れの記憶違いか……?

確認のため、なんとか発掘した
v4.5の日本語マニュアルにはこう書いてあった。

>-Qkscalar デフォルトのx87 命令でなく、
>ストリーミングSIMD 拡張命令を
>使用して、すべての32 ビット浮
>動小数点演算を実行します。

日本語訳が間違えているのかもしれないが、
英語のドキュメントどっか逝ってしまって見つけ出せなかったので確認できず。
ちなみに、v5.0のドキュメントを見たら、-Qkscalarは載ってなかった。
0239212NGNG
>>217の訂正
mov ax, [edi + eax] → mov ax, [edi + eax * 2]

テーブルの計算方法は間違っていました。
 type
  TWordTable = array[Word] of Word;

 procedure SetWordTable(var Table: TWordTable);
 var
  I: Integer;
  H, L: Char;
 begin
  for I := 0 to $FFFF do
  begin
  H := Char(Hi(I));
  L := Char(Lo(I));

  case H of
  'A': H := 'T';
  'T': H := 'A';
  'C': H := 'G';
  'G': H := 'C';
  end;

  case L of
  'A': L := 'T';
  'T': L := 'A';
  'C': L := 'G';
  'G': L := 'C';
  end;

  Table[I] := MakeWord(Byte(L), Byte(H));
  end;
 end;
0240212NGNG
>>223
>純粋にキャッシュヒットしてるんじゃないか?>連続呼び出し
そのようでした。 同じ文字列(同じメモリブロック)がキャッシュに
入っていたみたいです。 UniqueStringで別のアドレスに確保すると、
速くなりませんでした。

AGIストールについても考えてみます。
ありがとうございます。


部分レジスタストールについて質問なのですが、
下の(1)と(2)で発生するのでしょうか?

mov ax, 0
inc ecx
mov ecx, eax // (1)直後でない

@@Loop:
mov ecx, eax // (2)ループ
mov ax, 0
jmp @@Loop
0241212NGNG
また質問です。

http://www.sonycsl.co.jp/person/fnami/pentopt.htm#PPRO
の例で

MOV AL, [mem1] 1 uv
MOV AH, [mem2] 1 uv
MOV [mem3], AX 1
2 + 5(ペナルティー) = 7 clock

MOVZX EAX, BYTE PTR [mem1] 3
MOVZX EBX, BYTE PTR [mem2] 3
SHL EBX, 8 1 u
OR EAX, EBX 1 uv
MOV [mem3], AX 1
8 clock

なので、遅くなりませんか?

これは次のように変更するべき
でブラウザを検索すると見つかります。
0242213NGNG
>240
ん〜(1),(2)ともしないと思うけど?

>241
Pentiumでは部分レジスタストールは発生しないよ?
もうチョッとよく読もうな
そこでの記載はPentiumProとPentium2(3)に関してだし
Ppro系CPUではMOVZXは1クロックだよ(P4では0.5クロック)
μopコード実行だからペアリングなんて概念自体が無いので>Ppro
逆にPentiumではmovzxは重い処理になるのでやるべきじゃない

・Pentium
MOV AL,[mem1];1uv
MOV AH,[mem2];1uv
MOV [mem3],AX;1
2クロック

MOVZX EAX,BYTE PTR [mem1];3
MOVZX EBX,BYTE PTR [mem2];3
SHL EBX,8;1u
OR EAX,EBX;1uv
MOV [mem3],AX;1
8クロック


・PentiumPro
MOV AL,[mem1];1
MOV AH,[mem2];1
MOV [mem3],AX;1+5
約8クロック

MOVZX EAX,BYTE PTR [mem1];1
MOVZX EBX,BYTE PTR [mem2];1
SHL EBX,8;1
OR EAX,EBX;1
MOV [mem3],AX;1
約5クロック

どっちのCPU向けに最適化するかによる
今時だとP2、P3が主流だと思うんでPpro向けの最適化のほうが好ましいと思う
Pentiumでの遅延を減らしたいなら
movzx eax,[mem]→xor eax,eax/mov al,[mem]
に展開するべき(さもなくばCPUによってル−チンを切り替えるか)

ちなみにP4だと何故か展開したほうが速くなるんだよね……>movzx
0243デフォルトの名無しさんNGNG
完全にランダムなDWORD値を作る最速のルーチンを教えて
0244デフォルトの名無しさんNGNG
>>243

真の乱数(規則性なし)は量子コンピュータ持ってきても作れませんが、何か……?
量子力学やカオス理論の世界ですら、
時間をパラメータとする規則性のある数列でしかないことがわかってるし。
自然界では時間は任意に変更できないから、
ある意味真にランダムであるとも言えるだけで。

つーか、ランダム性と処理速度とどっちを重視するのか言ってくれないと、
紹介のしようもない。
0245Delあめ猫にゃNGNG
もちろん完全にランダムじゃないけど
乱数種の一つとして

function RDTSCm:integer;
asm
 DW $310F //RDTSC
 XOR EAX,EDX
 IMUL EAX,65535
end;
0246デフォルトの名無しさんNGNG
>>243
最近のPCならチップセットに乗ってる
ハードで完全にランダムな値、作れるんじゃないの?
漏れのマシンにはついてないけど。
http://developer.intel.com/design/chipsets/rng/faq.htm

レジスタ叩いて読むだけ。
>>244さんはこれでも満足できないのかもしれないけど

ソフトでやるのでは、回数が少なければ、
サイコロ振って乱数表作ってメモリに入れとけば、
規則性のない乱数列が作れるんじゃない。
周期性は避けられないが。
0247デフォルトの名無しさんNGNG
ノイズ拾ってデジタルデータに変換するADCあたりを
シリアルポートにでもつなげ
0248246NGNG
>>247
んならサウンドカードでええやん、
0249デフォルトの名無しさんNGNG
>>248
24bit以上のデータを扱えるオーディオカードならな。
普通のサウンドカードだと、16bit、しかも低い値しか取れないから、
拡大すると荒い乱数しか取れない。
0250212NGNG
213さん、重ね重ねありがとうございます。

215さんも224さんもありがとうございます。
キャッシュが・・・、と言われていたのに・・・。
0251デフォルトの名無しさんNGNG
>>249
例えば32bitの乱数が欲しければ、サンプルの下位1bitだけを
使用するとして32個サンプリングすればよいんじゃないの?
(本当はもっと偏りがないようにうまくやったほうが良いが)

これなら16bitサウンドカードでも大丈夫だ。24bitのサンプル1個を
そのまま乱数に使うってのは頭が悪いとしか思えん。
0252デフォルトの名無しさんNGNG
>>251
速度が遅くなんない?
どのぐらいかかるか知らないけど
0253デフォルトの名無しさんNGNG
>252 というか WavInデバイスを使うってだけで1秒にせいぜい2*44.1K/秒 だからね
 M系列とかの乱数種に プログラム起動時に1回使うだけならともかく
0254デフォルトの名無しさんNGNG
21 34 12 3E FF C9
0255デフォルトの名無しさんNGNG
何クロックかかるとかどの資料を見ればわかりますか?
0256デフォルトの名無しさんNGNG
Intelの資料に書いてあるけど、P6以降はあまり意味がないような・・・
0257デフォルトの名無しさんNGNG
CPUが新しくなるほど遅くなってそうだね。
0258デフォルトの名無しさんNGNG
>255 資料見るより 実際にコード書いて >>245 にあるRDTSCで数えさせる
■ このスレッドは過去ログ倉庫に格納されています