int a[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++)
{
if( a[i] > 5)
//do something
I would like to translate the above C code to Risc-V assembly. This is what I have so far, but I am having some confusion regarding the initialization, storage, and accessing of the array:
#create stack
addi sp, sp, -40
#save s0
sw s0, 40(sp)
#update s0
addi s0, sp, 40
li x18, 1
sw x18, -40(s0)
li x18, 2
sw x18, -36(s0)
li x18, 3
sw x18, -32(s0)
li x18, 4
sw x18, -28(s0)
li x18, 5
sw x18, -24(s0)
li x18, 6
sw x18, -20(s0)
li x18, 7
sw x18, -16(s0)
li x18, 8
sw x18, -12(s0)
li x18, 9
sw x18, -8(s0)
li x18, 10
sw x18, -4(s0)
addi x5, x0, x0 //x5 = i = 0
addi x31, x0, 10 //x31 = 10
Func:
//do something
Loop:
lw x10, 0(s0) //x10 = a[i]
bgt x10, 5, Func //if(a[i] > 5)
addi s0, s0, 4 //&a[i++]
addi x5, x5, 1 //i = i + 1
blt x5 x31, Loop //if condition (i < 10)
Is this approach correct?
if
statement is not quite right. The code is incomplete, so it is hard to tell where you're going with that. But, given that you're branching backwards to before the loop, you would have to put some extra branching in here and there. Let's note that in the C code, the if
statement is nested inside the loop, and, normally we would do the same in assembly instead of placing the then
part of the if
statement before and in front of the loop. The intent of the C if
statement is that the then
part is conditionally executed, and then when the if
statement is finished, control passes to the next sequential statement after the if
(here that is remainder of the loop) whether or not the if
statement runs/fires the then
part. If you resume control somewhere else (or only on one of condition instead of on both conditions — when the if condition is true vs. when false) your assembly code won't run like the C code.
Loop:
lw a0, 0(s0)
ble a0, 5, if1IsDone // if a[i] <= 5 then skip the "do something"
// do something -- this is the "then" part, only runs when a[i] > 5
if1IsDone: // when the If is done control goes on to the rest of the loop
// whether the then-part executed or was skipped
addi s0, s0, 4
addi t0, t0, 1
blt t0, 10, Loop
In the above, the if
statement is fully nested within the loop, just like it is in the C code.
You're saving s0
at the top of the stack, which you don't own as it belongs to the caller. Put another way, you're allocating 40 bytes of stack space, for your local array, but you need 44 bytes of stack space for the array + the saved s0
.
You're creating a base pointer ( s0
) equal to the original stack pointer and then accessing the array using negative addressing. This is both confusing and unnecessary. We can access the array from sp
itself, as that is just another register. So, a[0]
is at sp+0 and a[1]
is at sp+4. Forwards using positive addressing.
Since you set up s0
to point to the end of the array, your pointer dereferencing inside the loop will not access the elements as you intend in the C code. Instead it will access the stack memory of the caller. Change to point to the beginning of the array instead, then advancing the pointer by 4 will access successive elements as you intended. (You could bias the dereference by the size of the array as a negative offset, but that would be silly compared to simply pointing to the start of the array in the first place.)
However, finish your C code before writing the assembly code. A small change in the C code can result in major changes to the assembly code. For example, if you have a function call inside the loop, you'd want to change the registers for values that are live across a call, probably have to save an additional registers to the stack, which could move your array and change offsets.
Write your assembly code true to your C code. Don't make algorithmic optimizations during translation of C to assembly.
do.. while
loop instead of a for
loop then write the C code that way before taking it to assembly. As Peter says, don't mix friendly (ABI: t0,s0,sp,a0, etc..) register names with unfriendly ones (x10,x18,..) — that's super confusing. Use only friendly ABI register names. Don't use s
registers unless you need them (here you don't yet).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.