ARM Assembly - Factorial Recursion Program Counter out of valid memory range - recursion

Hello I am very new to writing assembly and have a question regarding my attempt at writing a recursive function to compute the factorial of n.
Here is my attempt at writing the factorial function:
.global main
main:
MOV r1, #3
fact:
SUB sp, sp, #8
STR lr, [sp, #0]
STR r1, [sp,#4]
CMP r1, #1
BGT Else
ADD sp, sp, #8
MOV pc, lr
Else:
SUB r1, r1, #1
BL fact
MOV r2, r1
LDR r1, [sp, #4]
LDR lr, [sp, #0]
ADD sp, sp, #8
MUL r1, r2, r1
MOV pc, lr
MOV r0, #1
SWI 0x6b
SWI 0x11
The issue is this: i successfully can compute that 3 factorial is 6 and it gets stored in r1 at the end of the program; however, I can never get passed the last "MOV pc, lr" statement in the third execution of the loop and I cannot understand the logic behind why.
When I get to the third loop of MOV pc, lr I get an error stating: "PC out of valid memory range" but I am not sure why this is the case. Any pointers in the right direction would be greatly appreciated because I am an absolute beginner and cannot understand why this error is occurring. Thank you for your time!

Related

Intel 8086 Division. Need AX to be denominator not numerator

Need to divide CL by 10. I understand that in division AX will always be the numerator, but I need it to be the denominator.
In the code below I attempt to move the value I need as the numerator into AL and then put 10 into CL and divide.
Any help would be appreciated.
Mov Al, Cl
Mov Cl, 10
Div Cl
Need to divide Cl by 10
So you'll want the quotient back in the CL register then.
Your corrected solution (10 bytes):
mov al, cl
xor ah, ah ;Clear high byte because DIV will use the entire AX
mov cl, 10
div cl ;Divides AX by 10, leaves quotient in AL
mov cl,al
Shorter solution (6 bytes):
mov al, cl
aam ;Divides AL by 10, leaves quotient in AH
mov cl, ah
On 8086 the AAM instruction exclusively divides by 10.
On x86 the AAM instruction can divide by any byte-sized number.
So this AAM instruction is in effect an 8 bit by 8 bit division!
Is there a way then to divide a register by 10?
All divisions implicitly use the accumulator (AL, AX, DX:AX). Just copy your register to the accumulator first.

Read After Write(RAW) HAZARD

I am confused in finding RAW dependencies whether we have to find only in adjacent instructions or non-adjacent also.
consider the following assembly code
I1: ADD R1 , R2, R2;
I2: ADD R3, R2, R1;
I3: SUB R4, R1 , R5;
I4: ADD R3, R3, R4;
FIND THE NUMBER OF READ AFTER WRITE(RAW) DEPENDENCIES IN THE Above Code.
assume ADD x,y,z = x <- y + z
I am getting 2 dependency I2-I1 and I4-I3.
Let us say that after an instruction enters the pipeline, it will take it x stages after which any register write by that instruction will be visible to any following instruction.
Then you have to take care of the RAW dependencies among every set of x consecutive instructions. In the worst case you can take x to be the max no. of stages in the pipeline.
Now, the case in the question looks like a HW problem and since the pipeline structure is not defined so you will have to look at the RAW dependencies over all the instructions, which in this case are:
I2 and I1 over R1
I3 and I1 over R1
I4 and I2 over R3
I4 and I3 over R4

8086 assembly language unsigned interpretation

I have to write a program in 8086 assembly that calculates this:
(a+b*c+2/c)/(2+a)+e
where
a,b - byte
c - word
e - doubleword,
in unsigned interpretation.
So far I have this:
assume cs:code,ds:data
data segment
a db 4
b db 2
c dw 16
e dd 126
data ends
code segment
start:
mov ax,data
mov ds,ax
and here is my program
mov al,b ; al=b
mov ah,0 ; ax=b;
mul c; dx:ax=b*c; b*c=doubleword
mov bx,ax; we save b*c in bx to use ax in the division 2/c
mov al,2; al=2
mov ah,0; al=ax=0
div c; ax=dx:ax/c ; dx=dx:ax%c;
I don't know how to continue.
When you write
mov bx,ax; we save b*c in bx to use ax in the division 2/c
you're actually only saving the low word of the product between B and C. It works with the numbers provided but it's not a general solution.
In stead of writing
mov al,2; al=2
mov ah,0; al=ax=0
use mov ax,2 and remember to explicitely clear the DX register because the division needs it.
To continue I would suggest you create a result variable of doubleword size because in the end the size of your largest expression participant defines the size of the result. Then on the way move or add your partial results to this variable.
If you are allowed to use 32 bit registers a suitable approach might be to promote all values to 32 bit and continue from there.

How do you clear a specific bit in a register without changing the other bits in ONE instruction?

For example, let's say register 4 (R4) has a value 0001110010101111. How could you change bit 5 (0001110010 >1< 01111) to 0 (even if it was already 0) without moving or changing the other bits in a single hex instruction?
So 0001110010101111 -> 0001110010001111
You'll want to AND it. Since the immediate value for AND is 5 bits and it uses sign extension, you can only clear a bit if it's one of the four least significant bits. Otherwise, you will need to perform another instruction to load the mask into a register. I'll do an example of both.
In the case of the 5th bit, the number that will mask the bit is 0b1111111111011111. In decimal, this is #65503 or #-33. Since this is too big to fit in an immediate instruction, you won't be able to do it in a single instruction. You will need to declare it in the data segment of your program and load the mask into a register. Then, you can AND it with R4.
; assuming R4 = 0001110010101111
LD R5, MASK_5 ; load the mask into R5
AND R4, R4, R5 ; set R4 = R4 AND R5
; R4 will now have the bit cleared
; data segment
MASK_5 .FILL #65503
In the case of the 3rd bit, the number that will mask the bit is 0b1111111111110111. In decimal, this is #65527 or #-9. This will fit in the immediate value of AND, so you can perform it in a single instruction:
; assuming R4 = 0001110010101111
AND R4, R4, #-9 ; set R4 = R4 AND #-9
; R4 will now have the bit cleared

Arithmetic operations in ASM Language

I just need some help. I don't fully understand and I am fairly new to masm32 so if you could explain, that would be great!
MOV AX, 200
ADD AX, 300
MOV RESULT, AX
Will result be equal to 500? I tried adding 3 and 2 and using this to show output:
MOV DX, RESULT
ADD RESULT, '0'
MOV AH, 02H
INT 21H
But the output is a candy cane character! Where is it wrong?
Now I assume subtraction will work the same as addition, so on to Multiplication we go.
This is what I did for multiplication
MOV AX, 30
MOV BX, 8
MUL BX
MOV RESULT, AX
Is RESULT's value equal to 240?....
I tried AX as 3 and BX as 2. The output is a spade. Can you point me to the right direction?
Now division.
MOV AX, 30
MOV BX, 12
DIV BX
MOV RESULT, AX
What holds the quotient? If what I read was correct, that would be AX, and DX holds the remainder...?
I have already done 8 bit arithmetic (using AL, BL, DL...) and I tried to apply it here, sadly, when the RESULT becomes greater than 128, it just outputs garbage. Someone suggested that I should declare my variables as 'RESULT dw ?' instead of 'RESULT db ?' and instead of AL BL registers I should use AX BX.... Now I'm stuck.
Any help would be appreciated! Sorry if these questions seem too trivial. Anyway, thanks in advance! :DD
MOV AX, 200
ADD AX, 300
MOV RESULT, AX
Will result be equal to 500?
Yes.
I tried adding 3 and 2 and using this to show output:
MOV DX, RESULT
ADD RESULT, '0'
MOV AH, 02H
INT 21H
But the output is a candy cane character! Where is it wrong?
You're adding '0' to RESULT after moving RESULT to DX. You should probably add '0' to DL instead of to RESULT.
Now division.
MOV AX, 30
MOV BX, 12
DIV BX
MOV RESULT, AX
What holds the quotient? If what I read was correct, that would be AX, and DX holds the remainder...?
DIV BX divides the 32-bit value DX:AX by BX, so you should clear DX before the division. The quotient will end up in AX and the remainder in DX.
Someone suggested that I should declare my variables as RESULT dw ?
If you're going to move 16-bit values to/from the variable (e.g. MOV RESULT,AX) then you should make the variable (at least) 16 bits.

Resources