Intel 8086 Division. Need AX to be denominator not numerator - intel

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.

Related

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

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!

How to simply convert MIPS instruction to 32bits hex number

I'm working with ASM/MIPS technology and I want to train myself to conversion.
I wanna convert MIPS instructions to a 32bits hexadecimal number.
For example, I want to change sub$t0,$zero,$t1 to a hexa number.
I've find a lot of solutions, but everything is different.
Any idea ?
The MIPS sub instruction subtracts two registers and stores the result in a register.sub $d,$s,$t means $d = $s - $t
sub = function code 34 (see manual), 22 in hex, 100010 in bin (6 bits)
$t0 = 8 in decimal, 8 in hex, 01000 in bin (5 bits)
$zero = 0 in decimal, 0 in hex, 00000 in bin (5 bits)
$t1 = 9 in decimal, 9 in hex, 01001 in bin (5 bits)
So the machine code for your instruction is 01001 01000 00000 100010
For R-format instructions, the opcode, or "operation code" is always zero. rs, rt, and rd correspond to the two source and one destination registers.
The source sub$t0,$zero,$t1 therefore translates to 0x00094022 in hexadecimal notation.
Explanation
Every MIPS instruction is 32bits and translates to a 32bits number that can be written as machine code in hexadecimal format.
The instruction sub (subtract) has opcode 0x22. Therefore the rightmost digits has to be 22 (see above that they are).
sub is an instruction type R. This means the R instructions are used when all the data values used by the instruction are located in registers.
All R-type instructions have the following format:
OP rd, rs, rt
Where "OP" is the mnemonic for the particular instruction (in this case sub). rs, and rt are the source registers, and rd is the destination register. In this case, the sub instruction is used as:
sub $t0, $zero, $t1
In other words, your instruction means "subtract t1 from 0 and put the result in t0".
If you want to swap the values of two registers you can do it as follows:
.text
.globl __start
__start:
sw $t0, x
sw $t1, y
lw $t0, y
lw $t1, x
.data
x:
.word 0x000000FF
y:
.word 0xABCDE080
If you want to put the content in $t0 also in $t1, you can use the or instruction:
lui $t0, 0x0123
or $t1, $zero, $t0

How can I check if a register is evenly divisible by 7?

I want to check if the value of the register ax is divisible by 7, with remainder = 0. How can I do it?
You can use the same way as shown in this answer, with different constants of course.
The modular multiplicative inverse of 7 mod 216 is 0x6db7, which (by definition) means that numbers of the form x = n * 7 will obey x * 0x6db7 = n, where n will be less than or equal to 0xffff / 7. So if you get something bigger out of x * 0x6db7, you know it's not a multiple of 7. Also, non-multiples of 7 cannot also map to low results, because multiplication by an odd number modulo a power of two is bijective.
So you can use (not tested)
imul ax, ax, 0x6db7
cmp ax, 0x2492
ja not_multiple_of_7
This is for unsigned numbers of course.
As a bonus, ax will be the original value divided by 7 iff it was a multiple of 7.
org 100h
mov ax,14
mov cl,7
div cl
cmp ah,0
je positive
PRINTN "The number has a remainder"
jmp finish
positive:
PRINTN "The number has no remainder"
finish:
PRINTN "After comparison"
mov ah, 0
int 16h
ret

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.

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