Find biggest and smallest values of an array using loops - arrays

I have the following code already written and everything should be good. It suppose to find biggest and smallest values in array of size 4 using loop.
I got the loops setup and everything except my output is not correct. I have a bug in line 46 that when load the array the value into register X11 I get big weird number and causes the whole calculations to be wrong.
Please see if you can suggests a fix in this code.
//X0 Array, X17 number of runs, X11 Biggest, X12 Smallest
ADR X0,v
LDR X17,=4
LDR X11,[X0],#3
MOV X12,X11
loop:
**LDR X11,[X0],#3 //Line 46**
//LSL X11,X0,#3
CMP X12,X11
BLT loop1
SUB X17,X17,#1
CMP X17,#1
BEQ exit
BGT loop
loop1:
MOV X12,X11
SUB X17,X17,#1
CMP X17,#1
BEQ exit
BGT loop
I'm using the DS-5 IDE, in case that matters.

LDR X11,[X0],#3
Reading 64bit values (Xregister), and post-incrementing by #3?
I have a great suspicions that 3Bytes != 64bit.

Related

Finding the smallest element in array in arm assembly

I have this program that i have to write in arm assembly to find the smallest element in an array. Normally this is a pretty easy thing to do in every programming language, but i just can't get my head around what i'm doing wrong in arm assembly. I'm a beginner in arm but i know my way around c. So I wrote the algorithm on how to find the smallest number in an array in c like this.
int minarray = arr[0];
for (int i =0; i < len; i++){
if (arr[i] < minarray){
minarray = arr[i];
}
It's easy and nothing special really.
Now i tried taking over the algorithm in arm almost the same. There are two things that have already been programmed from the beginning. The address of the first element is stored in register r0. The length of the array is stored in register r1. In the end, the smallest element must be stored back in register r0. Here is what i did:
This is almost the same algorithm as the one in c. First i load the first element into a new register r4. Now the first element is the smallest. Then once again, i load the first element in r8. I compare those two, if r8 <= r4, then copy the content of r8 to r4. After that (because i'm working with numbers of 32 bits) i add 4bytes to r0 to get on to the next element of the array. After that i subtract 1 from the array length to loop through the array until its below 0 to stop the program.
The feedback i'm getting from my testing function that was given to us to check if our program works says that it works partly. It says that it works for short arrays and arrays of length 0 but not for long arrays. I'm honestly lost. I think i'm making a really dumb mistake but i just cannot find it and i've been stuck at this easy problem for 3 days now but everything i have tried did not work or as i said, only worked "partly". I would really appreciate if someone could help me out.
This is the feedback that i get:
✗ min works with other numbers
✗ min works with a long array
✓ min works with a short array
✓ min tolerates size = 0
(x is for "it does not work", ✓ is for "it works")
So you see what i'm saying? i just do not understand how to implement the fact that its supposed to work with a longer array.
I'm not very good at ARM assembly by to my understanding R4 is expected to keep the value of minimum. R8 is used to keep the most recently fetched value from the input array.
The minimum is updated with this instruction:
MOVLE r8, r4
But it actually updated R8, not R4.
Try:
MOVLE r4, r8
EDIT
Other issue is using incorrect branch instruction:
SUBS r1, r1, #1
BPL loop1
works like:
r1 = r1 - 1
if (r1 >= 0) goto loop1;
For R1 equal to 1 the loop is exectured twice.
r1 = 1
... do stuff
r1 = r1 - 1 // r1 is 0 now
if (r1 >= 0) goto loop1; // 0>=0 TRUE!
... do stuff, overflow the input by indexing at `[r0 + 4]`
r1 = r1 - 1 // r1 is -1
if (r1 >= 0) goto loop1; // -1 >= 0 FALSE
// exit function
To fix it use branching only when input is non-zero.
BNE loop1
Coding in C use the correct types
You do not have to iterate from the index 0 only 1
int foo(const int *arr, size_t len)
{
int minarray = arr[0];
for (size_t i = 1; i < len; i++)
{
if (arr[i] < minarray)
{
minarray = arr[i];
}
}
return minarray;
}
And it generates this code:
foo:
mov r3, r0
subs r1, r1, #1
ldr r0, [r3], #4
beq .L1
.L3:
ldr r2, [r3], #4
cmp r0, r2
it ge
movge r0, r2
subs r1, r1, #1
bne .L3
.L1:
bx lr

How to make this LC3 program multiply instead?

Was trying to learn how to multiply in LC3 but having trouble modifying my old program that was just meant for adding sums. How would I go about modifying this program to multiply by the 2 given inputs?
Code:
.ORIG x3000 ; begin at x3000
; input two numbers
IN ;input an integer character (ascii) {TRAP 23}
LD R3, HEXN30 ;subtract x30 to get integer
ADD R0, R0, R3
ADD R1, R0, x0 ;move the first integer to register 1
IN ;input another integer {TRAP 23}
ADD R0, R0, R3 ;convert it to an integer
; add the numbers
ADD R2, R0, R1 ;add the two integers
; print the results
LEA R0, MESG ;load the address of the message string
PUTS ;"PUTS" outputs a string {TRAP 22}
ADD R0, R2, x0 ;move the sum to R0, to be output
LD R3, HEX30 ;add 30 to integer to get integer character
ADD R0, R0, R3
OUT ;display the sum {TRAP 21}
; stop
HALT ;{TRAP 25}
; data
MESG .STRINGZ "The sum of those two numbers is: "
HEXN30 .FILL xFFD0 ; -30 HEX
HEX30 .FILL x0030 ; 30 HEX
.END```
The simplest approach to multiply on LC-3 is repetitive addition. So keep summing the multiplicand and decrement the multiplier; the iteration stops when the multiplier is consumed (i.e. zero).
There are lot's of caveats: if the multiplier is negative, then we would either negate it to use with count down, or count up instead — either way, the final result would be negated.
Since multiplication is commutative, we might consider using the lessor (absolute) value for the multiplier so that fewer iterations are done. But for more optimal multiplication, we would switch to a whole 'nother algorithm, the shift and add. Note that this algorithm is usually presented for hardware implementation, in which saving precious register bits is important, whereas for software this is not a really significant concern.

ARM Assembly, Keil Microvision 4; Working with non-zero registry values

Hoping for just a bit of help with something.
I have a college assignment which involves making what is basically a calculator that takes values entered in by the user as a string of ASCII characters and stores and displays the entered value, as well as making various computations such as sum, min, etc. and stores them all as well. The code only executes after a value is entered.
My code itself is working how I need it to so far, and I think I know how to write in all the computations, but my issue is that most of the registers hold non-zero values from the start, and so if I start adding in values to a register right away -- for the sum, for instance -- the end value will be incorrect. I can't just use LDR and set them to zero beforehand, though, since that will happen every time the code is run, and I need to keep the added values around to make the computations each time.
I don't know if I'm overthinking this or if there's something really simple that I'm missing, but I can't think of a way to do what I need to with non-zero registry values.
This is my working code so far:
AREA ConsoleInput, CODE, READONLY
IMPORT main
IMPORT getkey
IMPORT sendchar
EXPORT start
PRESERVE8
start
read
LDR R7, =0
BL getkey ; read key from console
CMP R0, #0x0D ; while (key != CR)
BEQ endRead ; {
BL sendchar ; echo key back to console
;R4 is used to store the hex value of whatever is entered (as a full number)
;R5 stored the entered input safely (as R0 can change)
;R6 holds the constant 10, for increasing successive entries by a base of ten
;R10 is where successive values are multiplied by 10
;R11 is used to hold the count (+1 each time the code is run)
LDR R6, =10
MUL R10, R6, R10
MOV R5, R0
AND R5, R5, #&F
ADD R10, R10, R5
MOV R4, R10 ;NUMBER ENTERED SENT TO R4
ADD R11, R11, #1 ;COUNT
B read ; }
endRead
stop B stop
END

Assembly language x86 IRVINE infinite loops

I'm new to Assembly language and I need help with an error I keep experiencing, my task in class is to do what I did below, everything I did is correct and how the professor wants it but I can't stop the program from infinite looping, I have the correct answer which is 14 but how do I stop the loop from being infinite without using special commands like ret. How do I stop it?
;Declare an array of words
;Write a loop that adds all the elements of the array located in even places
;Example 3,7,2,8,9
;3+2+9=14
INCLUDE Irvine32.inc
.data
val1 WORD 3,7,2,8,9
.code
main PROC
mov eax, 0
L1:
mov ecx, (LENGTHOF val1)*(TYPE val1+2)-(TYPE val1+4)
mov eax, ecx
call writeDec
loop L1
exit
main ENDP
END main
At the bottom of your loop, you have this instruction:
loop L1
which means "go back to L1."
Loop L1 is a conditional LOOP that is based on the value in ECX. The
real issue is the problem with the value in ECX. LOOP will first
decrement ECX by 1 and compare the new value in ECX with zero. If it
isn't zero it goes to the label (L1). If it is zero it falls through.
Look carefully at where you set the value of ecx. After LOOP decrements ecx by 1 and execution goes to L1, what happens?

sub-routines on Assembly

can I do something like this on Assembly bne jsr swap, if not how can I solve this problem from C, thanks in advance
if(start!=pivot_index){
swap(board,start,pivot_index);
}
I was taught that I must write jsr and sub-routine but can I do something like this bne sub-routine
In assembly that would usually be translated into something like this (pseudo-assembly):
load [start]
compare [pivot_index]
branch-if-equal label1
push [pivot_index]
push [start]
push [board]
call swap
add-stack-pointer 12
label1:
ie. the if statement is converted into a jump that jumps over the body of the if if the controlling expression is not true.
Sure you can do this. On x86 you need two branches:
# assume EAX = start, EBX = pivot_index
cmp eax, ebx
beq .SkipSwap
call swap
.SkipSwap:
For ARM assembly it's easier because you can use a conditional branch:
# assume r0 = start, r1 = pivot_index
cmp r0, r1
blne swap
No, you cannot do bne subroutine instead of jsr subroutine, because jsr means "jump setting return".
The difference between that and the conditional branch instructions is that the jsr pushes the return address onto the stack, so the subroutine knows where to return. If you just branch to the subroutine using bne, there's no return address saved, so the subroutine doesn't know where to return when done.
caf's answer shows you the typical way you would handle that, you just need to translate it into PDP-11 operations.

Resources