Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# lab-1
Here are three different version...

1. [recursion](lab-1/): Use `make` command to check the answer
2. [iteration](lab-1i/): Use `make` command to check the answer
3. [c-code](lab-1-c/): Translate arm code to c, and use `gprof` to analyze. You can use `make` to run the `gprof` script, the results will show in `analysis.txt`. After arranging the data, you can see the example in [result.txt](lab-1-c/result.txt). Finally, I use the [script](lab-1-c/gplot_cmd.txt) and the [result](lab-1-c/efficiency.png) shows as following...
```sh
gnuplot
> plot "analysis-result.txt"
> set style data lines # connect each dots
> set grid # set background as grid
> set title "fib efficiency" # add title
> replot
> plot "analysis-result.txt" using 1:2 title 'Recursion', \
"analysis-result.txt" using 1:3 title 'Tail-Recursion', \
"analysis-result.txt" using 1:4 title 'Iteration' # plot three data at the same time
> set logscale y; replot # data in y-axis is large, use logscale
> set output "efficiency.png" ; set term png ; replot
```
![picture alt](lab-1-c/efficiency.png)
19 changes: 19 additions & 0 deletions lab-1-c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

default: fib

fib: fib.o
gcc -Wall -pg fib.c -o fib

fib.o: fib.c

qemu: fib
@num=1 ; while [ $$num -le 10 ] ; do \
echo "go to $$num" ; \
echo "\ngo to $$num \n" >> analysis.txt ; \
./fib $$num ; \
gprof fib gmon.out -p -b >> analysis.txt ; \
num=`expr $$num + 1` ; \
done

clean:
rm fib fib.o gmon.out analysis.txt
Binary file added lab-1-c/efficiency.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions lab-1-c/fib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stdio.h>
#define TIMES 1000000

int recursive(int n){ return n<3 ? 1 : recursive(n-1)+recursive(n-2); }

int tail_rec(int n,int a,int b){ return n==0 ? b : tail_rec(n-1,a+b,a); }

int iterative(int n){
int i1=0, i2=1, res;
for(;n;--n){ res=i2; i2+=i1; i1=res; }
return res;
}

int main(int argc, char* argv[]){
int n=atoi(argv[1]),i;
for(i=0;i<TIMES;++i){
recursive(n);
tail_rec(n,1,0);
iterative(n);
}
}

8 changes: 8 additions & 0 deletions lab-1-c/fib_iterative.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <stdio.h>

int main(void){
int i1=0, i2=1, n, res;
scanf("%d",&n);
for(;n;--n){ res=i2; i2+=i1; i1=res; }
printf("%d\n",res);
}
9 changes: 9 additions & 0 deletions lab-1-c/fib_recursive.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdio.h>

int fib(int n){ return n<3 ? 1 : fib(n-1)+fib(n-2); }

int main(void){
int n;
scanf("%d",&n);
printf("%d\n",fib(n));
}
12 changes: 12 additions & 0 deletions lab-1-c/fib_tail_recursive.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdio.h>
#define times 10000000

int fib(int n,int a,int b){ return n==0 ? b : fib(n-1,a+b,a); }

int main(void){
int n,i;
scanf("%d",&n);
for(i=0;i<times;++i) fib(n,1,0);
// printf("%d\n",fib(n,1,0));
}

