Link to home
Start Free TrialLog in
Avatar of psi3000
psi3000

asked on

Assembly Language division without using DIV HELP

I have a homework assignment that I understand the theory behind but do not know how to write it in assembly.  The program must perform integer division that the user inputs, without using DIV.
It must use this alogorithm:
const int MAX_REPS =8;
for (int reps=1; resp <=MAX_REPS; reps++)
{
   if (Product (LSB) == 1)
         Add multiplicand to the left half of the product and place the result in the left half of the Product register;
   Shift the Product register right 1 bit;
}

The dividend and the divisor must be positive and smaller than 65,535.  All inputs are to be validated with a reprompt occurring when there is illegal input.  The program is to prompt for and validate a dividend and a divisor and then display the quotient and the remainder.

This is an extra part I need to do for this assignment:
Allow the user to enter both positive and negative numbers.  You can choose to half the ranges as is done with the Integer type variable in a high level language, or you can choose to keep the same ranges, just allow negatives as well as positives.  It must indicate the range by displaying it at the beginning of the program, so the user can know what test valuses to use.


I know the basic therory of multiplying by 1/10 and then shifting the register, I just dont know how to do it in assembly.  And I have no idea how to do the second part.  Please help
ASKER CERTIFIED SOLUTION
Avatar of Andre_Tertling
Andre_Tertling
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The problem with the approach that gabeso mentioned is that integer divisions will basically always end up as DIV a,b opcodes. I can't think of any compiler switch that would keep the compiler from using the built-in DIV instruction - DIV has been available for ages on the x86 platform and it is always faster than a discrete implementation, even if you unroll the loop used in the pseudo-code posted by psi3000.
Nonetheless, the approach itself is valid for more complex algorithms, just not when the task is to re-implement a CPU opcode :)
Avatar of psi3000
psi3000

ASKER

Yeh, I just have no idea on how to begin this program.
Here is what I have:
.model small
.stack 100h
.data
      msg1 db "Enter dividend":
      msg2 db "Enter divisor":
      msg3 db "Illegal integer":
      msg4 db "END OF DATA":
      msg5 db "Richard Pulliam CSC242, Section 01 assignment 3":
      strHeader db 10
.code
main proc
      mov dx, offset msg5
      mov dx, offset msg1
      mov ah,9
      int 21h
      jb error      ;sends user to error subroutine if over 65536
      mov dx, offset strHeader
      mov al,0AH      ;moves string/dividend into al
      int 21h
      mov dx, offset msg2
      mov ah,9
      int 21h
      jb error
      mov dx, offset strHeader
      mov ch,0AH      ;moves string/divisor into ch
      int 21
      mov bh,ch
nextIteration:             ;called within the loop while bh is 2 or over
      shr al,1      ;shifts al to the right one dividing al by 2
      sub bh,2      ;subtracting 2 from bh
      add cl,1      ;adding 1 to ch to keep track of our product
      cmp bh,1      ;compairing bh to 1 to send to one subroutine
      jmp one            ;jump if bh equals 1
      cmp bh,2      ;compairing bh to 2
      jae nextIteration      ;jumping to nextIteration if bh is equal to or above 2
      offset cl      ;displaying product which is in cl
      mov ah,9
      int21
      jmp done      ;exiting program

error:            ;subroutine called when input throws jb flag to make sure input is not over the 65536 barrier
      mov dx, offset msg3

one:            ;subroutine called when bh is equal to one
      sub al,ch      ;subtracting ch since it is our original divisor because we can only divide by 2
      offset cl
      mov ah,9
      int21

done:      
      mov dx, offset msg4

exit

Ok this is what I have does it look ok.  Does it make sence. i dont even know how I came up with it. Could be completely wrong.  But hopfully someone can show me what I am doing wrong and can understand by it what I want to do.
thanks guys
Avatar of psi3000

ASKER

Ok I found some errors while compiling. Here is my new program:
.model small
.stack 100h
.data
      msg1 db "Enter dividend":
      msg2 db "Enter divisor":
      msg3 db "Illegal integer":
      msg4 db "END OF DATA":
      msg5 db "Richard Pulliam CSC242, Section 01 assignment 3":
      strHeader db 10
