« 2007年10月 | トップページ | 2007年12月 »

2007年11月の5件の記事

2007-11-26

Perlでコールバック サブルーチンの引数としてサブルーチンの参照を渡す

サブルーチンの引数に、
配列、ハッシュ(連想配列)などを渡してきました。
今回は、サブルーチンにサブルーチンを渡します。
C言語のクイックソートのコールバックのように使えます。
渡し方は至って簡単です。
配列やハッシュを渡すのと同じように、
関数のアドレスを渡してやります。

下の例では、サブルーチンsubjectに、
サブルーチンcallbackの参照を渡します。
subject内では引数として渡された、
callbackをfuncという変数に代入し、
このfuncをコールします。
コールすると1秒間待機した後にループします。
このループを10回繰り返します。


01: sub callback
02: {
03:   my $val = $_[0];
04: 
05: # print "\x1b[0D;$val%\n\x1b[1A;";
06:   print "$val%\n";
07: }
08: 
09: sub subject
10: {
11:   my $func = $_[0];
12: 
13:   for ($i = 0; $i < 10; ++$i) {
14:     &$func($i * 10);
15:     sleep(1);
16:   }
17:   print "completed\n";
18: }
19: 
20: &subject(\&callback);


5行目のサブルーチンcallbackのコメントしてある箇所ですが、
Linuxではエスケープシーケンスが利用できますが、
Windows 2000/XPでは、エスケープシーケンスが
利用できないようですので、
Windows 2000/XP以外のOSでテストする場合には、
6行目をコメントとして、5行目を実行させると、
ちょっとそれらしい感じになるかも知れません。
Windows98などは、エスケープシーケンスが利用できるようです。
Windows Vistaは、多分できないと思います。
LinuxとWindows XPのみ検証済みです。

この程度のサブルーチンで、複数箇所から利用されない場合には、 無名サブルーチンの参照を渡してしまうと、もっと簡単になります。
可読性の問題は出てくるかもしれませんが。

callbackサブルーチンをコメント化してしまって、最後の &subject (\&callback); の部分を
&subject ( sub { print "$_[0]%\n"; } );
とすると、callbackサブルーチンを無名サブルーチンのリファレンスとして渡す事ができ、callbackサブルーチンを定義した場合と同じ結果が得られると思います。


| | コメント (0) | トラックバック (0)

2007-11-15

独習アセンブラ リスト4-4

独習アセンブラ 翔泳社の第四章のリスト 4-4です。

スタックは通常、先に積んだ物の上に
後から積む物が、上に載せられるイメージなので、
当然上の物を取り出さない限り、
下の物を取り出す事は出来ませんので、
先に積んだ物は、後から取り出す事になります。

この順序を意図的に変更する事で、
レジスタ内の値を交換します。


01: section .text
02: global  _start
03: 
04: _start:
05:         push    0x31
06: 
07:         mov     edx, 4
08:         mov     eax, 1
09: 
10:         push    edx
11:         push    eax
12: 
13:         pop     edx
14:         pop     eax
15: 
16:         mov     ebx, 1
17:         mov     ecx, esp
18:         int     0x80
19: 
20:         pop     eax
21: 
22:         mov     eax, 1
23:         mov     ebx, 0
24:         int     0x80


Linuxのシステムコールでは、
eaxに4
edxには、出力するバイト数を指定しますが、
ここでは、これを逆にします。
eax = 1
edx = 4
と指定します。

これを一度スタックに積み、
逆の順序で取り出すことで、
eaxとedxの内容を交換します。

5行目と20行目のpushとpopは、
出力される文字 '1' ( 0x31 )です。





| | コメント (0) | トラックバック (0)

独習アセンブラ リスト4-3

独習アセンブラ 翔泳社の第四章のリスト 4-3です。
XCHG命令で、ソースとディスティネーションの内容を交換します。


