ARM printing elements of an Array leads to Seg Fault - arrays

I am trying to print all the elements of an array using the write() system call. I haven't used write a whole lot before but from what I understand, the parameters I am passing to write seem to be correct. I know that write takes:
The file descriptor of the file (1 means standard output).
The buffer from where data is to be written into the file.
The number of bytes to be read from the buffer.
Here is my code:
mov r3, #0 /*Offset (also acts as LVC)*/
print: mov r0, #1 /*Indicates standard output*/
ldr r4, =array /*Set r4 to the address of array*/
ldr r5, [r3,r4] /*Add offset to array address*/
ldr r1, [r6] /*Element of array to write*/
mov r2, #1 /*Write 1 byte*/
bl write
add r3, r3, #1 /*Increase offset each iteration*/
cmp r3, #41
blt print
Does this look correct? Is it likely that my problem is elsewhere in my program?

No. You want to pass the address where the data to write are in r1, not the value itself.
Therefore r1 should be set to just <address-of-array> + <index>, i.e.:
ldr r4, =array /*Set r4 to the address of array*/
add r1, r3, r4 /*Add offset to point to array item */
It crashed for you, because you tried to read from memory at an invalid address -- the value of the array item. You were reading a word (ldr r5, [r3,r4]), not byte, from the array at index r3, then trying to read another word (not byte) from that address.
It is not relevant in this case, but just for reference, you would use lrdb to read a single byte.
Also the "invalid address" above might be both that it is undefined and falls outside of any mapped region, but also that it is improperly aligned. The ARM architecture disallows reading a word, e.g. a 32 bit value, from address not aligned at those 32-bits (4 bytes). For r3 == 1 in the second iteration, this wouldn't apply (assuming array would start on a 32-bit boundary).

Related

Converting a code a* b * c written in C to LC3

I don't know if this question is vague or lacks enough information but I was just wondering If I want to convert this line a = a * b * c written in C language to LC-3, how can I do it? Assuming that a, b and c are local variables and that the offset of a is 0, b is -1, c is -2?
I know that I can start off like this:
LDR R0, R5, #0; to load A
LDR R1, R5, #-1; to load B
Is there a limitation to the registers I can use? Can I use R2 to load C?
Edit:
LDR R0, R5, #0; LOAD A
LDR R1, R5, #-1; LOAD B
LDR R2, R5, #-2; LOAD C
AND R3, R3, #0; Sum = 0
LOOP ADD R3, R3, R1; Sum = sum + B
ADD R0, R0, #-1; A = A-1
STR R0, R5, #0; SAVE TO A (a = a*b)
BRp LOOP
ADD R4, R4, R2; Sum1 = sum1 + C
ADD R2, R2, #-1; C = C-1
BRp LOOP
STR R0, R5, #0; SAVE TO A (a = a*c = a*b*c)
If you're writing a whole program, which is often the case with LC-3, the only physical limit is the instruction set, so modulo that, you can use the registers as you like.
Your coursework/assignment may impose some environmental requirements, such as local variables and parameters being accessible from a frame pointer, e.g. R5, and having the stack pointer in R6.  If so, then those should probably be left alone, but in a pinch you could save them, and later restore them.
If you're writing just a function that is going to be called, then you'll need to follow the calling convention.  Decode the signature of the function you're implementing according to the parameter passing approach.  If you want to use R7 (e.g. as a scratch register, or if you want to call another function) be aware that on entry to your function, it holds the return address, whose value is needed to return to the caller, but you can save it on the stack or in a global storage for later retrieval.
The calling convention in use should also inform which registers are call clobbered vs. call preserved.  Within a function, call-clobbered registers can be used without fuss, but call-preserved registers require being saving before use, and later restored to original values before returning to the function's caller.

Does multidimentional array indices calls a function to calculate the element adress in c?

