Pythonアセンブラw
今日はPythonの中でアセンブリを書こうと思います。
まだ初歩的なものしか書けないので Hello worldを出力させようと思います。
#test_write.py #!/usr/bin/env python # -*- coding: utf-8 -*- from pyasm import Program from pyasm.data import String from pyasm.registers import eax,ebx,ebp,ecx,edx from pyasm.macro import syscall from pyasm.instructions import mov,ret,push,add def example(): msg = "Hello, World\n" prog = Program( mov(ebx,1), mov(ecx,String(msg)), mov(edx,len(msg)), syscall('write'), ret(), ) fun = prog.compile() fun() if __name__ == '__main__': example()
簡単に説明します。
#Programがソースを書くための土台です。 from pyasm import Program #後ほど説明します。 from pyasm.data import String #レジスタを設定します。どのレジスタを使うか決めます。 from pyasm.registers import eax,ebx,ebp,ecx,edx #システムコールを呼べるようにしてるんかなぁ…w from pyasm.macro import syscall #命令です from pyasm.instructions import mov,ret,push,add #example関数 def example(): #msgに代入 msg = "Hello, World\n" prog = Program( mov(ebx,1), mov(ecx,String(msg)), mov(edx,len(msg)), syscall('write'), ret(), )
ん〜、ちょっと分からんのが、
順番なんですよねぇ〜。
アセンブリなら
movl $4,%eax #writeのシステムコール movl $1,%ebx #1 は stdout movl $msg,%ecx #msgは文字列のポインタ movl $msg_len,%edx #msg_lenはmsgの文字数 int $0x80
でかけるんですが、 Pythonはどうやらちょっと違うっぽいです。
syscall('write')なら直接っぽいですね。
ちなみに、
%ecxに入ってるのは 文字列のポインタなので
>>> from pyasm.data import String >>> a = "Hello world" >>> b = String(a) >>> b <pyasm.data.String object at 0xb736ba8c> >>>
って感じです。
Stringは文字列のアドレスを表記するものですねぇ。
それを %ecx に代入してるって分かればまぁ納得出来ますね。
#アセンブリで書いたので compileしないとダメそうですね。 fun = prog.compile() #返り値は fun() ですかね。 fun()
一通り説明は終わりましたぁ〜
結果は
ashigirl96@bt:~$ python test_write.py Hello, World ashigirl96@bt:~$