---
tags: Computer architecture 2022
---
# Assignment2: RISC-V Toolchain
contributed by < [`qwe661234`](https://github.com/qwe661234) >
## Problem description:
* This problem is based on [Leetcode 925. Long Pressed Name](https://leetcode.com/problems/long-pressed-name/) from [潘鴻福](https://hackmd.io/@kaminto-1999/long-pressed-name).
* Motivation: My homework 1 implement singly-linked list in rsic-v, but it did't cover the array in rsic-v. Therefore, I want to be familiar with the array in rsic-v by this homework.
## Long Pressed Name ([LeetCode 925](https://leetcode.com/problems/long-pressed-name/))
This is one of the "Easy" questions on LeetCode as requested in the assignment. The question is as follows.
Problem:
>Your friend is typing his **name** into a keyboard. Sometimes, when typing a character c, the key might get *long pressed*, and the character will be typed *1 or more times*.
>You examine the typed characters of the keyboard. Return **True** if it is possible that it was your friends name, with some characters (possibly none) being long pressed.
Example 1:
>Input: name = "alex", typed = "aaleex"
>Output: true
>Explanation: 'a' and 'e' in 'alex' were long pressed.
Example 2:
>Input: name = "saeed", typed = "ssaaedd"
>Output: false
>Explanation: 'e' must have been pressed twice, but it was not in the typed output.
## C code
```c
bool isLongPressedName(char *name, char *typed){
int i = 0, j = 0;
if (name[0] != typed[0]) return false;
while (i < strlen(name))
{
if(name[i] == typed[j]){
j++; i++;
}
else{
if(typed[j] == name[i-1])/* long typing */
j++;
else
return false;
}
}
while (j < strlen(typed))
{
if (typed[j++] != name[strlen(name)-1])
return false;
}
return true;
}
int main()
{
char name[] ="alex";
char typed0[]="aalexx";
char typed1[]="aalleexx";
char typed2[]="aalewx";
bool a;
if (isLongPressedName(name,typed0))
printf("PASS\n");
else
printf("FAIL\n");
if (isLongPressedName(name,typed1))
printf("PASS\n");
else
printf("FAIL\n");
if (isLongPressedName(name,typed2))
printf("PASS\n");
else
printf("FAIL\n");
}
```
## Rewrite assembly code (from [潘鴻福](https://hackmd.io/@kaminto-1999/long-pressed-name)) for using rv32emu
```c
.org 0
# Provide program starting address to linker
.global main
/* newlib system calls */
.set SYSEXIT, 93
.set SYSWRITE, 64
.data
addr_name: .string "alex"
addr_typed0: .string "aaleex"
addr_typed1: .string "aalleexx"
addr_typed2: .string "aalewx"
SuccessResult: .string "PASS\n"
.set success_result_size, .-SuccessResult
FailResult: .string "FAIL\n"
.set fail_result_size, .-FailResult
.text
main:
la t0, addr_name #Load "name" 1st address
la t1, addr_typed0 #Load "typed" 1st address
jal ra, isLongPressed #1st test-case
la t1, addr_typed1 #Load "typed" 1st address
jal ra, isLongPressed #2nd test-case
la t1, addr_typed2 #Load "typed" 1st address
jal ra, isLongPressed #3rd test-case
j End
isLongPressed:
addi sp, sp, -8 #Use 2 byte for saving register
sw ra, 0(sp) #1st byte is ra
sw t0, 4(sp) #2nd byte is t0
lb t2, 0(t0) #1st character of name
lb t3, 0(t1) #1st character of typed
bne t2, t3, Fail #1st character must the same
addi t0, t0, 1 #i++
addi t1, t1, 1 #j++
jal Loop #Call Loop
lw ra, 0(sp) #Recall ra
lw t0, 4(sp) #Recall t0
addi sp,sp, 8
ret
Loop: #1st while loop
lb t2, 0(t0) #Load name[i]
lb t3, 0(t1) #Load typed[j]
beq t2, x0, checkLastCharacter #If name[i]= NULL
If:
bne t2, t3, Else #If name[i]!=typed[j]
addi t0, t0, 1 #i++
addi t1, t1, 1 #j++
j Loop
Else:
lb t2, -1(t0) # Load name[i-1]
bne t2, t3,Fail # If typed[j] != name[i-1] then Fail
addi t1, t1, 1 # j++
j Loop
checkLastCharacter: #2nd while loop
lb t2, -1(t0) # Load last character of name
if2:
beq t3, x0, Pass # If typed[j] = NULL, then passed
bne t2, t3,Fail # If typed[j] != name[last] then Fail
addi t1, t1, 1 # j++
lb t3, 0(t1) # Load next character of typed
j if2
Pass:
li a7, SYSWRITE # "write" syscall
li a0, 1 # 1 = standard output (stdout)
la a1, SuccessResult # load address of hello string
li a2, success_result_size # length of hello string
ecall # invoke syscall to print the string
ret
Fail:
li a7, SYSWRITE # "write" syscall
li a0, 1 # 1 = standard output (stdout)
la a1, FailResult # load address of hello string
li a2, fail_result_size # length of hello string
ecall # invoke syscall to print the string
ret
End:
li a0, 0
li a7, SYSEXIT
ecall
```
### Result
```
$ make && ../../build/rv32emu longStr.elf
../../mk/toolchain.mk:25: GNU Toolchain for RISC-V is required. Please check package installation
riscv-none-elf-as -R -march=rv32i -mabi=ilp32 -o longStr.o longStr.S
riscv-none-elf-ld -o longStr.elf -T longStr.ld --oformat=elf32-littleriscv longStr.o
PASS
PASS
FAIL
inferior exit code 0
```
## Observe elf file
> $ riscv-none-elf-objdump -d longStr.elf
```
longStr.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <main>:
0: 00000297 auipc t0,0x0
4: 0ec28293 addi t0,t0,236 # ec <addr_name>
8: 00000317 auipc t1,0x0
c: 0e930313 addi t1,t1,233 # f1 <addr_typed0>
10: 020000ef jal ra,30 <isLongPressed>
14: 00000317 auipc t1,0x0
18: 0e430313 addi t1,t1,228 # f8 <addr_typed1>
1c: 014000ef jal ra,30 <isLongPressed>
20: 00000317 auipc t1,0x0
24: 0e130313 addi t1,t1,225 # 101 <addr_typed2>
28: 008000ef jal ra,30 <isLongPressed>
2c: 0b40006f j e0 <End>
00000030 <isLongPressed>:
30: ff810113 addi sp,sp,-8
34: 00112023 sw ra,0(sp)
38: 00512223 sw t0,4(sp)
3c: 00028383 lb t2,0(t0)
40: 00030e03 lb t3,0(t1)
44: 09c39063 bne t2,t3,c4 <Fail>
48: 00128293 addi t0,t0,1
4c: 00130313 addi t1,t1,1
50: 014000ef jal ra,64 <Loop>
54: 00012083 lw ra,0(sp)
58: 00412283 lw t0,4(sp)
5c: 00810113 addi sp,sp,8
60: 00008067 ret
00000064 <Loop>:
64: 00028383 lb t2,0(t0)
68: 00030e03 lb t3,0(t1)
6c: 02038263 beqz t2,90 <checkLastCharacter>
00000070 <If>:
70: 01c39863 bne t2,t3,80 <Else>
74: 00128293 addi t0,t0,1
78: 00130313 addi t1,t1,1
7c: fe9ff06f j 64 <Loop>
00000080 <Else>:
80: fff28383 lb t2,-1(t0)
84: 05c39063 bne t2,t3,c4 <Fail>
88: 00130313 addi t1,t1,1
8c: fd9ff06f j 64 <Loop>
00000090 <checkLastCharacter>:
90: fff28383 lb t2,-1(t0)
00000094 <if2>:
94: 000e0a63 beqz t3,a8 <Pass>
98: 03c39663 bne t2,t3,c4 <Fail>
9c: 00130313 addi t1,t1,1
a0: 00030e03 lb t3,0(t1)
a4: ff1ff06f j 94 <if2>
000000a8 <Pass>:
a8: 04000893 li a7,64
ac: 00100513 li a0,1
b0: 00000597 auipc a1,0x0
b4: 05858593 addi a1,a1,88 # 108 <SuccessResult>
b8: 00600613 li a2,6
bc: 00000073 ecall
c0: 00008067 ret
000000c4 <Fail>:
c4: 04000893 li a7,64
c8: 00100513 li a0,1
cc: 00000597 auipc a1,0x0
d0: 04258593 addi a1,a1,66 # 10e <FailResult>
d4: 00600613 li a2,6
d8: 00000073 ecall
dc: 00008067 ret
000000e0 <End>:
e0: 00000513 li a0,0
e4: 05d00893 li a7,93
e8: 00000073 ecall
000000ec <addr_name>:
ec: 78656c61 .word 0x78656c61
...
000000f1 <addr_typed0>:
f1: 656c6161 .word 0x656c6161
f5: Address 0x00000000000000f5 is out of bounds.
000000f8 <addr_typed1>:
f8: 6c6c6161 .word 0x6c6c6161
fc: 78786565 .word 0x78786565
...
00000101 <addr_typed2>:
101: 656c6161 .word 0x656c6161
105: Address 0x0000000000000105 is out of bounds.
00000108 <SuccessResult>:
108: 53534150 .word 0x53534150
10c: Address 0x000000000000010c is out of bounds.
0000010e <FailResult>:
10e: 4c494146 .word 0x4c494146
112: 000a .short 0x000a
```
- Observation
- Register Used: 6
- sx register: None
- tx register: None
- ax register: a0 a1 a2 a3 a4 a5
- other: None
- Stack used(bytes): None
- lw/sw count: 1