Reputation: 21
I'm trying to write a program that reads in a string and calculates the length of it to be used later on in the program. This is what I have so far.
ldr x0, =stringread
ldr x1, =strbuffer //string to be analyzed
bl scanf
mov x9, #0 //initialize length = 0
bl Loop
Loop:
ldrb w11, [x1, x9] //load w11 with the x9th value of the string in x1
cbnz w11, increment_length //until a 0 appears, continue iterating
//thru string while incrementing length
/* what to put here to break the loop once zero is reached?*/
increment_length:
add x9, x9, #0
bl Loop
I'm not sure exactly how to break this loop. Would I branch to another branch that simply serves to break the loop? As in a branch labeled zero_reached
? I'm currently getting a segmentation fault. Any tips or pointers would be much appreciated.
(For reference, this is my entire program. It is not completed yet, and I just need to get past calculating the length to continue to the other parts).
.data
outformat: .asciz "%c"
flush: .asciz "\n"
stringread: .asciz "%s"
lengthread: .asciz "%d"
strbuffer: .space 100
lenbuffer: .space 8
.text
.global main
main:
ldr x0, =prompt
mov x1, x0
bl printf
ldr x0, =stringread
ldr x1, =strbuffer
bl scanf
mov x9, #0 //length
bl Loop
Loop:
ldrb w11, [x1, x9]
cmp w11, #0
bne increment_length
add x9, x9, #1
increment_length:
add x9, x9, #0
bl Loop
#Change length to length-1
sub x0, x0, #1
#Move string address to x1
ldr x1, =strbuffer
#Starting index for reverse
mov x2, #0
#Branch to reverse, setting return address
bl reverse
#Flush the stdout buffer
ldr x0, =flush
bl printf
#Exit the program
b exit
reverse: #In reverse we want to maintain
#x0 is length-1
#x1 is memory location where string is
#x2 is index
subs x3, x2, x0
#If we haven't reached the last index, recurse
b.lt recurse
base: #We've reached the end of the string. Print!
ldr x0, =outformat
#We need to keep x1 around because that's the string address!
#Also bl will overwrite return address, so store that too
stp x30, x1, [sp, #-16]!
ldrb w1, [x1, x2]
bl printf
ldp x30, x1, [sp], #16
#Go back and start executing at the return
#address that we stored
br x30
recurse: #First we store the frame pointer(x29) and
#link register(x30)
sub sp, sp, #16
str x29, [sp, #0]
str x30, [sp, #8]
#Move our frame pointer
add x29, sp, #8
#Make room for the index on the stack
sub sp, sp, #16
#Store it with respect to the frame pointer
str x2, [x29, #-16]
add x2, x2, #1
#Branch and link to original function.
bl reverse
#Back from other recursion, so load in our index
end_rec:
ldr x2, [x29, #-16]
#Print the char!
stp x30, x1, [sp, #-16]!
ldr x0, =outformat
ldrb w1, [x1, x2]
bl printf
ldp x30, x1, [sp], #16
#Clear off stack space used to hold index
add sp, sp, #16
#Load in fp and lr
ldr x29, [sp, #0]
ldr x30, [sp, #8]
#Clear off the stack space used to hold fp and lr
add sp, sp, #16
#Return to correct location in execution
br x30
exit:
mov x0, #0
mov x8, #93
svc #0
.section .data
prompt:
.asciz "input a string\n"
Upvotes: 1
Views: 839
Reputation: 2599
I'm not sure what assembler you're using, but I can say that you're not always using BL
correctly. BL
is 'branch with link', which is effectively a 'call' instruction and overwrites the link register with the required return address before branching. Sometimes you're using this correctly (BL printf
) and sometimes not (BL Loop
, when what you mean is simply B Loop
).
Note also that the first branch to the 'Loop' label is unnecessary because it's simply branching to the next instruction, and that you're not actually incrementing your length counter (you're adding 0 to it!).
My suggestion for your loop snippet would be as follows:
ldr x0, =stringread
ldr x1, =strbuffer // String to be analyzed
bl scanf
mov x9, #0 // Initialize length = 0
Loop:
ldrb w11, [x1, x9] // Load w11 with the x9th value of the string in x1
cbz w11, LoopEnd // Until a 0 appears, continue iterating
add x9, x9, #1 // Increment x9
b Loop
LoopEnd: // Continue from here
Note how the loop branch is unconditional, and a conditional branch is used near the beginning of the loop to escape it. This is approximately what a C compiler would generate if presented with code like
char * buffer = strbuffer;
int index = 0;
while (buffer[index] != 0) {
++index;
}
The condition at the top of the while
loop is evaluated at the start of each loop, and causes a branch to the end of the loop if it is not satisfied, just like in the assembly language code above.
Upvotes: 2