|
|
|
2018/1/1(Mon) 17:46:35|NO.82152
あけましておめでとうございます
HSPのマシン語を作成しようとしたのですが、上手くいきません
作成手順は以下のサイトを参考にしました
http://chokuto.ifdef.jp/urawaza/mcn/vc_enumwnd.html
OSはWindows7の64bit版、開発環境はVisual Studio 2017 Communityです。
codファイルを出力した結果、中身は以下のようになりました
( 〜 省 略 〜 )
; Line 4
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 81 ec e8 00 00
00 sub esp, 232 ; 000000e8H
00009 53 push ebx
0000a 56 push esi
0000b 57 push edi
0000c 8d bd 18 ff ff
ff lea edi, DWORD PTR [ebp-232]
00012 b9 3a 00 00 00 mov ecx, 58 ; 0000003aH
00017 b8 cc cc cc cc mov eax, -858993460 ; ccccccccH
0001c f3 ab rep stosd
; Line 5
0001e c7 45 f8 11 11
11 11 mov DWORD PTR _p_hwnd$[ebp], 286331153 ; 11111111H
; Line 6
00025 c7 45 ec 22 22
22 22 mov DWORD PTR _p_cnt$[ebp], 572662306 ; 22222222H
; Line 7
0002c c7 45 e0 33 33
33 33 mov DWORD PTR _max_num$[ebp], 858993459 ; 33333333H
; Line 9
00033 8b 45 ec mov eax, DWORD PTR _p_cnt$[ebp]
00036 8b 4d e0 mov ecx, DWORD PTR _max_num$[ebp]
00039 39 08 cmp DWORD PTR [eax], ecx
0003b 7c 04 jl SHORT $LN2@EnumWindow
; Line 10
0003d 33 c0 xor eax, eax
0003f eb 32 jmp SHORT $LN1@EnumWindow
$LN2@EnumWindow:
; Line 11
00041 8b 45 ec mov eax, DWORD PTR _p_cnt$[ebp]
00044 8b 08 mov ecx, DWORD PTR [eax]
00046 c1 e1 02 shl ecx, 2
00049 8b 55 f8 mov edx, DWORD PTR _p_hwnd$[ebp]
0004c 8b 45 08 mov eax, DWORD PTR _hwnd$[ebp]
0004f 89 04 0a mov DWORD PTR [edx+ecx], eax
; Line 12
00052 8b 45 ec mov eax, DWORD PTR _p_cnt$[ebp]
00055 89 85 18 ff ff
ff mov DWORD PTR tv71[ebp], eax
0005b 8b 8d 18 ff ff
ff mov ecx, DWORD PTR tv71[ebp]
00061 8b 11 mov edx, DWORD PTR [ecx]
00063 83 c2 01 add edx, 1
00066 8b 85 18 ff ff
ff mov eax, DWORD PTR tv71[ebp]
0006c 89 10 mov DWORD PTR [eax], edx
; Line 13
0006e b8 01 00 00 00 mov eax, 1
$LN1@EnumWindow:
; Line 14
00073 5f pop edi
00074 5e pop esi
00075 5b pop ebx
00076 8b e5 mov esp, ebp
00078 5d pop ebp
00079 c2 08 00 ret 8
_EnumWindowsProc@8 ENDP
_TEXT ENDS
END
↓は参考サイトを元に変換したマシン語コード
fncode.0=$81ec8b55,$0000e8ec,$57565300,$ff18bd8d,$3ab9ffff,$b8000000
fncode.6=$cccccccc,$45c7abf3,$111111f8,$ec45c711,$22222222,$33e045c7
fncode.12=$8b333333,$4d8bec45,$7c0839e0,$ebc03304,$ec458b32,$e1c1088b
fncode.18=$f8558b02,$8908458b,$458b0a04,$188589ec,$8bffffff,$ffff188d
fncode.24=$83118bff,$858b01c2,$ffffff18,$01b81089,$5f000000,$e58b5b5e
fncode.30=$0008c25d
上記のマシン語をスクリプトに組み込み実行した結果、エラーが出てしまいました
HSPで正しく動作するマシン語が出力されるようにするには、どうすればよいのでしょうか?
ちなみに下は参考サイトに載っていたマシン語です
こちらは問題なく動作しました
fncode = $222222b8, $81088b22, $333333f9, $33057c33, $0008c2c0, $0424548b
fncode.6 = $118d1489, $8b111111, $08894108, $000001b8, $0008c200
よろしくお願いします
| |
|
2018/1/4(Thu) 15:03:53|NO.82160
HSP側のソースはどうしたのでしょうか?
ちょくとさんのはHSP2時代のソースなのでHSP3だと少々修正しないといけないんですよね。
一応HSP2.61で確認してみましたが、ちょくとさんの方はできましたが、
雪月夜さんのマシン語はエラーになるのは確認できました。
Cのソースもちょくとさんとものと同じですよね?
こちらはWindows10ですが、同じ開発環境でコンパイルしてみましたが雪月夜さんとは
微妙に違うものが出力されて……
さらにそちらもエラーでした。
Visual Studioって設定で出力されるマシン語が変わるので、
それでも前にマシン語使ってみた時は出来たんですが、当時のソースが行方不明……
且つマシン語が久しぶりすぎてどうやってたかすら忘れている始末……
デバッグだとマシン語が出力できるのにリリースだとヘッダ部分しか出力してくれないし……
ちょっと愚痴や言い訳が入ってしまいましたが、
コンパイラよりもHSP側のバージョンやソースを見せていただければ、
忘却状態の私よりも的確な回答して下さる方が出て来ると思いますよ。
|
|
2018/1/5(Fri) 00:50:58|NO.82169
あまらさん、返信ありがとうございます
>HSP側のソースはどうしたのでしょうか?
失礼しました
確認に用いたHSPのソースは以下になります
#include "llmod3/llmod3.hsp"
#ifndef xdim
#uselib "kernel32.dll"
#func global VirtualProtect@_xdim "VirtualProtect" var,int,int,var
#define global xdim(%1,%2) dim %1,%2: VirtualProtect@_xdim %1,%2*4,$40,x@_xdim
#endif
; マシン語を変数に格納する (必ず xdim を使用すること)
xdim fncode, 11
fncode = $222222b8, $81088b22, $333333f9, $33057c33, $0008c2c0, $0424548b
fncode.6 = $118d1489, $8b111111, $08894108, $000001b8, $0008c200
; マシン語コードのアドレス(コールバック関数アドレス)取得
getptr pfn, fncode
; カウンタ用変数のアドレスを1バイト目にセット
getptr t, wndcnt
memcpy fncode, t, 4, 1
; 列挙するウィンドウの最大数(配列の要素数)を9バイト目にセット
t = 256
memcpy fncode, t, 4, 9
; ウィンドウハンドルを格納する配列変数のアドレスを$1bバイト目にセット
dim ahwnd, 512
getptr t, ahwnd
memcpy fncode, t, 4, $1b
; カウンタを 0 にセット
wndcnt = 0
; EnumWindows の呼び出し
pm = pfn, 0
dllproc "EnumWindows", pm, 2, D_USER
dialog "" + wndcnt + "個のウィンドウハンドルが取得されました。"
stop
HSPのバージョンは最新版の3.5です
参考サイトそのままでは実行できなかったので一部修正しました
>Cのソースもちょくとさんとものと同じですよね?
はい、サイトの「ソースファイル enumwnd.c」とまったく同じです
後で分かったんですが、確かにDebugとReleaseでは出力結果が異りますね
最初に投稿したのはデバックの方で、リリースだと以下のようになりました
; Line 4
00000 55 push ebp
00001 8b ec mov ebp, esp
00003 83 ec 0c sub esp, 12 ; 0000000cH
; Line 5
00006 c7 45 f4 11 11
11 11 mov DWORD PTR _p_hwnd$[ebp], 286331153 ; 11111111H
; Line 6
0000d c7 45 fc 22 22
22 22 mov DWORD PTR _p_cnt$[ebp], 572662306 ; 22222222H
; Line 7
00014 c7 45 f8 33 33
33 33 mov DWORD PTR _max_num$[ebp], 858993459 ; 33333333H
; Line 9
0001b 8b 4d f8 mov ecx, DWORD PTR _max_num$[ebp]
0001e 8b 45 fc mov eax, DWORD PTR _p_cnt$[ebp]
00021 39 08 cmp DWORD PTR [eax], ecx
00023 7c 08 jl SHORT $LN2@EnumWindow
; Line 10
00025 33 c0 xor eax, eax
; Line 14
00027 8b e5 mov esp, ebp
00029 5d pop ebp
0002a c2 08 00 ret 8
$LN2@EnumWindow:
; Line 11
0002d 8b 45 fc mov eax, DWORD PTR _p_cnt$[ebp]
00030 8b 4d f4 mov ecx, DWORD PTR _p_hwnd$[ebp]
00033 8b 10 mov edx, DWORD PTR [eax]
00035 8b 45 08 mov eax, DWORD PTR _hwnd$[ebp]
00038 89 04 91 mov DWORD PTR [ecx+edx*4], eax
; Line 12
0003b 8b 45 fc mov eax, DWORD PTR _p_cnt$[ebp]
0003e ff 00 inc DWORD PTR [eax]
; Line 13
00040 b8 01 00 00 00 mov eax, 1
; Line 14
00045 8b e5 mov esp, ebp
00047 5d pop ebp
00048 c2 08 00 ret 8
_EnumWindowsProc@8 ENDP
_TEXT ENDS
END
ちなみにこちらの方もHSPではエラーになりました
| |
|
2018/1/5(Fri) 01:50:13|NO.82171
少し思い出してきたので、試してみたら成功しました。
HSPのソースは雪月夜さんの物に少し手を加えさせていただきました。
マシン語はリリースの方です。
;#include "llmod3/llmod3.hsp"
#uselib "user32.dll"
#func global EnumWindows "EnumWindows" sptr, sptr
#ifndef xdim
#uselib "kernel32.dll"
#func global VirtualProtect@_xdim "VirtualProtect" var,int,int,var
#define global xdim(%1,%2) dim %1,%2: VirtualProtect@_xdim %1,%2*4,$40,x@_xdim
#endif
; マシン語を変数に格納する (必ず xdim を使用すること)
;xdim fncode, 11
;fncode = $222222b8, $81088b22, $333333f9, $33057c33, $0008c2c0, $0424548b
;fncode.6 = $118d1489, $8b111111, $08894108, $000001b8, $0008c200
xdim fncode, 19
fncode.0 = $83ec8b55, $45c70cec, $111111f4, $fc45c711, $22222222, $33f845c7
fncode.6 = $8b333333, $458bf84d, $7c0839fc, $8bc03308, $08c25de5, $fc458b00
fncode.12 = $8bf44d8b, $08458b10, $8b910489, $00fffc45, $000001b8, $5de58b00
fncode.18 = $000008c2
; マシン語コードのアドレス(コールバック関数アドレス)取得
;getptr pfn, fncode
pfn = varptr(fncode);
; カウンタ用変数のアドレスを1バイト目にセット
;getptr t, wndcnt
t = varptr(wndcnt);
;memcpy fncode, t, 4, 1
memcpy fncode, t, 4, 16
; 列挙するウィンドウの最大数(配列の要素数)を9バイト目にセット
t = 256
;memcpy fncode, t, 4, 9
memcpy fncode, t, 4, 23
; ウィンドウハンドルを格納する配列変数のアドレスを$1bバイト目にセット
dim ahwnd, 512
;getptr t, hwnd
t = varptr(ahwnd);
memcpy fncode, t, 4, 9
; カウンタを 0 にセット
wndcnt = 0
; EnumWindows の呼び出し
;pm = pfn, 0
;dllproc "EnumWindows", pm, 2, D_USER
EnumWindows pfn, 0
dialog "" + wndcnt + "個のウィンドウハンドルが取得されました。"
stop
変更前の部分もコメントとして残してあります。
変更点としては
・getptrがvarptrの登場によって不要となったためllmod3を退場
・llmod3に含まれるdllprocも直接EnumWindowsを用意して退場
・そして一番重要な点がmemcpyのオフセットの変更です。
リリースのマシン語を余計な部分を削って並べてみると
55 8b ec 83 ec 0c c7 45 f4 11
11 11 11 c7 45 fc 22 22 22 22
c7 45 f8 33 33 33 33 8b 4d f8
8b 45 fc 39 08 7c 08 33 c0 8b
e5 5d c2 08 00 8b 45 fc 8b 4d
f4 8b 10 8b 45 08 89 04 91 8b
45 fc ff 00 b8 01 00 00 00 8b
e5 5d c2 08 00
このようになります。
このマシン語の中の
22 22 22 22
33 33 33 33
11 11 11 11
この3つのコードがある位置がオフセット位置になっているわけです。
22……が16バイト目
33……が23バイト目
11……が9バイト目
memsetのオフセットをこのバイトに合わせて変えないとエラーになってしまいます。
ちょくとさんのCソースや、あとの文章でも説明はされているのですが、
マシン語抜き出し、引っ繰り返して並べ替え等々に気を取られて見逃してしまうんですよね。^^;
| |
|
2018/1/5(Fri) 18:22:38|NO.82176
ぐあーお恥ずかしい(汗
確かにちゃんと「〜バイト目にセット」と書かれていましたね、もっと注意を払うべきでした
再考編の方だとそういうのは考えなくて良いみたいなのでそっちを先にやれば良かったです
あまらさん、どうもありがとうございます
おかげさまでマシン語を使ったプログラムを作成することが出来ました
この質問は解決済みとさせていただきます
ためしにマシン語でコードを組んでみました
#uselib "kernel32.dll"
#func global VirtualProtect "VirtualProtect" var,int,int,var
#define global xdim(%1,%2) dim %1,%2:VirtualProtect@ %1, %2*4,$40,AZSD
#module
#deffunc sort array p1,int flg
xdim code,28
code.0 =$51ec8b55,$0c5d8b53,$000001b8,$738d5600,$fc7589ff,$437ef685
code.6 =$5708558b,$8b0c4589,$3bc88bfa,$831f7dc3,$8b00107d,$f28b8a14
code.12=$2d75078b,$2d7cd03b,$4108558b,$e77ccb3b,$8b0c458b,$8340fc75
code.18=$ee8304c7,$0c458901,$75fc7589,$0001b8cc,$5e5f0000,$5de58b5b
code.24=$7ed03bc3,$08558bd3,$898a0489,$00cceb37
prm=varptr(p1),length(p1),flg
pcode=varptr(code)
return callfunc(prm, pcode, 3)
#global
sdim list,10000
randomize
sum=1000
dim a,sum
repeat sum
a(cnt)=rnd(sum)
loop
sort a,0 ;0,昇順 1,降順
title"並べ替え"
repeat sum
list+=""+a(cnt)+"\n"
loop
mesbox list,640,480
標準命令で組んだコードよりも200倍以上高速でした
マシン語の処理速度を実感できて満足です
| |
|
2018/1/5(Fri) 18:44:14|NO.82177
> あとリリースのマシン語は
> メニューの「プロジェクト」>「〜のプロパティ」>構成プロパティ>C/C++>最適化
> の「プログラム全体の最適化」を「いいえ」にすると出力されます
すみません書き込みに気がつくのが遅くなりましたが、
おかげ様でリリースでも出力できるようになりました。
マシン語も無事成功おめでとうございます。
|
|