11 changes: 11 additions & 0 deletions lab-1-c/gplot_cmd.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
gnuplot
> plot "analysis-result.txt"
> set style data lines # 設定成連線模式
> set grid # 模擬方格紙效果
> set title "fib efficiency" # 加上標題。
> replot # 重畫一遍
> plot "analysis-result.txt" using 1:2 title 'Recursion', \
"analysis-result.txt" using 1:3 title 'Tail-Recursion', \
"analysis-result.txt" using 1:4 title 'Iteration' # 同時畫三圖
> set logscale y; replot # y軸差異太大, 用 logscale
> set output "efficiency.png" ; set term png ; replot
46 changes: 46 additions & 0 deletions lab-1-c/result.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
1 1.52 3.03 2.02
2 3.03 1.01 6.06
3 7.58 13.13 5.05
4 9.09 9.09 5.05
5 29.80 20.20 7.07
6 50.52 16.16 6.06
7 30.31 21.21 10.10
8 95.98 22.22 28.28
9 121.24 25.25 15.15
10 298.04 29.29 44.44
11 272.78 40.40 35.35
12 722.37 30.30 26.26
13 914.33 43.43 31.31
14 1400 43.43 40.40
15 2550 52.53 46.46
16 3030 49.49 35.35
17 10100 56.57 58.59
18 9090 63.64 65.66
19 15150 68.69 49.49
20 23740 64.65 67.68
21 48490 98.99 62.63
22 60110 72.73 78.79
23 111640 78.79 66.67
24 183880 87.88 77.78
25 293490 85.86 84.85
26 606190 90.91 79.80
27 1210000 97.98 81.82
28 1520000 96.97 90.91
29 2170000 124.24 84.85
30 3740000 130.30 74.75
31 5250000 121.21 78.79
32 9500000 104.04 90.91
33 13490000 146.46 94.95
34 22530000 111.11 118.18
35 46520000 119.19 109.09
36 65670000 120.20 98.99
37 70720000 151.52 101.01
38 141440000 129.29 123.23
39 227320000 153.54 117.17
40 434430000 132.32 135.35
41 676910000 161.62 122.22
42 1120000000 137.37 143.43
43 1720000000 200.00 130.30
44 3120000000 155.56 115.15
45 4600000000 157.58 128.28
45 8660000000 159.60 145.45
35 changes: 1 addition & 34 deletions lab-1/Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1 @@
CC = arm-linux-gnueabihf-gcc
CFLAGS = -O1 -Wall
LDFLAGS = -fno-stack-protector

objects = fibseq.o fib.o

default: fibseq

.PHONY: default clean qemu

fibseq: $(objects)
$(CC) $(LDFLAGS) -o $@ $^

fib.o: fib.s
fibseq.o: fibseq.c

%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<

%.o: %.s
$(CC) -c $(CFLAGS) -o $@ $<

clean:
rm -f $(objects) fibseq

QEMU_CMD = qemu-arm -L /usr/arm-linux-gnueabihf ./fibseq &
CMD = yes 9 | $(call QEMU_CMD) && sleep 1
qemu: fibseq
@yes 5 | $(call QEMU_CMD)
@sleep 1
@yes 6 | $(call QEMU_CMD)
@sleep 1
@yes 7 | $(call QEMU_CMD)
@sleep 1
include ../make_fib.mk
30 changes: 11 additions & 19 deletions lab-1/fib.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,25 @@
fibonacci:
@ ADD/MODIFY CODE BELOW
@ PROLOG
push {r3, r4, r5, lr}
push {r4, r5, lr}

@ R4 = R0 - 0 (update flags)
@ if(R0 <= 0) goto .L3 (which returns 0)
subs r4, r0, #0 @ R4 = R0 - 0 (update flags)
beq .L4 @ If R4 == 0 goto .L4 (which returns second)

@ Compare R4 wtih 1
@ If R4 == 1 goto .L4 (which returns 1)
sub r5, r1, #0 @ R5 = first

@ R0 = R4 - 1
@ Recursive call to fibonacci with R4 - 1 as parameter
sub r0, r4, #1 @ R0 = R4 - 1
add r1, r5, r2 @ R1 = first+second
mov r2, r5 @ R2 = first
bl fibonacci @ Recursive call to fibonacci

@ R5 = R0
@ R0 = R4 - 2
@ Recursive call to fibonacci with R4 - 2 as parameter

@ R0 = R5 + R0 (update flags)

pop {r3, r4, r5, pc} @EPILOG
pop {r4, r5, pc} @EPILOG

@ END CODE MODIFICATION
.L3:
mov r0, #0 @ R0 = 0
pop {r3, r4, r5, pc} @ EPILOG

.L4:
mov r0, #1 @ R0 = 1
pop {r3, r4, r5, pc} @ EPILOG
sub r0, r2, #0 @ R0 = second
pop {r4, r5, pc} @ EPILOG

.size fibonacci, .-fibonacci
.end
11 changes: 9 additions & 2 deletions lab-1/fibseq.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
/* * The fibonacci function call here,
* there are three arguments: fibonacci(int x, int y, int z)
* x: request for the xth Fibonacci number
* y: the last Fibonacci number we've known (fib 1 = 1)
* z: the second last Fibonacci number (fib0 = 0)
*/

#include <stdio.h>

extern int fibonacci(int x);
extern int fibonacci(int x, int y, int z);

