contributed by <tina0405
>
記得固定格式喔!
課程助教
是 Wikipedia,而非 wiki,兩者不同
cross compiler: is a compiler capable of creating executable code for a platform other than the one on which the compiler is running
所需背景知識
LLVM 現在已不可以稱作 Low Level Virtual Machine
Frontend LLVM Backend
C/C++ -> IR -> X86 組語
利用 Brainfuck instruction 來得到 C 的執行檔:
產生 C 的執行檔或 ELF ,可以透過 Brainfuck instruction (不同類型的指令)來產生
Brainfuck instruction
|
Brainfuck Compiler
/ \
ELF C 的執行檔
Character | C | Meaning |
---|---|---|
> | ++p | increment the data pointer (to point to the next cell to the right) |
< | - -p | decrement the data pointer (to point to the next cell to the left) |
+ | ++*p | increment (increase by one) the byte at the data pointer. |
- | - -*p | decrement (decrease by one) the byte at the data pointer. |
. | putchar(*p) | output the byte at the data pointer. |
, | *p=putchar() | accept one byte of input, storing its value in the byte at the data pointer. |
[ | while(*p){ | if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command. |
] | } | if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command. |
brainfunction: [-]
C: Clean
while(cell[0])
{
--cell[0];
}
影片中 Interpreter 和 Static Compiler 的比較
影片中提到的 JIT compiler( Just-in-time compilation )
而通常程序有兩種進行方式是上述的: Dynamic Interpreter 和 Static Compiler, 但 JIT compiler 集合兩種特性:
然後呈現的結果是 Dynamic(JIT compiler) 不做最佳化的效率贏過 Static Compiler 做最佳化
碎形 (fractal)
__libc_start_main :
function shall initialize the process, call the main function with appropriate
arguments, and handle the return from main.
__libc_start_main is not in the source standard;
it is only in the binary standard.
Usage: as_exec [-w] [-x] [-o <out_file>] <in_file>
-w Assemble <in_file> and write to an ELF file, see -o below
-o if -w is specifed, <out_file> is used to store the object code
-x Load <in_file> and execute it
<in_file> the file name to be used by commands above
tests/fib-recursive.s
和 tests/fib-iterative.s
vm.c
(和對應的原始程式碼),允許執行時期由使用者 (和 Makefile
) 帶入參數,如 --input
,這數值應該透過暫存器作為上述 Fibonacci 數列程式的 Fib(N)
Fibonacci number : the Fibonacci numbers are the numbers in the following integer sequence, called the Fibonacci sequence
定義: every number after the first two is the sum of the two preceding ones
Fib(N) 就是要求出數列中的第 N 個為多少 :
or $0 $0 #1 ;R_1 : initial the first number
or $0 $1 #2 ;R_2 : initial the second number
or $0 $0 #3 ;R_3 for temp
or $0 $0 #0 ;R_0 for input
jz #0 #12 ;if 0,print 0
or $0 #2 #3 ;temp = R_2
add #1 #2 #2 ;R_2 = R_1 + R_2
or $0 #3 #1 ;R_1 = temp
sub #0 $1 #0 ;input-1
jnz #0 #5 ;jump back until it become 0
print #2
halt
print $0
halt
int fib(int x) {
if (x == 0)
return 0;
if (x == 1)
return 1;
return fib(x-1)+fib(x-2);
}
fin(5)
/ \
fin(4) fin(3)
/ \ / \
fin(3) fin(2) fin(2) fin(1)
/ \ / \ / \ / \
fin(2)fin(1)fin(1)fin(0).....
/ \
fin(1) fin(0)
or $0 $0 #1 ;r_1=output
or $2 $0 #0 ;r_0=input
call #5
print #1
halt
xor #0 $1 #2 ;r_2=compare register
jnz #2 #9 ;jump,if!=1
add #1 $1 #1 ;if==1,output add
ret
xor #0 $0 #2
jnz #2 #12 ;jump,if!=1
ret ;if==0,return
sub #0 $1 #0
call #5
sub #0 $1 #0
call #5
add #0 $2 #0
ret
--input
的設計,我想要他和 -w
一起打包成一個 elf ,所以不和 -x
一起使用...
} else if (!strcmp(argv[i], "--input")) {
if (!argv[i + 1])
FATAL(-1, "Fib(N) need int as a parameter , see -h\n");
if (req == LOAD_ELF_AND_EVAL)
FATAL(-1, "-x and --input used together, see -h\n");
int Fib_N = atoi(argv[++i]);
}
...
driver.c
本身不該知道特定程式的存在,這些錯誤訊息應該移到組合語言程式中。driver.c
只檢查輸入的型態。注意看 atoi 的回傳值,我們可能會分不清楚 0
來自使用者輸入,抑或是錯誤的表達式
了解了,謝謝老師提點! tina0405
--input
,將他的參數放進 register_0
--input
參數放置的--input
如同一開始就有一行組語是在初始化暫存器
void assemble_from_fd(vm_env *env, int fd, int input)
{
...
if (input != -1) {
char str[20]; /* INT_MAX = 2147483647 */
sprintf(str, "or #0 $%d #0", input);
assemble_line(env, str);
}
...
}
} else if (!strcmp(argv[i], "--input")) {
...
for (int k = 0; k < strlen(argv[i]); k++) {
if (argv[i][k] < 48 || argv[i][k] > 57) {
error_N = 1; /*error signal for assembly*/
break;
}
}
...
// A tail recursive function to
// calculate n th fibnacci number
int fib(int n, int a = 0, int b = 1)
{
if (n == 0)
return a;
if (n == 1)
return b;
return fib(n-1, b, a+b);
}
n a b
5 0 1
4 1 1
3 1 2
2 2 3
1 3 5
or $0 $0 #1 ;a = 0
or $1 $0 #2 ;b = 1
or $0 $0 #3 ;tmp = 0
call #8
print #3
halt
xor #0 $0 #3 ;compare with 0
jnz #3 #12
or #1 $0 #3
ret
xor #0 $1 #3 ;compare with 1
jnz #3 #16
or #2 $0 #3
ret
sub #0 $1 #0
or #1 $0 #3
or #2 $0 #1
add #2 #3 #2
call #8
ret
其實這個 Q-Matrix 就是利用矩症乘法的特性,又要乘的係數剛好都是 1 所以有累加的效果
矩陣的實作因為有 4 個元素,但是是 3 個值,用 3 個 rigister 表示
然後我們做矩陣的乘法,例子:
所以我們每次只做 4 件事,但至少要兩個暫存器來存被蓋掉之前的值
原本 4 行的運算式,用組語表示就必須一直考量暫存器是否會被蓋掉:
or $0 $0 #1 ;F0 = 0
or $1 $0 #2 ;F1 = 1
or $1 $0 #3 ;F2 = 1
or $0 $0 #4 ;tmp
or $0 $0 #6 ;tmp
or $0 $0 #7 ;tmp
or $0 $0 #8 ;tmp
xor #0 $0 #4
jnz #4 #13
print #1 ;input == 0 ,print result
halt
or #3 $0 #7 ;record F2
mul $1 #3 #4 ;1*F2
mul $1 #2 #6 ;1*F1
add #4 #6 #3 ;1*F2+1*F1=F2
or #2 $0 #8 ;record F1
mul $1 #2 #4 ;1*F1
mul $1 #1 #6 ;1*F0
add #4 #6 #2 ;1*F1+1*F0=F1
mul $1 #7 #4 ;1*F2
mul $0 #8 #6 ;0*F1
add #4 #6 #3 ;1*F2+0*F1=F1
mul $1 #8 #4 ;1*F1
mul $0 #1 #6 ;0*F0
add #4 #6 #1 ;1*F1+0*F0=F0
sub #0 $1 #0 ;input sub 1
jmp #9
參考了這篇證明 Fibonacci Fast Doubling Proof
我們可以利用以上證明寫出下列的算式 :
把奇數偶數分開處理
or $0 $0 #1 ;R_1 : initial the first number
or $0 $1 #2 ;R_2 : initial the second number
or $0 $0 #3 ;R_3 for temp
or $0 $0 #4 ;R_4 for n
or $0 $0 #6 ;F(n)
or $0 $0 #7 ;F(n+1)
or $0 $0 #8 ;R_8 for temp
mod #0 $2 #8
jnz #8 #13 ;if even
div #0 $2 #4 ;register_4 = n
jmp #24
sub #0 $1 #4 ;if odd
div #4 $2 #4 ;register_4 = n
jmp #24
jnz #4 #18 ;if 0,print 0
ret
or $0 #2 #3 ;temp = R_2
add #1 #2 #2 ;R_2 = R_1 + R_2
or $0 #3 #1 ;R_1 = temp
sub #4 $1 #4 ;input-1
jnz #4 #18 ;jump back until it become 0
ret
call #16
or #1 $0 #6 ;register_6 = F(n)
add #4 $1 #4 ;n-1
call #16
or #1 $0 #7 ;register_7 = F(n-1)
jnz #8 #36
mul $2 #6 #3 ;even
mul #3 #7 #3 ;2*F(n)*F(n+1)-F(n)*F(n)
mul #6 #6 #1
sub #3 #1 #3
print #3
halt
mul #6 #6 #3 ;odd
mul #7 #7 #1 ;F(n+1)*F(n+1)+F(n)*F(n)
add #3 #1 #3
print #3
halt