I was given an array, defined by:
.orig x6000
.fill -20
.fill 14
.fill 7
.fill 0
.fill -3
.fill 11
.fill 9
.fill -9
.fill 2
.fill -5
.end
I need to iterate through these values within my main program. From what I understand this "array" is just values stored in memory far away from where the instructions are stored. My question is, "How do I load these values?" I know that they start at x6000, but I don't know how to get to them using instructions.
The best thing to do would be to read the LC3 ISA and pay special attention to the LDR instruction.
Here is an example program to help get you started.
You need to know and keep track of two things: (1) the address of the array and (2) the length of the array/index as you iterate. For (1), I chose to use a filled value; for (2) the length of the array is defined in the instruction itself. I AND R1, R1, 0 to clear the register and add 10. We could just as easily have a filled value LENGTH equal to 10 and LD R1 LENGTH.
The loop begins by decrementing R1 and checking to see if it is negative. If R1 is negative, then the loop exits. We decremented length first, so you can think of the "length" (value in R1) as an index. So, if the index < 0, then the loop exits.
The LDR R0, R2, 0 instruction gets the value at the address in register R2 offset by 0 and puts it in R0. Presumably you would want to do something with the data after this line.
Before the unconditional branch to LOOP, we increment the address of the array to point at the next element.
.orig x3000
LD R2, ARRAY ; R2 = x6000
AND R1, R1, 0 ; R1 = 0 (clear before add)
ADD R1, R1, 10 ; R1 = 10 (length of array)
LOOP ADD R1, R1, -1 ; R1--
BRn DONE ; if R1 < 0 then halt, else...
LDR R0, R2, 0 ; R0 <-- mem[R2 + 0]
ADD R2, R2, 1 ; R2++
BR LOOP ; loop
DONE HALT ; halt
ARRAY .fill x6000
.orig x6000
.fill -20
.fill 14
.fill 7
.fill 0
.fill -3
.fill 11
.fill 9
.fill -9
.fill 2
.fill -5
.end
Related
I have an example here. I checked on the debug and realized that in the beginning, the SP's value is 0x20001000. Why does the compiler use 0x20001000 for the intitial value of stack pointer? I created some data segments but it's still 0x20001000.
soA EQU 25
soB EQU 30
AREA RESET, DATA, READONLY
DCD 0x20001000
DCD Reset_Handler
AREA MYCODE, CODE, READONLY
EXPORT Reset_Handler
ENTRY
Reset_Handler
MOV R0, #soA
MOV R1, #soB
KiemTra
CMP R0, R1
BLT NhoHon
BEQ KetThuc
LonHon
SUB R0, R1
B KiemTra
NhoHon
SUB R1, R0
B KiemTra
KetThuc
END
I need to write a ARM assembly program will “iteratively” sum up (the integer multiplication of each integer element in the array_D by 4) and also the next element by looping until the end of the array signaled by 0. In each iteration, the current element x of the array_D will be replaced with the new result of summation as (x * 4 + [next element]). For instance, in case array_D = [2020, -97, 2441, -11, 0], the final result stored in r0 should be : (2020 * 4 - 97) + (-97 * 4 + 2441) + (2441 * 4 -11) + (-11 * 4 + 0)= 19745, with the array_D updated as [7983, 2053, 9753, -44, 0]. When it reaches the end of the array, the ARM assembly program will exit the loop and then terminate the program execution with the result of summation stored in register r0. Here is the program I've written:
# File : simple2.s------------------------
.data
array_D: .word 2020, -97, 2441, -11, 0
.text
.global main
main:
LDR r1,=array_D # load base addr. of array_D into r1
MOV r2, #0 # r2 as the array pointer
loop:
LDR r3, [r1,r2] # r3 as the array element
LSL r3, r3, #2 # multiply r3 by 4
MOV r4, r2 # copy r2 to r4
ADD r2, r2, #4 # r2 points to next element
LDR r5, [r1,r2] # r5 as the next element
ADD r3, r3, r5 # add r5 to r3
ADD r0, r0, r3 # sum the new element to r0 (change this to ADD r6, r6,
r3 and it worked)
STR r3, [r1,r4] # store the new value to the array_D
CMP r5, #0 # test if the next element is 0
BNE loop # loop if not 0
SWI 0x11
.end
However this program will not store the final result in r0 but zero instead (register view 1). I have tried r6 to store the result and it worked (register view 2). But the assignment requires me to store it in r0. What is wrong with my program?
register view 1
register view 2
I'm trying understand what is the reason of ARM exception that I encounter.
It happens randomly during system startup, and may looks in few different ways.
One of simplest is following:
0x8004e810 in ti_sysbios_family_arm_a8_intcps_Hwi_vectors ()
#0 0x8004e810 in ti_sysbios_family_arm_a8_intcps_Hwi_vectors ()
#1 0x80002f04 in ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm(int0_t) ()
at /home/rnd_share/sysbios/bios_6_51_00_15/packages/ti/sysbios/family/arm/exc/Exception_asm_gnu.asm:103
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
r0 0x20000197 536871319
r1 0x20000197 536871319
r2 0x20000197 536871319
r3 0x20000197 536871319
r4 0x20000197 536871319
r5 0x6 6
r6 0x80000024 2147483684
r7 0x80007a0c 2147514892
r8 0x8004f0a8 2147807400
r9 0x80041340 2147750720
r10 0x80040a3c 2147748412
r11 0xffffffff 4294967295
r12 0x20000197 536871319
sp 0x7fffff88 0x7fffff88
lr 0x80002f04 2147495684
pc 0x8004e810 0x8004e810 <ti_sysbios_family_arm_a8_intcps_Hwi_vectors+16>
cpsr 0x20000197 536871319
PC = 8004E810, CPSR = 20000197 (ABORT mode, ARM IRQ dis.)
R0 = 20000197, R1 = 20000197, R2 = 20000197, R3 = 20000197
R4 = 20000197, R5 = 00000006, R6 = 80000024, R7 = 80007A0C
USR: R8 =8004F0A8, R9 =80041340, R10=80040A3C, R11 =FFFFFFFF, R12 =20000197
R13=80212590, R14=80040A3C
FIQ: R8 =AEE1D6FA, R9 =C07BA930, R10=1B0B137A, R11 =7EC3F1DF, R12 =2000019F
R13=80065CF8, R14=00000000, SPSR=00000000
SVC: R13=4030CB20, R14=00022071, SPSR=00000000
ABT: R13=7FFFFF88, R14=80002F04, SPSR=20000197
IRQ: R13=F4ADFD8A, R14=80041020, SPSR=8000011F
UND: R13=80085CF8, R14=ED0F7EF1, SPSR=00000000
(gdb) frame
#0 0x8004e810 in ti_sysbios_family_arm_a8_intcps_Hwi_vectors ()
(gdb) frame 1
#1 0x80002f04 in ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm(int0_t) ()
at /home/rnd_share/sysbios/bios_6_51_00_15/packages/ti/sysbios/family/arm/exc/Exception_asm_gnu.asm:103
103 mrc p15, #0, r12, c5, c0, #0 # read DFSR into r12
(gdb) list
98 .func ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm__I
99
100 ti_sysbios_family_arm_exc_Exception_excHandlerDataAsm__I:
101 stmfd sp!, {r0-r12} # save r4-r12 while we're at it
102
103 mrc p15, #0, r12, c5, c0, #0 # read DFSR into r12
104 stmfd sp!, {r12} # save DFSR
105 mrc p15, #0, r12, c5, c0, #1 # read IFSR into r12
106 stmfd sp!, {r12} # save DFSR
107 mrc p15, #0, r12, c6, c0, #0 # read DFAR into r12
(gdb) monitor cp15 6 0 0 0
Reading CP15 register (6,0,0,0 = 0x7FFFFF54)
My understanding is that, there was some ongoing exception, which can be seen in frame 1.
It tries to save registers onto stack:
101 stmfd sp!, {r0-r12} # save r4-r12 while we're at it
But, stack pointer was incorrect at:
ABT: R13=7FFFFF88
I don't understand both:
What can be a cause of such value of SP in ABT and IRQ contexts ?
what is actually in frame 0 ? in other words, how Cortex reacted to data abort while being already in exception handler ?
This device usually starts normally, such situation happens like 3 times per 10 boots. It never happens when starting from debugger, only release and only when started from bootloader.
Two weeks later...
Boot procedure is following:
2nd stage bootloader loads application to memory
2nd stage bootloader jumps to application start.
main function of application is entered.
It turns out that sometimes statically initialized values of application have correct values after 1 step of booting, but then in 3 step they are corrupted. I mean application image is corrupted.
Caches haven't been flushed correctly between step 1 and 2.
Disabling caches at 2nd stage bootloader fixed problem at all.
Now need to fix that correctly.
TL;DR: How to copy elements from one array to another (not all but some)?
I want to perform a sorting algorithm on some array, but so that I only sort odd or even numbers in it, depending on a flag. So my idea was to set a flag on either 0 or 1 and then I'd extract all the numbers that have to be sorted into another array and put -1 (as a marker) on the positions where those numbers were. After that I'd just insert the sorted numbers back into the original array, for example:
arr1: 5 8 2 4 13 9 14 10 9
arr2: 8 2 4 14 10
arr2 (sorted): 2 4 8 10 14
arr1 (without even numbers): 5 -1 -1 -1 13 9 -1 -1 9
arr1 (final): 5 2 4 8 13 9 10 14 9
Now while writing this in a higher language is rather trivial for me, doing it in assembly which I'm learning for a class isn't. The part where I sort the numbers works just fine, but the part that causes me problems is the one where I have to copy the numbers into another array. My main method looks like this:
section .data
arr dd 6,8,1,7,4,2,9,107,10,8,12,16,14,5
len equ ($-arr) / 4 - 1
section .bss
section .text
extern sort
global _start
_start:
mov r8, len
mov esi, arr ; esi points to the start of the array/top of it
call sort
mov rax, 60
mov rdi, 0
syscall
And the subroutine which will do the job (showing only the problematic part):
mov r9d, esi
.export:
mov eax, [r9d]
cdq
div dword [divider]
cmp edx, [flag]
je .add
.continue:
add r9d, 4 ; point to the next number
inc dword [i]
cmp r8d, [i]
jg .export
.add:
mov edi, [r9d]
mov dword [r9d], -1 ; put the number in the old array to -1
sub edi, 4
inc dword [lenNewArray] ; inc the total number of elements in new array
jmp .continue
Anyway what I want to accomplish is that I add an element that matches the condition to some location and then point rdi to that location, when I want to add another element I subtract -4 from rdi so it points to the lower location and put that element there, in the end I'd have rdi pointing to the last element which was extracted, is that possible to be done, and is it a bad way?
I am having problem on how exactly should i use loop to get the desire output in this program,
What i want to do is to take input any number from the user and then sort that number in descending order,
I tried my best here to explain every step of the code in the comment.
here is my code,
STSEG SEGMENT
DB 64 DUP(?)
STSEG ENDS
DTSEG SEGMENT
SNAME DB 24 DUP("$")
DTSEG ENDS
CDSEG SEGMENT
MAIN PROC
ASSUME CS:CDSEG, DS:DTSEG, SS:STSEG
MOV AX,DTSEG
MOV DS,AX
MOV ES, AX ;ES:DI
MOV DX, OFFSET STRNG1
MOV AH,09
INT 21H
XOR DX,DX
MOV BYTE PTR SNAME, 40
MOV DX, OFFSET SNAME
MOV AH, 0AH
INT 21H
PUSH DX ;Hold the input number in a stack until we clear the screen and set the cursor
; The clear screen and cursor position code is here which i didn't really mention.
;What we need to do now is to compare first number to each other number and store the greatest
of two on first position.
MOV BX,DX ;Copy un-sorted number to BX,
MOV AX,BX[1] ;the length of the number which is stored on the first position of the string
XOR AH,AH ;Empty AH
MOV CL,AL ;MOVE AL into CL for looping 6 times
SUB CL,1
MOV SI,02H ;the number is stored in string array from the 2nd position
;Suppose the input number is the following,
;[6][3][9][1][8][2][6]
;this is how it should work,
; Loop 6 times , CX = 6
[7][6][3][9][1][8][2][6] ; 7 is length of the number which is already copied in CX above.
; but we need 6 iterations this is why we subtract 1 from CL above.
; 6 > 3 ?
; Yes, then BX[SI] = 6 and BX[SI+1] = 3
; 6 > 9 ?
; NO, then BX[SI] = 9 and BX[SI+2] = 6
; 9 > 1
; Yes, then BX[SI] = 9 and BX[SI+3] = 1
; 9 > 8
; Yes, then BX[SI] = 9 and BX[SI+4] = 8
; 9 > 2
; Yes, then BX[SI] = 9 and BX[SI+5] = 2
; 9 > 6
; Yes, then BX[SI] = 9 and BX[SI+6] = 6
; After first iteration the incomplete sorted number is,
;[9][3][6][1][8][2][6]
;Similarly here i need to loop 5 times now by comparing the 2nd number which is a 3 with all ;the number after it and then loop 4 times then 3 times then two times and then 1 time.
L1:
;Loop 1 must iterate 6 time for the supposed input number,
;but i couldn't be able to write the proper code as i always get out of registers. kindly help me out
L2:
LOOP L2
Loop L1
Kindly help me with the nested loop where i've stucked.
The loop instruction uses the cx register.
So you must either preserve cx for the outer loop with e.g. push cx (before L2:) and pop cx (after loop L2):
mov cx,5
L1:
push cx
mov cx,6
L2:
. . . do stuff inner
loop L2
pop cx
. . . do stuff outer
loop L1
or remember that loop is roughly equal to dec cx jnz, so do e.g.
mov dx,5
L1:
mov cx,6
L2:
... do stuf inner
loop L2
.. do stuff outer
dec dx
jnz L1
Possible off-by-one errors are intended and meant as an exercise for the reader :-)