The question is "Store the data to the memory location 1001h, ..(1001h+10) and copy the data in reverse order in memory location 2001...(2001+h)" I keep getting the run time error invalid immediate operand value
immediate must be creatable by rotating an 8-bit number right within a 32bit word.
How do i fix it?
MVN R2,#0x1001
MOV R3,#0x2000
MOV R4,#0X01
MOV R0,#0X10
LOOP
STRB R4,[R2]
LDRB R5,[R2]
STRB R0,[R3]
ADD R2,R2,#0x01
ADD R3,R3,#0x01
ADD R4,R4, #0x01
SUB R0,R0, #0x01
CMP R0,#0x01
BNE LOOP
END
Related
; Call a function "high" to find the largest element in array A
AREA |.text|, CODE, READONLY
EXPORT high
high
MOV R1,#0 ; Set R1 to 0
MOV R2,#0 ; Set R2 to 0
LDR R3,[A,R1] ; Load the first element in array A
LDR R4,[A]; Load the first element in array A
MOV R5,#5 ; Set R5 to the size of array A
Here While building the program I am getting an error saying "Bad register symbol, expected Integer register".
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.
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
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).
Ok, to make things as simple as possible, say I have a basic loop that i want to use in order to modify some elements of an array labeled a. In the following sample code I've tried replacing all elements of a with 1, but that doesn't really work.
assume cs:code ,ds:data
data segment
a db 1,2,3,4
i db 0
data ends
code segment
start:
mov ax,data
mov ds,ax
lea si,a
the_loop:
mov cl,i
cmp cl,4
jae the_end
mov ds:si[i],1 ; this is the part that i don't really understand since
inc i ; i'm expecting i=0 and ds:si[i] equiv to ds:si[0] which
loop the_loop ; is apparently not the case here since i actually receives the
; the value 1
the_end:
mov ax,4c00h
int 21h
code ends
end start
I am aware that I could simply do this by modifying the element stored in al after the lodsb instruction, and just store that. But I would like to know if it is possible to do something like what I've tried above.
In x86 assembly you can't use a value stored to a memory to address memory indirectly.
You need to read i into some register that can be used for memory addressing, and use that instead. You may want to check Wikipedia for 8086 memory addressing modes.
So, replace
mov ds:si[i],1
with (segment ds is unnecessary here, as it's the default of si, bx and bx+si too):
xor bx,bx
mov bl,[i]
mov [bx+si],byte 1 ; some other assemblers want byte ptr
There are other problems with your code too. The entire loop can be made easier and fixed this way:
lea si,a
xor cx,cx
mov cl,[i]
#fill_loop:
mov [si], byte 1
inc si
dec cx
jnz #fill_loop
Or, if you want to save 1 byte and use loop instruction.
#fill_loop:
mov [si], byte 1
inc si
loop #fill_loop
Note that in 16-bit mode loop instruction decrements cx and jumps to label if cx is not zero after decrement. However, in 32-bit mode loop decrements ecx and in 64-bit mode (x86-64) it decrements rcx.
I suppose that your code does not even run through the assembler, since
mov ds:si[i],1
is not a valid address mode.
Use something like
mov byte ptr [si],1 ; store value 1 at [SI]
inc si ; point to next array element
instead (used MASM to verify the syntax).
The DS: prefix is unnecessary for [si] since this is the default.
See also The 80x86 Addressing Modes.