.code
main proc
      mov dx, offset msg5
      mov ah,9
      int 21h
      mov dx, offset msg1
      mov ah,9
      int 21h
      jb error      ;sends user to error subroutine if over 65536
      mov dx, offset strHeader
      mov al,0AH      ;moves string/dividend into al
      int 21h
      mov dx, offset msg2
      mov ah,9
      int 21h
      jb error
      mov dx, offset strHeader
      mov ch,0AH      ;moves string/divisor into ch
      int 21
      mov bh,ch
nextIteration:             ;called within the loop while bh is 2 or over
      shr al,1      ;shifts al to the right one dividing al by 2
      sub bh,2      ;subtracting 2 from bh
      add cl,1      ;adding 1 to ch to keep track of our product
      cmp bh,1      ;compairing bh to 1 to send to one subroutine
      jmp one            ;jump if bh equals 1
      cmp bh,2      ;compairing bh to 2
      jae nextIteration      ;jumping to nextIteration if bh is equal to or above 2
      mov dx, offset cl      ;displaying product which is in cl
      jmp done      ;exiting program

error:            ;subroutine called when input throws jb flag to make sure input is not over the 65536 barrier
      mov dx, offset msg3
      mov ah,9
      int 21h

one:            ;subroutine called when bh is equal to one
      sub al,ch      ;subtracting ch since it is our original divisor because we can only divide by 2
      mov d, offset cl


done:      
      mov dx, offset msg4


end main

I have an compiling error it says : "fatal error A1010: unmatched block nesting : main" can anyone help with this as well.
thanks
The copy and paste was incomplete but apart from that... "I don't even know how I came up with it" smells like google plus copy & paste ;) This can prove to be a dangerous thing sometimes ;) You should at least understand what you copy and paste :)

But back to the code. I have a couple of hints for you:

- bl, bh, cl, ch are 8-bit registers. You are dealing with numbers up to 65535, does that ring a bell? If so, what changes are required in the code?
- The beginning of main proc lacks some instructions right at the beginning. Do you know which ones?
Okay, your post and mine overlapped so clear for next round :)

You found the missing text output, but you messed up with the text input. I recommend consulting Ralf Brown's interrupt list for requirements for your int21 calls. And you should pay attention to which registers are set to what values for particular functions.
Here is a great HTML version of that interrupt list: http://www.ctyme.com/rbrown.htm

Looking at Int21h/AX=000Ah says you need to prepare the buffer with some data before calling that function. I am sure you can add the necessary code to your program without my help ;)

Then the end of your main routine (see labels done, one, error) looks a bit bad to me. To terminate your DOS program, you have to call the proper DOS function. You can find it in the interrupt list as well.

The code after the label "error" should terminate the program too, so that it can't proceed with the instructions following the labels "one" and "done".

The code after "one" looks suspicious, too. What exactly should it do?

About the compiling error you get: which assembler do you use?
Oh, one thing: Try to enter a number over 65535, you'll notice that it doesn't complain about it. Do you see why?
Avatar of psi3000

ASKER

Ok first of all, no, this is not a copy and paste from any place at all.  I came up with this on my own, I promise you that. And I used ML, does that sound familar, or MASM?  I have no idea what you are talking about with that HTML, there is just a bunch of links to interupt lists.  Which one do I need?  And how did you get it to work if you entered a number over the 65535 barrier? I cant even get mine to compile still
About the interrupt list: You're already using functions from interrupt 21h, so you may have figured that it would make sense to look at the other functions offered by that interrupt. First things first, let's solve that compilation error.

PROC and END don't match, if you start a block of code with PROC you need to end it with ENDP. But in your sample problem there is just one procedure, the main one so just leave out PROC :)

Then, understand what you are doing at all. You are using Int21h/AX=000Ah to collect user input. This function needs a pointer to a reserved and prepared buffer for input. The "bunch of links to interrupt lists" can be used to find out what's missing to prepare the buffer properly. Otherwise your program will do all kinds of crazy stuff including crashes and spontaneous reboots. Trust me, I've been there :)

And of course, checking for the value of the input is absolutely senseless if you check it before you even process it.

Last but not least for this post: Think about what you get when you read input from the user byte by byte. Correct, you'll get a string. You have to convert it to a number before you can use it for calculations...