int main(int argc, char **argv)
{
int number=0;
int result=0;

scanf("%d",&number);
result = fibonacci(number);
result = fibonacci(number,1,0);
printf("The fibonacci sequence at %d is: %d\n", number, result);
}

35 changes: 1 addition & 34 deletions lab-1i/Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1 @@
CC = arm-linux-gnueabihf-gcc
CFLAGS = -O1 -Wall
LDFLAGS = -fno-stack-protector

objects = fibseq.o fib.o

default: fibseq

.PHONY: default clean qemu

fibseq: $(objects)
$(CC) $(LDFLAGS) -o $@ $^

fib.o: fib.s
fibseq.o: fibseq.c

%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<

%.o: %.s
$(CC) -c $(CFLAGS) -o $@ $<

clean:
rm -f $(objects) fibseq

QEMU_CMD = qemu-arm -L /usr/arm-linux-gnueabihf ./fibseq &
CMD = yes 9 | $(call QEMU_CMD) && sleep 1
qemu: fibseq
@yes 5 | $(call QEMU_CMD)
@sleep 1
@yes 6 | $(call QEMU_CMD)
@sleep 1
@yes 7 | $(call QEMU_CMD)
@sleep 1
include ../make_fib.mk
33 changes: 11 additions & 22 deletions lab-1i/fib.s
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,22 @@
fibonacci:
@ ADD/MODIFY CODE BELOW
@ PROLOG
push {r3, r4, r5, lr}
push {r4, r5, r6, lr}

@ R4 = R0 - 0 (update flags)
@ if(R0 <= 0) goto .L3 (which returns 0)
sub r4, r0, #0 @ R4 = R0 - 0 (update flags)

@ Compare R4 wtih 1
@ If R4 == 1 goto .L4 (which returns 1)
mov r5, #0 @ init fib(0) = 0
mov r6, #1 @ init fib(1) = 1
.Loop:
mov r0, r6 @ R0 = R6 and also the result
add r6, r5, r6 @ R6 += R5
mov r5, r0 @ R5 = R0 (exchange R5, R6)
subs r4, r4, #1 @ R4 = R4 - 1
bne .Loop

@ R0 = R4 - 1
@ Recursive call to fibonacci with R4 - 1 as parameter

@ R5 = R0
@ R0 = R4 - 2
@ Recursive call to fibonacci with R4 - 2 as parameter

@ R0 = R5 + R0 (update flags)

pop {r3, r4, r5, pc} @EPILOG
pop {r4, r5, r6, pc} @EPILOG

@ END CODE MODIFICATION
.L3:
mov r0, #0 @ R0 = 0
pop {r3, r4, r5, pc} @ EPILOG

.L4:
mov r0, #1 @ R0 = 1
pop {r3, r4, r5, pc} @ EPILOG

.size fibonacci, .-fibonacci
.end
48 changes: 48 additions & 0 deletions make_fib.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
CC = arm-linux-gnueabihf-gcc
CFLAGS = -O1 -Wall
LDFLAGS = -fno-stack-protector

objects = fibseq.o fib.o

default: fibseq

.PHONY: default clean qemu

fibseq: $(objects)
$(CC) $(LDFLAGS) -o $@ $^

fib.o: fib.s
fibseq.o: fibseq.c

%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<

%.o: %.s
$(CC) -c $(CFLAGS) -o $@ $<

clean:
rm -f $(objects) fibseq

QEMU_CMD = qemu-arm -L /usr/arm-linux-gnueabihf ./fibseq &
CMD = yes 9 | $(call QEMU_CMD) && sleep 1
qemu: fibseq
@num=1 ; i1=0 ; i2=1 ; \
while [ $$num -le 50 ] ; do \
# save output answer \
ans=`yes $$num | $(call QEMU_CMD)` ; \
sleep 0.5 ; \
# echo output \
echo $$ans ; \
# split output string && save answer \
ans=`echo $$ans | cut -d ' ' -f 7` ; \
# calculate the correct answer \
i3=$$i2 ; i2=`expr $$i1 + $$i2` ; i1=$$i3 ; \
# check if it is right \
if [ "$$i1" -eq "$$ans" ] ; then \
echo " -> correct" ; \
else \
echo " -> wrong, the ans is $$i1" ; \
fi ; \
num=`expr $$num + 1` ; \
done