Assume I am working on ARM Cortex M7. Now take a look at:
int a[4][4];
a[i][j]=5;
Is in assembly language a function will be calculating the a[j][j] address or it uses lookuptable (pointer array with the same size) or some magical way to place 5 in correct place?
This is disassembler output:
136 array1[i][i+1]=i;
08000da6: ldr r3, [r7, #36] ; 0x24
08000da8: adds r3, #1
08000daa: ldr r2, [r7, #36] ; 0x24
08000dac: uxtb r1, r2
08000dae: ldr r2, [r7, #36] ; 0x24
08000db0: lsls r2, r2, #2
08000db2: add.w r0, r7, #40 ; 0x28
08000db6: add r2, r0
08000db8: add r3, r2
08000dba: subs r3, #36 ; 0x24
08000dbc: mov r2, r1
08000dbe: strb r2, [r3, #0]
If you write the indices as in your example, the compiler will calculate the exact memory address required at compile time.
If the indices were variables, then address would be calculated at run time.
Here is a comparison of assembly output for both cases.
Without considering optimization, the standard way a compiler implements a reference to an array element, say x[k]:
Start with the memory address of x.
Multiply the number of bytes in an element of x by k.
Add that to the memory address of x.
Let’s suppose int has four bytes.
With a[i][j] of int a[4][4], there are two memory references, so the address is calculated:
Start with the memory address of a.
The elements of a are arrays of 4 int, so the size of an element of a is 4 times 4 bytes, which is 16 bytes.
Multiply 16 bytes by i.
Add that to the address of a. Now we have calculated the address of a[i].
We use the address of a[i] to start a new calculation.
a[i] is an array of int, so the size of an element of a[i] is 4 bytes.
Multiply 4 bytes by j.
Add that to the address of a[i]. This gives the address of a[i][j].
Summarizing, if s is the start address of a, and we use units of bytes, then the address of a[i][j] is s + 16•i + 4•j.

Reversing String in ARM GAS Assembler returns NULL

I know I'm doing something stupid, but I can't figure out what. The functions return a null string, so I'm not copying each character. Entry into my reverse_string_func has the input string in R0. The example I have used a syntax which gas doesn't seem to support, so I modified it, but it isn't functional. I want to move along the array of char one at a time. Any assistance is greatly appreciated, I've stared at it so many times I'm going code blind.
EDIT:
The input string is in R0 when it is passed to the function. The reverse_string is an empty buffer filled with 0's. What I'm attempting to do is load the location of the input string into R1, move through it (while loading into r3) until I find the terminating 0, then move to the copy loop. There I want to load the current location of R3 (end of the string) into the first position of R2 (the reverse string) then go backwards pulling the characters from R3 and putting them back into R2 in the reverse order. I assumed I was using R2 and not ignoring it?
ldr r2, [r0], r3 /* start at end of string */
add r3, #-1
I believe I'm pushing the value numbered R3 in the array held in R0 into R2? Is that not what is happening?
reverse_string_func:
PUSH {ip, lr}
LDR r1, =input_string # pointer to first string.
LDR r2, =reverse_string # pointer to second string
mov r3, #0
mv2end: /* try to find the end of the string */
ldr r1, [r1], #1
add r3, #1
cmp r1, #0
bne mv2end
/* found end of string, move on */
string_copy:
ldr r2, [r0], r3 /* start at end of string */
add r3, #-1
cmp r3, #0
bne string_copy /* move back for next character */
POP {ip, pc}
EDIT2:
OK, so I've made changes to attempt to str the values I'm finding. I have single-stepped through everything and it all seems to be in the registers, but it isn't being stored into the character buffer in memory? I still don't understand what I'm doing wrong.
reverse_string_func:
PUSH {ip, lr}
LDR r1, =input_string # pointer to first string.
LDR r4, =reverse_string # pointer to second string
mov r3, #0
mv2end: /* try to find the end of the string */
ldrb r2, [r1, r3]
add r3, #1
cmp r2, #0
bne mv2end
/* found end of string, move on */
add r3, #-2 /* on terminator, move back past terminator, and line feed */
string_copy:
add r3, #-1
ldrb r2, [r1, r3]
strb r4, [r1, r3] # <--- I believe I'm going wrong here, but how?
cmp r3, #0
bne string_copy /* move back for next character */
POP {ip, pc}
As it stands this just returns a NULL string into the main program.
The problem I was having with the second edit was with the STRB mnemonic and the problem was I that was misunderstanding the direction of storing. The correct way is:
strb r2, [r4, r5]
Because you're storing the contents of register R2 into the memory location held in R4, by the offset R5.
Hopefully this might help someone else who comes here later. There is a good tutorial here: https://azeria-labs.com/memory-instructions-load-and-store-part-4/
You load current character into r2 register (and then ignore it), while it appears what you wanted is to store that character into string pointed to by r2.

Why doesn't the stack pointer decrease when I am using a 64 bit local variable?

Here is the disassembly code which compiled from C:
00799d60 <sub_799d60>:
799d60: b573 push {r0, r1, r4, r5, r6, lr}
799d62: 0004 movs r4, r0
799d64: f000 e854 blx 799e10 <jmp_sub_100C54>
799d68: 4b15 ldr r3, [pc, #84] ; (799dc0 <sub_799d60+0x60>)
799d6a: 0005 movs r5, r0
799d6c: 4668 mov r0, sp
799d6e: 4798 blx r3
The target of the subroutine call (799d6e: 4798 blx r3) takes a 64 bit integer pointer argument and returns a 64 bit integer. And that routine is a library function, so I am not able to make any modifications on it.
Could this operation overwrite the stack which storages the lr and r6's value?
You say that the branch target "takes a 64 bit integer pointer argument and returns a 64 bit integer", but this is not the case. It takes a pointer to a 64-bit integer as its only argument (and this pointer is 32 bits long unless you're on aarch64, which I doubt given the rest of the code); and it returns nothing, it simply overwrites the 64-bit value pointed to by the argument you passed in. I'm sure this is what you meant, but be careful with your use of terminology, because the difference between these things is important! In particular there is no 64-bit argument passed either into our out of the function you're calling.
On to the question itself. The key to understanding what the compiler is doing here is to look at the very first line:
push {r0, r1, r4, r5, r6, lr}
The ARM calling convention doesn't require r0 and r1 to be call-preserved, so what are they doing in the list? The answer is that the compiler has added these 'dummy' pushes to create some space on the stack. The push operation above is essentially equivalent to
push {r4, r5, r6, lr}
sub sp, sp, #0x08
except that it saves an instruction. The result is not quite the same, of course, because whatever was in r0 and r1 ends up being written to these locations; but given that there's no way to know what was there beforehand, and the stacked values are about to get overwritten anyway, it's of no consequence. So we have, as a stack frame,
lr
r6
r5
r4
(r1)
sp -> (r0)
with the stack pointer pointing at the space created by the dummy push of r0 and r1. Now we just have
mov r0, sp
which copies the stack pointer to r0 to use as the pointer argument to the function you're calling, which will then overwrite the two words at this location to result in a stack frame of
lr
r6
r5
r4
(64-bit value, high word)
sp -> (64-bit value, low word)
You haven't shown any code beyond the blx r3, so it's not possible to say exactly what happens to the stack at the end of the function. But if this function returns no arguments, I would expect to see a matching
pop {r0, r1, r4, r5, r6, pc}
which will, of course, result in your 64-bit result being left in r0 and r1. But these registers are call-clobbered according to the calling convention so there's no problem.

How to start the basic programming task using Pennsim and LC-3 programming language?

The task at hand is to write a subroutine STRCPY to implement a string copy function like the C the programming language's strcpy() function.
I know:
R1 is the address of the string to copy from
R2 is the address of where the string is to be copied to
It's to be assumed that the function should copy every character of the source string to the destination address (including the null terminator), thus creating a complete duplicate copy of the source string. Also, it can be assumed that the caller has allocated sufficient space for the new string, and the subroutine will not return any information to the caller.
The starting code is given here.
I guess I'm just somewhat overwhelmed by all of the LEA commands at the beginning and as such, any guidance/assistance would be tremendously appreciated.
I don't have your starting code, but guessing at what is required...
You might start by producing a more detailed explanation in English.
For example:
You have a string to copy. The string is in memory, beginning at a fixed address. The fixed address is in R1. You are going to copy the string to memory, to another fixed address. That other fixed address is in R2.
You can approach this by copying one character, moving to the next, and repeating. You will stop when you hit the last character (the one with value 0).
Copy the character at the address in R1 to the address in R2
Check if the character copied was the null terminator
If it was, stop.
If it was not, move the addresses in R1 and R2 up one character (point to next character), and go to step (1).
Then turn that into assembly:
Some of the sorts of instructions you will to translate this English recipe into LC3 assembly are likely to be:
LDR R3, R1, #0 will load the character at the address in R1 into R3.
STR is the analogous command you can use for storing the character in R2 (but you should work that out yourself if this is homework).
ADD R1, R1, #1 will add 1 to the address in register R1 (R1 = R1 + 1).
AND R4, R3, x1111 will set R4 to 0 if R3 is 0 (the null character) (R4 = R3 & 0x1111).
BRZ DONE will go to the label "DONE:" if the last instruction set the zero flag.
LEA R5, NEXT followed by JMP R5 will go to the label "NEXT:" by loading the address of the label "NEXT:" into R5 and then jumping to that value.
I imagine your code will look something like:
LEA R5, NEXT Put the address of NEXT in R5
NEXT:
LDR R3, R1, #0 Copy what is in the address in R1 (a character) to R3
STR... Store the character in R2
AND R4, R3, x1111 See if the character in R3 (the one copied) is 0
BRZ DONE If it is, finish
ADD R1, R1, #1 If not, go to the next character
ADD ...
JMP R5 Jump to the address in R5 (which is NEXT)
DONE:
...
You should not assume I have this correct. I don't have an LC3 simulator handy.
Best of luck.

Resources