HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0506
hspailマシン語で浮動小数点実数の演算10解決


hspail

リンク

2009/5/6(Wed) 10:37:52|NO.24984

マシン語で 3.0 + 2.5 (数値は適当です)を計算するプログラムを作っているのですが、質問があります。
Cのソースはスクリの一番上に書いてあります。



/*----------------------------- #include <windows.h> double WINAPI func(double *p1) { double a = *p1; return a+2.5; } -----------------------------*/ #uselib "kernel32" #func global VirtualProtect "VirtualProtect" var, int, int, var #define global xdim(%1,%2) dim %1, %2 : VirtualProtect %1, %2*4, $40, rrr #module #deffunc getdouble if code == 0 { xdim code, 3 code = $0424448b,$04c218dd,$00000000 fret=0.0 } prm = varptr(fret) res = callfunc(prm, varptr(code), 1) return fret #global xdim mcncode, 4 mcncode = $0424448b, $05dc00dd, $00000000, $000004c2 a = 3.0 prm = varptr(a) ret = callfunc(prm, varptr(mcncode), 1) getdouble dialog refdval end
これを実行すると、callfunc の部分でシステムエラーになります。




/*----------------------------- #include <windows.h> double WINAPI func(double *p1, double *p2) { double a = *p1; double b = *p2; return a+b; } -----------------------------*/ #uselib "kernel32" #func global VirtualProtect "VirtualProtect" var, int, int, var #define global xdim(%1,%2) dim %1, %2 : VirtualProtect %1, %2*4, $40, rrr #module #deffunc getdouble if code == 0 { xdim code, 3 code = $0424448b,$04c218dd,$00000000 fret=0.0 } prm = varptr(fret) res = callfunc(prm, varptr(code), 1) return fret #global xdim mcncode, 4 mcncode = $0424448b, $448b00dd, $00dc0824, $000008c2 a = 3.0 b = 2.5 prm = varptr(a), varptr(b) ret = callfunc(prm, varptr(mcncode), 2) getdouble dialog refdval end
これだとエラーになりません。
どうしてでしょうか?


要は 数値 2.5 をマシン語の中に埋め込むか、HSPから渡すのかの違いですが・・・
上のスクリのような書き方をしたいのですが、どうにかならないでしょうか?


よろしくお願いします。



この記事に返信する


hspail

リンク

2009/5/6(Wed) 10:38:18|NO.24985

ちなみに

#include <windows.h> double WINAPI func(double *p1) { double a = *p1; return a*2.5; }
だとエラーが出るけれど、


#include <windows.h> double WINAPI func(double *p1) { double a = *p1; return a*2.0; }
だとエラーが出ません。

実数の計算はできないのでしょうか?
何かわかる方居ましたらお願いします。



KA

リンク

2009/5/6(Wed) 11:32:00|NO.24987

私の技量範囲外のことなので、的確な回答はできませんが。

1:見ただけでは何の事か分からない。(実行して大体分かった)
2:Cでコンパイルして、アセンブラコードを抜き出し、HSPに
  組み込むのなら、最初からHSPで計算した方が建設的では?

>>a = 3.0
>>b = 2.5
>>c = a+b
>>dialog c
>>end

デジャブ?



hspail

リンク

2009/5/6(Wed) 12:10:00|NO.24989

回答ありがとうございます。
大量の計算を行うのでHSPでは処理が追いつかず、マシン語を使うことにしました。



natu

リンク

2009/5/6(Wed) 13:00:10|NO.24993

【エラーになっているコードの逆アセンブラ】CS ← とあるコードセグメント内のアドレス

  アドレス| 機械語 | ニーモニック等
  CS : 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
  CS+4: DD00 FLD QWORD PTR DS:[EAX]
  CS+6: DC05 00000000 FADD QWORD PTR DS:[0]
  CS+C: C2 0400 RETN 4

上の逆アセンブラコードから分かるとおり、データセグメント上の0番地を参照しているからエラーになります.
x86 FPU は即値オペランドを持たないから、データを一旦メモリに保存しそのアドレスを参照するわけです.
現状ではエラーの出ない方を採用したほうが無難かと思います.



natu

リンク

2009/5/6(Wed) 16:24:43|NO.24999

ひとつスレ見忘れてました(^^;
double WINAPI func(double *p1) {
double a = *p1; return a*2.0; }
だとエラーが出ないのは、コンパイラが return (a+a); とか最適化しているので、即値 2.0 が参照されないからでしょう.
ためしに a*2.0 のコードを逆アセンブルせば a+a のコードに最適化されるでしょう.足し算が掛け算より速いのは有名ですね.



hspail

リンク

2009/5/7(Thu) 04:08:31|NO.25018

natsu さん、ありがとうございます。

>現状ではエラーの出ない方を採用したほうが無難かと思います.
実数のリテラルを使用する方法はあるのでしょうか?


>だとエラーが出ないのは、コンパイラが return (a+a); とか最適化しているので、即値 2.0 が参照されないからでしょう.
そういうことですか。ありがとうございます。



moa

リンク

2009/5/7(Thu) 07:02:03|NO.25020

>実数のリテラルを使用する方法はあるのでしょうか?
自分でプログラム内のアドレスを書き換えれば可能だけど面倒でしょ?
他の方法も考えればありそうだけど、結局はHSPから引数で渡した方が楽だとおもう。
あ、でも0.0や1.0といった特別な値ならそのまま使えると思う。
x86FPUには特別な定数をロードする専用の命令があるので。



hspail

リンク

2009/5/7(Thu) 17:38:42|NO.25029

> moa さん
やっぱり書き換えしかないですか。面倒ですね。

固定小数を使って実装してみることにします。
皆さんありがとうございました。



natu

リンク

2009/5/7(Thu) 21:24:08|NO.25035

C言語で高速化するなら、CでDLLを作成した方が簡単ではありませんか?
アセンブラで高速化するならマシン語を扱う意味はあると思いますが…
それにDLLとしてmakeすることで高速化につながることもあります。
例えばコンパイラ(linkerも含む)がジャンプテーブルを使って分岐したりだとか、コードをalignさせたりだとか…
とてもHSP側でアドレスを書き換えるなんてことはできないですから.



hspail

リンク

2009/5/9(Sat) 02:05:51|NO.25054

>natu さん
私もちょうど DLL を作ればいいじゃないかと思っていました。
何で今までマシン語に拘っていたのか謎です(笑
DLLで実装してみたいと思います。
ありがとうございました。



ONION software Copyright 1997-2023(c) All rights reserved.