01: section .data
02:
03: msg     db 'Hello, assembler', 0x0a
04: len     equ $ - msg
05:
06: section .text
07: global  _start
08:
09: _start:
10:         mov     dl,  [msg]
11:         xchg    dl,  [msg + 1]
12:         mov     [msg], dl
13:
14:         mov     eax, 4
15:         mov     ebx, 1
16:         mov     ecx, msg
17:         mov     edx, len
18:         int     0x80
19:
20:         mov     eax, 1
21:         mov     ebx, 0
22:         int     0x80


10行目でdlの内容が'H'となります。
続いて11行目でdlの内容が'e'(msg + 1)
msg + 1の内容が'H'になります。
この時点でメモリ上のmsgは、
HHllo, assembler\n
となっている筈です。

12行目で、'H'([msg])にdlの内容'e'を移動するので、
メモリ上のmsgは、
eHllo, assembler\n
となりました。

あとは、出力するだけです。




| | コメント (0) | トラックバック (0)

2007-11-12

独習アセンブラ リスト4-2

独習アセンブラ 翔泳社の第四章のリスト 4-2です。
メモリのアドレスを操作する事で、
任意のデータを取得します。


01: section .data
02: 
03: msg     db 'Hello, assembler', 0x0a
04: 
05: section .text
06: global  _start
07: 
08: _start:
09:         mov     eax, [msg]
10:         push    eax
11:         mov     eax, 4
12:         mov     ebx, 1
13:         mov     ecx, esp
14:         mov     edx, 1
15:         int     0x80
16:         pop     eax
17: 
18:         mov     eax, [msg + 7]
19:         push    eax
20:         mov     eax, 4
21:         mov     ecx, esp
22:         int     0x80
23:         pop     eax
24: 
25:         mov     eax, 1
26:         mov     ebx, 0
27:         int     0x80


9行目はmsgのアドレスの値を得ます。
msgの値は、以下のような感じになっています。
msg +  0 = 'H'
msg +  1 = 'e'
msg +  2 = 'l'
msg +  3 = 'l'
msg +  4 = '0'
msg +  5 = ','
msg +  6 = ' '
msg +  7 = 'a'
msg +  8 = 's'
msg +  9 = 's'
msg + 10 = 'e'
msg + 11 = 'm'
msg + 12 = 'b'
msg + 13 = 'l'
msg + 14 = 'e'
msg + 15 = 'r'
msg + 16 = 0x0a

なので、18行目の[msg + 7]の値はaになります。

本文の例の説明には、
msgが指すメモリアドレスの文字とmsgの8番目の文字[msg + 7]を参照して、
MOVで移動するコードを含む

とあるので、一度eaxに移動してからスタックにプッシュしています。
eaxに移動しないでも、push dword [msg + 7]とする事で、
同じ事ができました。




| | コメント (0) | トラックバック (0)

2007-11-06

独習アセンブラ リスト1-4

リストの1-3は、1-2と同じような物なので、
ここでは省略します。

次は、リスト1-4です。
add命令が出てきます。
加算です。

サンプルリストでは、1 + 5を行っています。
01:  section .text
02:  global  _start
03:
04:  _start:
05:          mov     edx, 1
06:          add     edx, 5
07:          add     edx, 0x30
08:          push    edx
09:          mov     eax, 4
10:          mov     ebx, 1
11:          mov     ecx, esp
12:          mov     edx, 1
13:          int     0x80
14:          pop     edx
15:
16:          mov     eax, 1
17:          mov     ebx, 0
18:          int     0x80
まず始めに、edxを1にして
6行目、7行目で足し算をしています。
6行目の足し算は単純に5を足します。
これで、1+5の結果がedxの値となります。
7行目の足し算は文字コードの'0'を足しています。
文字コードは、'0', '1', '2', '3', '4'と並んでいます。
つまり、'0'が0x30で0x31は'1'です。
0x36は'6'になります。
数値としての6ではなく、
文字としての'6'です。
この'6'という文字を、リスト1-1と同じように
画面に出力します。

以前やったように
スタックのポインタが指すアドレスを
下のように直接操作しても問題ありません。(多分)
add     esp, 4






| | コメント (0) | トラックバック (0)

« 2007年10月 | トップページ | 2007年12月 »