I am writing a bubble sort in ARM Assembly on the STM32.
AREA Data1,DATA,READWRITE
ARR DCD 1,3,2,4
How can I write a value to the array in the data area? I am using LDR,=ARR to load the address of ARR. However, when I check the memory, the values are all zero.
AREA main, CODE, READONLY
EXPORT __main
__main
MOV R4,#4; LENGTH OF ARRAY
MOV R5,#3; NUMBER OF ITERATIONS
MOV R6,#3; NUMBER OF COMPARISONS
LDR R0,=ARR; ADDRESS OF ARR[0] FROM DATA AREA
__LOOP1
CMP R5,#0
BEQ __done
CMP R6,#0
BEQ __L2;
LDR R2,[R0,#4]; R2=ARR[i+1]
LDR R1,[R0];
MOV R3,R1;
CMP R1,R2;
BLE __L1;
STR R2,[R1];
STR R3,[R0];
__L1
SUBS R6,#1;
ADDS R0,#4;
B __LOOP1;
__L2
SUBS R5,#1;
MOV R6,R5;
LDR R0,=ARR;
B __LOOP1;
__done
AREA A,DATA,READWRITE
ARR DCD 1,3,2,4
END
Related
I am trying to copy data from LUT from one location and copying it to another location. Here is the code
AREA Program, CODE, READONLY
EXPORT __main
ENTRY
__main
ldr r0, =SourceL ; Address of SourceL
ldr r1, =DestinationL ; Address of DestinationL
ldr r2, [r0] ; r2 contains data#SourceL
str r3, [r1] ; r3 contains data#DestinationL
mov r4, #245
str r4, [r1]
SWI &11
AREA MyData, DATA, READWRITE
SourceL
DCW &1234
ALIGN
DestinationL
DCW &0
ALIGN
END
This is a very basic ARM7TDMI assembly code.
When I see the address of Labels(in debugger). SourceL is 0x40000000 and DestinationL is 0x40000004.
But when I see the memory locations, they are having zero values .
But in LUT SourceL is having value &1234.
When I try to store some data at memory representing by label DestinationL I am able to successfully do that.
This is not the only case of this above code.
The example code in the ARM website
AREA StrCopy, CODE, READONLY
EXPORT __main
ENTRY ; Mark first instruction to execute
__main
LDR r1, =srcstr ; Pointer to first string
LDR r0, =dststr ; Pointer to second string
BL strcopy ; Call subroutine to do copy
stop
MOV r0, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; ARM semihosting (formerly SWI)
strcopy
LDRB r2, [r1],#1 ; Load byte and update address
STRB r2, [r0],#1 ; Store byte and update address
CMP r2, #0 ; Check for zero terminator
BNE strcopy ; Keep going if not
MOV pc,lr ; Return
AREA Strings, DATA, READWRITE
srcstr DCB "First string - source",0
dststr DCB "Second string - destination",0
END
The memory corresponding to srcstr is showing zero only.
I am using KEIL IDE for programming.
Why data in LUT is not shown in the memory location?
Thanks!
Your code does not copy #SourceL to #DestinationL. It only loads data into registers and does nothing with it (exactly per the comments).
ldr r0, =SourceL ; Address of SourceL
ldr r1, =DestinationL ; Address of DestinationL
ldr r2, [r0] ; r2 contains data#SourceL
str r2, [r1] ; Copy data#SourceL to DestinationL <<ADD THIS
I am working on one of the simple codes assigned for a ARM microprocessor course I'm taking. I am having a slight issue with getting my code to load a value of an array to compare using Keil. The program is supposed to compare 5 numbers and then store values if the comparison is true. When I run my program it will not load array values that I declared. My professor isn't much help either and doesn't seem to know why it's not working properly.
Here's what I have done so far. I also think my PUSH is wrong but I can probably figure that out after I at least get the array to load. I should be pushing those values onto the stack but I am pretty sure I'm just loading values in registers instead.
AREA main, CODE, READONLY
EXPORT __main
ENTRY
__main PROC
MOVS r5, #0
LDR r0, =NUMB
loop1
LDR r1, [r0]
CMP r5, #5
BEQ stop
loop
CMP r1, #10
BLT low10
CMP r1, #100
BLT mid
CMP r1, #255
BLT high100
low10
PUSH {r2}
MOVS r2, #2
ADDS r5, #1
B loop1
mid
PUSH {r3}
MOVS r3, #0
ADDS r5, #1
B loop1
high100
PUSH {r4}
MOVS r4, #1
ADDS r5, #1
B loop1
stop B stop
ENDP
AREA myDATA, DATA, READWRITE
ALIGN
NUMB DCD 1,11,111,11,1
END
With respect to the array, your element size is not 1-byte, it's 4-bytes.
Using GNU & GDB, if we examine the address at R0 and interpret as signed words (i.e, 4 byte form), we see the expected array values.
.data
NUMB: .word 1,11,111,11,1
...
LDR r0, =NUMB
(gdb) x/8wd $r0
0x200dc: 1 11 111 11
0x200ec: 1 4929 1634033920 16804194
So you will need to change your values in the context of R5 to assume a 4-byte word. E.g.,
CMP r5, #(4*5)
ADDS r5, #4
Is is sadly very simple, just change in myData READWRITE to READONLY :)
i have an assignment which requires me to loop through string of numbers and perform task based on each number. For example, if numbers are "24531", i have to blink the LED lights on my microprocessor boards which are on indices "2", "4", "5", "3" and "1".
I'm just stuck on the part where i need to loop through these string of numbers and have to interpret them individually in ARM assembly language.
Borrowing from original code by Colin__s
You can construe the string as byte size elements of some array.
Use ldrb to load byte from array at element n...
The code below will branch to "some function" when ASCII value for #4 is encountered. The code will fail to return; which is one of several things you will need to further resolve.
.data
array: .string "123456"
.equ len.array,.-array
.align
.text
.global main
main:
nop
ldr r2,=array // pointer
MOV r0, #0 // initialise loop index to 0
MOV r1, #len.array // number of elements
Loop:
ldrb r3, [r2,r0]
cmp r3, #0x34 // #4
beq _do_something
ADD r0, r0, #1 //increment loop index
CMP r0, r1
BLE Loop
_exit:
mov r7, #1
svc 0
_do_something:
ldr r10,=0xdeadc0de
I don't completely follow your question, but the code for a loop is below. You can add whatever it is you need to do on each iteration before the compare instruction.
MOV r0, #0 ;initialise loop index to 0
MOV r1, #100 ;number of iterations
Loop:
ADD r0, r0, #1 ;increment loop index
CMP r0, r1
BLE Loop
I am working on this homework assignment, and my professor is stumped (as I am too) on why my array address refuses to load into R2. He said my code is correct, but he is absolutely uncertain about why it is behaving this way. It used to load 10 constantly, however, under the branch manageArray:, it should be overwriting the old use of R2. I even tried re-initializing the value, and it never worked.
We have run it under ARMSim, and code it as a .s file under notepad++. If anyone can point out what the potential cause is and why (because I absolutely want to learn from this, not look for answers!), I would be forever in your debt!! We have sat for nearly an hour and sent back so many emails over this, we're just frustrated and lost on where to go. It always loads a value of 10 or 11, but never the array address.
This is my code as of now. Basically, it's meant to check for odds (and terminate if true), else, add all of the array and print that total out. Semi-colons (;) are comments in assembly, which is weird.
.data
oddPrompt: .asciz "This Array is odd: we are terminating this thing.\n\r"
.align
terminatedPrompt: .asciz "YOU HAVE BEEN TERMINATED!\n\r"
.align
totalPrompt: .asciz "Total : \n\r"
.align
arrayLength = 10
;determineArrayOdds = arrayLength
array: .skip arrayLength*4
.text
mov r0,#0
mov r1,#0
mov r2,#arrayLength
mov r3,#0
mov r6,#0 ;element 1
mov r7,#0 ;element 2
mov r8,#0 ;added values from R7 and R6
mov r9,#0 ;grandTotal
verifyOdds:
sub r2, r2, #2
cmp r2,#2
blt errorForOdd
bgt verifyOdds
beq manageArray
errorForOdd:
;It's odd, so we skip calculating, because we never hit 2
mov r0,#1
ldr r1,=oddPrompt
swi 0x69
swi 0x11
manageArray:
ldr r2,=array
loop:
;Here, populate and add array elements.
;R2 will be re-purposed for this to conserve space.
swi 0x6d
and r0,r0,#0xff ;get time tick UP to 255 (via hex)
mov r1,r0
mov r0,#1
;swi 0x6b
str r1,[r2],#4
cmp r4,#arrayLength
addlt r4,r4,#1
blt loop ;ORIGINAL 49, now 50
moveq r4,#0
ldreq r2,=array
beq addArray
addArray:
ldrlt r6,[r2,#0] ;element 1
ldrlt r7,[r2,#4] ;element 2
add r2,r2,#8
add r8,r7,r6 ;store to r8
;mov r9,r8
add r9,r8,r9
cmp r4,#arrayLength
addlt r4,r4,#1
blt addArray
beq total
total:
mov r0,#1
ldr r1,=totalPrompt
swi 0x69
mov r1,r9 ;r1 has to hold the total to print
mov r0,#1 ;r0 must be set to true
swi 0x6b ;PRINT TOTAL NOW
swi 0x11
terminate:
mov r0,#1
ldr r1,=terminatedPrompt
swi 0x69
swi 0x11
I'm new to assembly programing and I'm programing for ARM.
I'm making a program with two subroutines: one that appends a byte info on a byte vector in memory, and one that prints this vector. The first address of the vector contains the number of elements that follows, up to 255. As I debug it with GDB, I can see that the "appendbyte" subroutine works fine. But when it comes to the "printvector" one, there are some problems. First, the element loaded in register r1 is wrong (it loads 0, when it should be 7). Then, when I read the registers values with GDB after I use the "printf" function, a lot of register get other values that weren't supposed to change, since I didn't modify them, I just used "printf". Why is "printf" modyfing the values.
I was thinking something about the align. I'm not sure if i'm using the directive correctly.
Here is the full code:
.text
.global main
.equ num, 255 # Max number of elements
main:
push {lr}
mov r8, #7
bl appendbyte
mov r8, #5
bl appendbyte
mov r8, #8
bl appendbyte
bl imprime
pop {pc}
.text
.align
printvector:
push {lr}
ldr r3, =vet # stores the address of the start of the vector in r3
ldr r2, [r3], #1 # stores the number of elements in r2
.align
loop:
cmp r2, #0 #if there isn't elements to print
beq fimimprime #quit subroutine
ldr r0, =node #r0 receives the print format
ldr r1, [r3], #1 #stores in r1 the value of the element pointed by r3. Increments r3 after that.
sub r2, r2, #1 #decrements r2 (number of elements left to print)
bl printf #call printf
b loop #continue on the loop
.align
endprint:
pop {pc}
.align
appendbyte:
push {lr}
ldr r0, =vet #stores in r0 the beggining address of the vector
ldr r1, [r0], #1 #stores in r1 the number of elements and makes r0 point to the next address
add r3, r0, r1 #stores in r3 the address of the first available position
str r8, [r3] #put the value at the first available position
ldr r0, =vet #stores in r0 the beggining address of the vector
add r1, r1, #1 # increment the number of elements in the vector
str r1, [r0] # stores it in the vector
pop {pc}
.data # Read/write data follows
.align # Make sure data is aligned on 32-bit boundaries
vet: .byte 0
.skip num # Reserve num bytes
.align
node: .asciz "[%d]\n"
.end
The problems are in
ldr r1, [r3], #1
and
bl printf
I hope I was clear on the problem.
Thanks in advance!
The ARM ABI specifies that registers r0-r3 and r12 are to be considered volatile on function calls. Meaning that the callee does not have to restore their value. LR also changes if you use bl, because LR will then contain the return address for the called function.
More information can be found on ARMs Information Center entry for the ABI or in the APCS (ARM Procedure Call Standard) document.
printvector:
push {lr}
ldr r3, =vet # stores the address of the start of the vector in r3
ldr r2, [r3], #1 # stores the number of elements in r2
.align
loop:
cmp r2, #0 #if there isn't elements to print
beq fimimprime #quit subroutine
ldr r0, =node #r0 receives the print format
ldr r1, [r3], #1 #stores in r1 the value of the element pointed by r3. Increments r3 after that.
sub r2, r2, #1 #decrements r2 (number of elements left to print)
bl printf #call printf
b loop #continue on the loop
.align
endprint:
pop {pc}
that is definitely not how you use align. Align is there to...align the thing that follows on some boundary (specified in an optional argument, note this is an assembler directive, not an instruction) by padding the binary with zeros or whatever the padding is. So you dont want a .align in the code flow, between instructions. You have done that between the ldr r1, and the cmp r2 after loop. Now the align after b loop is not harmful as the branch is unconditional but at the same time not necessary as there is no reason to align there the assembler is generating an instruction flow so the bytes cant be unaligned. Where you would use .align is after some data declaration before instructions:
.byte 1,2,3,4,5,
.align
some_code_branch_dest:
In particular one where the assembler complains or the code crashes.