--- tags: CA2020 --- # Assignment2: RISC-V Toolchain-2 contributed by < `kevin30292` > ## GCD The following assembly program was implemented by `洪邵澤`. ```cpp .data num1: .word 120 # number 1 (u) num2: .word 78 # number 2 (v) str1: .string "\n" nums: .word 30 10 .text main: lw s0, num1 # u lw s1, num2 # v # check u or v is 0 beqz s1, print beqz s0, assign # use Euclidean algorithm loop: mv s2, s1 rem s1, s0, s1 mv s0, s2 bnez s1, loop j print assign: mv s0, s1 j print print: addi a7, x0, 1 # print_int ecall add a0, s0, x0 # integer ecall exit: ``` ## Rewrite into C implementation `gcd.c` ```c= #include <stdio.h> int _start() { int s0 = 120; int s1 = 78; if(s1 == 0){ ; } else if(s0 == 0){ s0 = s1; } else { while(s1) { int s2 = s1; s1 = s0 % s1; s0 = s2; } } volatile char *tx = (volatile char *)0x40002000; *tx = s0; } ``` ![](https://i.imgur.com/10Kvxvq.png) ```c= #include <stdio.h> int mod(int a, int b) { int r = a; while(r >= b) { r = r - b; } return r; } int _start() { int s0 = 120; int s1 = 78; if(s1 == 0){ ; } else if(s0 == 0){ s0 = s1; } else { int s2; while(s1) { s2 = s1; s1 = mod(s0, s1); s0 = s2; } } volatile char *tx = (volatile char *)0x40002000; *tx = (char)(s0 + '0'); return 0; } ``` ## Execute with `rv32emu` ``` $ riscv-none-embed-gcc -march=rv32i -mabi=ilp32 -O3 -nostdlib -o gcd gcd.c ``` ![](https://i.imgur.com/oYNhQgG.png) ## ELF files generated by C compiler ![](https://i.imgur.com/Y8xZs85.png) #### Compare the assembly 1. The ELF files generated by C compiler didn't branch back to mod. ->It merge the mod function in to _start 2. It's use stack to store the array temporary. ->It doesn't need to access memory so many times. ![](https://i.imgur.com/6W4ZrfI.jpg)