More Related Content
Similar to C++でHello worldを書いてみた
Similar to C++でHello worldを書いてみた(20)
C++でHello worldを書いてみた
- 3. デモ
Ubuntu 14.04 x86-64
$ make -f hello_gen.mk
g++ -fno-operator-names -o hello_gen_gen
hello_gen_gen.cc
./hello_gen_gen > numbers.cc
g++ -o hello_gen hello_gen.cc
./hello_gen > _.c
cc -c -Wa,-R -w _.c
ld _.o -e _ -o hello
./hello
Hello, world!
- 6. C で記号プログラミング ( 復習 )
記号のみでソースコードを記述
int 型の配列 _ を定義して、 text セグメントに
配置してプログラムとして実行する
エントリポイントを _start ではなく _ にする
ことでアルファベット (main) を書くことを回
避
というような記号だけのソースコードを生成
するジェネレータを (C で ) 書いた
- 10. struct Symbolizer
Symbolizer<0>().s -> !””
文字列 ( ポインタ ) の否定はゼロ
Symbolizer<1>().s -> !!””
ゼロの否定は 1
Symbolizer<n>().s ->
Symbolizer<(n & 1)>().s |
(Symbolizer<(n>>1)>().s << 1)
- 11. テンプレートの優位性
マクロ :
0 から 16 までの値を用意する必要があった
テンプレート :
特殊化により、最低限 0, 1, n を用意すれば
、任意の数値が生成できる
例 : コンパイラにフィボナッチ数を計算させる
0 の部分を生成しないようにしたり、 2, 3,
4, ... と個別に用意すれば、コードがコンパ
クトに
- 12. 強化点 2
2010: バイナリ (0xB8, 0x04, ...)
2015: ニーモニック (mov ...)
- 13. C++ でバイナリ生成といえば ...
Xbyak
ニーモニックによる記述が可能に
可読性と保守性の大幅な向上
2010:
MAKE32(_B,_8,_0,_4,_0,_0,_0,_0)
2015:
mov(eax, 4);
- 16. x86-64 対応 (1)
32bit/64bit の両方に対応したい
が、 #ifdef は減らしたい
↓
同じバイト列を生成するようにする
- 17. x86-64 対応 (2)
x86 と x86-64 の命令バイト列はほぼ共
通
64bit の即値代入命令を使い、後半
32bit に jmp 命令を埋め込むこと
で、 32bit モードの時だけ分岐する
これにより同じバイト列で両方に対応
デュアルアーキテクチャ
x86 と x64 の両方で動くシェルコードを書いてみる
http://inaz2.hatenablog.com/entry/2014/07/06/185125
- 18. objdump: x86
$ objdump -d hello
hello: file format elf32-i386
Disassembly of section .text:
08048080 <_>:
8048080: c7 44 24 f0 48 65 6c 6c c7 44 24 f4 6f 2c 20 77 .D$.Hell.D$.o, w
8048090: c7 44 24 f8 6f 72 6c 64 66 c7 44 24 fc 21 0a ba .D$.orldf.D$.!..
80480a0: 0e 00 00 00 48 bb 01 00 00 00 eb 19 00 00 48 8d ....H.........H.
80480b0: 74 24 f0 bf 01 00 00 00 89 f8 0f 05 31 ff b8 3c t$..........1..<
80480c0: 00 00 00 0f 05 8d 4c 24 f0 b8 04 00 00 00 cd 80 ......L$........
80480d0: 31 db b8 01 00 00 00 cd 80 00 00 00 1...........
- 19. objdump: x86-64
$ objdump -d hello
hello: file format elf64-x86-64
Disassembly of section .text:
08048080 <_>:
8048080: c7 44 24 f0 48 65 6c 6c c7 44 24 f4 6f 2c 20 77 .D$.Hell.D$.o, w
8048090: c7 44 24 f8 6f 72 6c 64 66 c7 44 24 fc 21 0a ba .D$.orldf.D$.!..
80480a0: 0e 00 00 00 48 bb 01 00 00 00 eb 19 00 00 48 8d ....H.........H.
80480b0: 74 24 f0 bf 01 00 00 00 89 f8 0f 05 31 ff b8 3c t$..........1..<
80480c0: 00 00 00 0f 05 8d 4c 24 f0 b8 04 00 00 00 cd 80 ......L$........
80480d0: 31 db b8 01 00 00 00 cd 80 00 00 00 1...........
- 21. コードジェネレータジェネレータ
Put St r i ng( const st d: : st r i ng &message) {
unsi gned i nt * dat a = ( unsi gned i nt * ) message. dat a( ) ;
mov( dwor d[ esp - 16] , dat a[ 0] ) ;
mov( dwor d[ esp - 12] , dat a[ 1] ) ;
mov( dwor d[ esp - 8] , dat a[ 2] ) ;
mov( wor d[ esp - 4] , dat a[ 3] ) ;
mov( edx, message. l engt h( ) ) ;
dec( eax) ;
mov( ebx, 1) ;
j mp( " @f " ) ;
add( byt e[ eax] , al ) ;
dec( eax) ;
l ea( esi , pt r [ esp - 16] ) ;
mov( edi , 1) ;
mov( eax, edi ) ;
syscal l ( ) ;
xor ( edi , edi ) ;
mov( eax, 60) ;
syscal l ( ) ;
L( " @@" ) ;
l ea( ecx, pt r [ esp - 16] ) ;
mov( eax, 4) ;
i nt 80h( ) ;
xor ( ebx, ebx) ;
mov( eax, 1) ;
i nt 80h( ) ;
}
スタック上にメッセージを
置く
(x86/x86-64 共通 )
x86-64 用コード
x86 用コード
https://github.com/firewood/test/blob/master/hello_gen_gen.cc