download
kono先生のディレクトリをcloneする
$rsync -avzP yomitan:../../../teacher/kono/public_html/compiler/compiler-examples ./
$ make clean
$ rm s-calc
$ rm s-intel
$ make s-calc
$ make s-intel
s-intel
この s-intel
はkono先生が作ったx86系アーキテクチャのAssemblerをインタプリタのように出力する。
例えば1+3を入力すると
#APP
.file "s-calc.c"
.text
.align 2
.globl main
main:
pushl %ebp
movl %esp,%ebp
subl $1028,%esp
1+3
##### 1+3
movl $3,%eax
pushl %eax
movl $1,%eax
popl %ebx
addl %ebx,%eax
call _print
## 1+3
などと出力される。
このkono先生の結果と自分で作ったアセンブラの結果を比較しながら読んでいこう。
asmb
1からアセンブラを書いてもいいが、荷が重い。 そこで適当なCを作成して、コンパイルし、これを使っていく
#include <stdio.h>
int main(void){
int d = 7;
printf("%d\n",d);
return 0;
}
これをアセンブラで出力する
$ clang -O0 -S hoge.c
そうすると適当な雛形ファイルが生成される.
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
movl $0, -4(%rbp)
movl $7, -8(%rbp)
movl -8(%rbp), %esi
movb $0, %al
callq _printf
xorl %esi, %esi
movl %eax, -12(%rbp) ## 4-byte Spill
movl %esi, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "%d\n"
.subsections_via_symbols
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
Ltmp2のこの前後はテンプレである。
movl $0, -4(%rbp)
movl $7, -8(%rbp)
movl -8(%rbp), %esi
movb $0, %al
callq _printf
一方このmovlの命令は7の出力に関わっているのみである。
ここから%al
に対して値を渡せば,print出来るとかんがえられる。
よってこの部分を修正していこう。
tree
実際にアセンブラにする前に、構文木を作る必要がある。
例えば 3+4*2
は
| +|
| |
v v
| 3| | * |
| |
v v
|4| | 2|
このようになる。 演算子と数値が同じ深さに並んでいる場合、それはスタックを利用して演算する必要がある事示している。 基本は深く、右からやるなどが良いかもしれない。
ex1
例えば3-(4-2)は次のようになる。
ここで addq
などの向きを気をつける。
また64bitでの演算にするか、適切に32bitで演算できるようにする必要性がある。
命令についてはこのサイトがわかりやすいだろう。
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
movq $3,%rax
pushq %rax
movq $4,%rax
movq $2,%rbx
subq %rbx,%rax # 4-2 ...sub S,D D<- D - S
popq %rbx
subq %rax,%rbx # 3- (4-2)
movq %rbx,%rsi
movb $0, %al
callq _printf
xorl %esi, %esi
movl %eax, -12(%rbp) ## 4-byte Spill
movl %esi, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "%d\n"
.subsections_via_symbols
ex2
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp0:
.cfi_def_cfa_offset 16
Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp2:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq L_.str(%rip), %rdi
movq $0,%rax # 0
pushq %rax # stack [0]
movq $1,%rax # 1
movq $3,%rbx #3
movq $2,%rcx #2
subq %rcx,%rbx # 3-2
addq %rbx,%rax # 1+ (3-2)
pushq %rax stack[0,(1+(3-2))]
movq $0,%rax
movq $1,%rbx
movq $2,%rcx
movq $3,%rdx
subq %rdx,%rcx # 2-3
addq %rcx,%rbx # 1+(2-3)
addq %rbx,%rax # 0+(1+(2-3))
popq %rbx # %rbx <- 1+(3-2)
subq %rax,%rbx # 1+(3-2) - (0+(1+(2-3)))
popq %rax # %rax <- 0
addq %rbx,%rax #0+(1+(3-2))-(0+(1+(2-3)))
movq %rax,%rsi
movb $0, %al
callq _printf
xorl %esi, %esi
movl %eax, -12(%rbp) ## 4-byte Spill
movl %esi, %eax
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "%d\n"
.subsections_via_symbols