PIC Division (multiplication of inverse)

Thread Starter

Pencil

Joined Dec 8, 2009
272
Hello all,

I haven't been experimenting with microcontrollers very long (<1 year).

I have attached a snippet of code (assembly) for dividing a 16 bit number
by an 8 bit number. Details are in the comments.

I would appreciate it greatly if anyone, more experienced, would look/test for errors.

All comments (good and bad) welcome.

Thanks.

Rich (BB code):
;**********************************************************************
;TEST FOR PIC16F690                                                   *
;DIVISION ROUTINE (MULTIPLICATION OF INVERSE OF DIVISOR)              *
;                                                                     *
;16 BIT DIVIDEND (XXXXXXXX XXXXXXXX)                                  *
;8 BIT INVERSE OF DIVISOR (1/DIVISOR)(.XXXXXXXX)                      *
;                                                                     *
;RESULT IS 16 BITS TO THE LEFT OF DECIMAL POINT, 8 BITS TO RIGHT      *
;OF THE DECIMAL POINT                                                 *
;                                                                     *
;RESULT FORMAT XXXXXXXX   XXXXXXXX   .XXXXXXXX                        *
;             HIGH BYTE   LOW BYTE   DECIMAL BYTE                     *
;                                                                     *
;INPUTS:                                                              *
;DVDHI=HIGH BYTE OF DIVIDEND                                          *
;DVDLO=LOW BYTE OF DIVIDEND                                           *
;DVSR=1/DIVISOR                                                       *
;                                                                     *
;OUTPUTS:                                                             *
;HIRSLT=HIGH BYTE OF RESULT                                           *
;LORSLT=LOW BYTE OF RESULT                                            *
;HIDEC=DECIMAL HIGH BYTE OF RESULT                                    *
;                                                                     *
;PRESERVES ORIGINAL VALUES OF DIVIDEND AND DIVISOR                    *
;                                                                     *
;                                                                     *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Filename:        xxx.asm                                         *
;    Date:                                                            *
;    File Version:                                                    *
;                                                                     *
;    Author:                                                          *
;    Company:                                                         *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P16F690.INC                                      *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;**********************************************************************


    list        p=16f690        ; list directive to define processor
    #include    <P16F690.inc>        ; processor specific variable definitions
    
    __CONFIG    _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF


; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.



main


    ;GENERAL PURPOSE VARIABLE ADDRESSES
;*************DIVISION ROUTINE VARIABLES*************
CNTR1   EQU   0x34    ;GENERAL PURPOSE COUNTER
CNTR2   EQU   0x35    ;GENERAL PURPOSE COUNTER
DVDHI   EQU   0x41    ;DIVIDEND HIGH BYTE XXXXXXXX xxxxxxxx
DVDLO   EQU   0x42    ;DIVIDEND LOW BYTE  xxxxxxxx XXXXXXXX
DVSR    EQU   0x43    ;DIVISOR (1/DIVISOR) .XXXXXXXX
HIRSLT  EQU   0x44    ;RESULT HIGH BYTE   XXXXXXXX xxxxxxxx
LORSLT  EQU   0x45    ;RESULT LOW BYTE    xxxxxxxx XXXXXXXX
HIDEC   EQU   0x46    ;RESULT DECIMAL PORTION xxxxxxxx xxxxxxxx.XXXXXXXX
HITEMP  EQU   0x47    ;TEMP HIGH BYTE     XXXXXXXX xxxxxxxx
LOTEMP  EQU   0x48    ;TEMP LOW BYTE      xxxxxxxx XXXXXXXX
DVRTMP  EQU   0x49    ;TEMP DIVISOR .XXXXXXXX
HDECTMP EQU   0x50    ;TEMP DECIMAL PORTION xxxxxxxx xxxxxxxx.XXXX
;***************************************************
   ;****INITIALIZE DIVISION ROUTINE VARIABLES****
    CLRF   CNTR1      ;0000 0000 INITIALIZE CNTR1
    CLRF   CNTR2      ;0000 0000 INITIALIZE CNTR2
    CLRF   DVDHI      ;0000 0000 INITIALIZE DVDHI
    CLRF   DVDLO      ;0000 0000 INITIALIZE DVDLO
    CLRF   HIRSLT     ;0000 0000 INITIALIZE HIRSLT
    CLRF   LORSLT     ;0000 0000 INITIALIZE LORSLT
    CLRF   HITEMP     ;0000 0000 INITIALIZE HITEMP
    CLRF   LOTEMP     ;0000 0000 INITIALIZE LOTEMP
    CLRF   HIDEC      ;0000 0000 INITIALIZE HIDEC
    CLRF   DVSR       ;0000 0000 INITIALIZE DVSR
    CLRF   DVRTMP     ;0000 0000 INITIALIZE DVRTEMP
    CLRF   HDECTMP    ;0000 0000 INITIALIZE HDECTMP
;***************************************************


;***********DIVISION ROUTINE***********

   ;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
   ;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
    MOVLW   0xFF      ;DIVIDEND HIGH BYTE XXXX XXXX 
    MOVWF   DVDHI     ;DVDHI=XXXX XXXX

    MOVLW   0xFF      ;DIVIDEND LOW BYTE XXXX XXXX
    MOVWF   DVDLO     ;DVDLO=XXXX XXXX

    MOVLW   0x01      ;1/DIVISOR .XXXX XXXX
    MOVWF   DVSR      ;DVSR=.XXXX XXXX
   ;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***
   ;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***

;*****BEGINNING OF DIVISION ROUTINE**** 
    MOVF    DVDHI,W   ;DVDHI TO W
    MOVWF   HITEMP    ;HITEMP=DVDHI
    MOVF    DVDLO,W   ;DVDHI TO W
    MOVWF   LOTEMP    ;LOTEMP=DVDLO
    MOVF    DVSR,W    ;DVSR TO W
    MOVWF   DVRTMP    ;DVRTMP=DVSR
    MOVLW   0x00      ;0000 0000
    MOVWF   HDECTMP   ;HDECTMP=0
    MOVLW   0x08      ;0000 1000 (8)
    MOVWF   CNTR1     ;CNTR1=8
    MOVLW   0x00      ;0000 0000
    MOVWF   CNTR2     ;CNTR2=0

  ;TEST BIT 7 OF DVRTMP
    BCF     STATUS,C
    INCF    CNTR2,F   ;BIT TEST COUNTER
    BTFSS   DVRTMP,7  ;TEST BIT 7 OF DVRTEMP
    GOTO    DIVIDECNTR
    GOTO    DIVIDE1

   ;SHIFT AND ADD DIVIDEND
DIVIDE1
    BCF     STATUS,C
    RRF     HITEMP,F   ;ROTATE RIGHT HITEMP
    RRF     LOTEMP,F   ;ROTATE RIGHT LOTEMP
    RRF     HDECTMP,F  ;ROTATE RIGHT HDECTMP
    BCF     STATUS,C
    DECF    CNTR2,F    ;BIT TEST COUNTER -1
    MOVF    CNTR2,F    ;TESTING COUNTER FOR =0
    BTFSS   STATUS,Z   ;IF INCREMENTAL SHIFTS NOT =O
    GOTO    DIVIDE1    ;ROTATE AGAIN
    MOVF    HDECTMP,W  ;HIDECTMP SAVED TO W
    ADDWF   HIDEC,F    ;ADD HDECTMP TO HIDEC
    BTFSS   STATUS,C   ;TEST FOR CARRY OF HIDEC
    GOTO    $+5        ;IF NO CARRY
    MOVLW   0x01
    ADDWF   LORSLT,F   ;IF HIDEC CARRIED ADD 1 TO LORSLT
    BTFSC   STATUS,C   ;TEST FOR CARRY OF LORSLT
    INCF    HIRSLT,F   ;IF LORSLT CARRIED ADD 1 TO HIRSLT
    MOVF    LOTEMP,W   
    ADDWF   LORSLT,F   ;ADD LOTEMP TO LORSLT
    BTFSC   STATUS,C   ;TEST FOR CARRY OF LORSLT
    INCF    HIRSLT,F   ;IF LORSLT CARRIED ADD 1 TO HIRSLT  
    MOVF    HITEMP,W
    ADDWF   HIRSLT,F   ;ADD HITEMP TO HIRSLT
    CLRF    CNTR2      ;CLEAR CNTR2
    GOTO    DIVIDECNTR ;SHIFT AND TEST DIVISOR AGAIN

   ;MANAGE COUNTERS, SHIFT DIVISOR, TEST DIVISOR BITS 
DIVIDECNTR
    BCF     STATUS,C
    BCF     STATUS,Z
    DECF    CNTR1,F   ;-1 TOTAL SHIFTS COUNTER
    MOVF    CNTR1,F   ;TESTING COUNTER FOR =0   
    BTFSC   STATUS,Z  ;CHECK FOR 8 TOTAL SHIFTS
    GOTO    $+6       ;IF ALL BITS OF DIVISOR HAVE BEEN TESTED THEN EXIT
    RLF     DVRTMP,F  ;ROTATE LEFT FOR TESTING NEXT BIT
    INCF    CNTR2,F   ;+1 BIT TEST COUNTER
    BTFSS   DVRTMP,7  ;TEST BIT 7 OF DVRTEMP 
    GOTO    $-7       ;IF BIT 7 IS 0 SHIFT AND TEST AGAIN 
    GOTO    DIVIDE1   ;IF BIT 7 IS 1 SHIFT AND ADD DIVIDEND
 
    NOP               ;TEMPORARY EXIT POINT
    GOTO    $-1       ;ENDLESS LOOP
;*******END OF DIVISION ROUTINE******* 

;********************************
BOTTOM
    ORG    0x2100                ; data EEPROM location
    DE    1,2,3,4                ; define first four EEPROM locations as 1, 2, 3, and 4
    END                       ; directive 'end of program'
 

THE_RB

Joined Feb 11, 2008
5,438
Sorry I haven't checked your code, but I wanted to suggest that you look at the microchip appnotes. They have a number of appnotes full of math examples in PIC assembler, that you can just cut and paste into your code. 16bit/8bit and 16bit/16bit division are very standard.
 

Thread Starter

Pencil

Joined Dec 8, 2009
272
I wanted to suggest that you look at the microchip appnotes. They have a number of appnotes full of math examples in PIC assembler, that you can just cut and paste into your code. 16bit/8bit and 16bit/16bit division are very standard.
Thanks for replying.

I am aware of the appnotes and other examples on the internet. I am trying
to get a better understanding of the basics for myself. At this point I feel
I should develop some basic routines "from the ground up". If I get into
the habit of copying and pasting this early in my learning I won't progress
as I feel I should. I am also afraid that if I am learning on my own, isolated
from outside input, I may teach myself some some bad habits or faulty logic.
 

MrChips

Joined Oct 2, 2009
30,708
I agree with you. You would do yourself a big favor if you refrained from copying other people's code. Personally I think your code looks a mess. But then I think PIC MCU design sucks - just my opinion. I could not make out a single thing about your code but this is not your fault, just the design of PIC asm. I could solve the same problem in HC11, HC08 or AVR with a lot simpler code. (If you want to learn good asm design, my advice would be to switch away from PIC - but I am sure a whole bunch of AAC members are going to jump on me for this - so spare me the agony, please.)

Before you attempt to tackle a problem like 16x8 or 16x16 multiply or divide and posting the code you should (or must) write out your algorithm. You can do this using a flowchart or pseudo code. I would suggest you begin here and I will guide you along the way.
Pseudo code should be MCU independent and should not refer to any hardware aspects (such as registers) of the MCU. Use plain algebra.

(I would also suggest going through this exercise first with 8x8 multiply, 16x8 multiply and 16x16 multiply just to get the hang of it.)
 
Last edited:

ErnieM

Joined Apr 24, 2011
8,377
It is always a good thing to write your own code for well defined problems such as this as it is a good learning tool. (It's also good to write code for new applications, they both teach you good things).

1. I have no clear idea what you mean by:

Rich (BB code):
    DVSR    EQU   0x43    ;DIVISOR (1/DIVISOR)         .XXXXXXXX
Is this the "traditional" divisor or it's inverse? I suspect you mean the former but I hate to guess.

2. Using code such as:

Rich (BB code):
    GOTO    $+5        ;IF NO CARRY
seems a willful act to purposely obfuscate the code. Use a label if you intend to have other people read the code.
 

Thread Starter

Pencil

Joined Dec 8, 2009
272
I realize how hard it is to read other peoples code. This is why it took
me a long time before getting brave enough to post. This is also the
reason I asked so I could learn how to get help.

Before you attempt to tackle a problem like 16x8 or 16x16 multiply or divide and posting the code you should (or must) write out your algorithm. You can do this using a flowchart or pseudo code. I would suggest you begin here and I will guide you along the way.
Pseudo code should be MCU independent and should not refer to any hardware aspects (such as registers) of the MCU. Use plain algebra.
Before writing the code I always work out the routine and work examples,
step by step, on paper. I will have to make something to post. My normal
notes to myself only make sense to me, as you can probably see in my
code. Learning to communicate ideas is something I'm working on.

1. I have no clear idea what you mean by:

Rich (BB code):
    DVSR    EQU   0x43    ;DIVISOR (1/DIVISOR)          .XXXXXXXX
Is this the "traditional" divisor or it's inverse? I suspect you mean the former but I hate to guess.
Edit: That is assigning the variable DVSR to the register address 0x43.
Maybe you meant to copy from elsewhere in the program? I think I get
the point about not knowing what to enter for the value of DVSR that
would be from here:
Rich (BB code):
   ;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
   ;***ENTER DIVIDEND AND 1/DIVISOR BELOW HERE***
    MOVLW   0xFF      ;DIVIDEND HIGH BYTE XXXX XXXX 
    MOVWF   DVDHI     ;DVDHI=XXXX XXXX

    MOVLW   0xFF      ;DIVIDEND LOW BYTE XXXX XXXX
    MOVWF   DVDLO     ;DVDLO=XXXX XXXX

    MOVLW   0x01      ;1/DIVISOR .XXXX XXXX
    MOVWF   DVSR      ;DVSR=.XXXX XXXX
   ;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***
   ;***ENTER DIVIDEND AND 1/DIVISOR ABOVE HERE***
The inverse of the divisor should be used. I was converting
the inverse of the divisor to fractional binary on paper then substituting
that value on the "MOVLW" line above the "MOVWF DVSR" line.
The code I posted was for testing purposes, the real usage of the code
will carry the value of DVSR to the subroutine for the calculation.

2. Using code such as:

Rich (BB code):
    GOTO    $+5        ;IF NO CARRY
seems a willful act to purposely obfuscate the code. Use a label if you intend to have other people read the code.
I assure you it is not my intent to confuse. It is just poor coding. I
believe I understand the use of labels, I will use labels instead of the
"GOTO $±x" whenever possible. Thanks for the tip.

Yes. I know of many references. Studying examples is all I have used
so far. I intend to get a book at some point. Keep the references
coming, there may be some I haven't seen.

Thanks for the help so far. I'll re-post another try with the advice given.
 
Last edited:

atferrari

Joined Jan 6, 2004
4,764
Reading others' code is a hard thing to do, at least for me. I feel much more inclined to look at your flow diagram than trying to understand your code.

Since my start, many years ago, I got used to write a flow diagram of what I want to do, so, later, I can code simply by following it.
 

THE_RB

Joined Feb 11, 2008
5,438
...
I am aware of the appnotes and other examples on the internet. I am trying
to get a better understanding of the basics for myself. At this point I feel
I should develop some basic routines "from the ground up".
...
I respect that attitude totally. But I would liek to say that the Microchip math routines appnotes are not really "pasting someone else's code" they are an official tool that has been refined by the Microchip professionals, and contain not just the code but good commenting, and text notes with analysis of what is happening.

As a learning tool they are VERY much worth looking at.
A quick google brought up AN526 and AN617, both have division routines that should act as good examples. :)

http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011000
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en010962
 

Thread Starter

Pencil

Joined Dec 8, 2009
272

Thread Starter

Pencil

Joined Dec 8, 2009
272
I'm really struggling with getting something in words/symbols
for a flow diagram/algorithm.

The best I can do for now is post an example showing how I initially
mapped out the routine in order to see the logic.

I'm still working on some sort of flow diagram.

Can the logic behind the code be seen in this example?
Is the logic sound?

Rich (BB code):
Example of process used for multiplication
of whole number and decimal in binary


Example:  5*.59375

Multiplicand=5
Multiplier=.59375

Convert multiplicand to binary format:    5=101
Convert multiplier to binary format :   .59375=.10011

Expanded representation of multiplier:  .10011=.1+.0001+.00001

Distributive property of multiplication and substitution makes the following true:
         101*.10011=(101*.1)+(101*.0001)+(101*.00001)

Equalities using bit shifting right technique:
         (101*.1)=101 shifted right 1 time =10.1
         (101*.0001)=101 shifted right 4 times =.0101
         (101*.00001)=101 shifted right 5 times =.00101

Substituting values from bit shifting yields:
         101*.10011=10.1+.0101+.00101

Solution of right hand side of equation:
         10.1+.0101+.00101=10.11111   (in base 10:  2.5+.3125+.15625=2.96875)

Conclusion by substitution:
         101*.1011=10.11111   (in base 10:  5*.59375=2.96875)
Does this help at all?
I feel like a caveman trying to communicate with a mathematician.:eek:
 

MrChips

Joined Oct 2, 2009
30,708
Here is how I would explain multiplication.

Let us see how this is done in decimal.
Suppose you wish to multiply 1234 x 789
There are two approaches:

A)

We could start with the least significant digit of the multiplier, 1234 x 9, save this result.
Then we take 1234 and shift left one place, multiply by 8 and add to previous result.
Then we take 12340 and shift left one place, multiply by 7 and add to previous result.

B)

We start with 1234, multiply by 7, and shift left by one place.
We multiply 1234 by 8, add to result and shift left by one place.
We multiply 1234 by 9, and add to previous result.

For a binary multiplication, we may choose either approach. Let us choose (B).

1. Begin with result = 0.
2. Take the multiplicand and multiply with the MSB of the multiplier. Add to result.
3. Is this the last bit of the multiplier? If yes, done.
4. Shift the result one bit to the left. Shift the multiplier one bit to the left.
5. Go to Step 2.
 

Markd77

Joined Sep 7, 2009
2,806
I haven't looked at how the code functions, but here are a few tips:
You will probably find declaring variables easier using the cblock method (google it). It saves typing and avoids accidentally declaring 2 files as the same register or leaving gaps in the registers (like 0x36-0x40 and 0x49-0x50).
Using a loop and the FSR to clear variables saves a little code space - example code is in the datasheet in the indirect addressing section. Clearing them directly is faster.
Use clrf foo instead of movlw 0x00, movwf foo.
There are a few times where bcf STATUS, C is not needed.
There is no need to do decf foo, F, movf foo, F because decf already changes the zero flag.
They are pretty small changes, but it all adds up.
 

Eric007

Joined Aug 5, 2011
1,158
But then I think PIC MCU design sucks - just my opinion......just the design of PIC asm.
I totaly disagree with you!!! But I respect your opinion...
It all about coming up with a good algorithm to solve this kind of problem then the implementation can be done with PIC, AVR, wateva...

my advice would be to switch away from PIC - but I am sure a whole bunch of AAC members are going to jump on me for this - so spare me the agony, please.)
Hahahahah...lolol you already know...
Before you attempt to tackle a problem like 16x8 or 16x16 multiply or divide and posting the code you should (or must) write out your algorithm. You can do this using a flowchart or pseudo code. I would suggest you begin here and I will guide you along the way.
Pseudo code should be MCU independent and should not refer to any hardware aspects (such as registers) of the MCU. Use plain algebra.
Totally agree!!
 

Thread Starter

Pencil

Joined Dec 8, 2009
272
Here is how I would explain multiplication.....
Thanks for the examples, I am working my my way toward a
thorough explanation. I realize the importance of this step.

I haven't looked at how the code functions, but here are a few tips:
You will probably find declaring variables easier using the cblock method (google it).
I am aware of c-block method, I need to start using it, it would help
to "clean things up a little".
Using a loop and the FSR to clear variables saves a little code space - example code is in the datasheet in the indirect addressing section. Clearing them directly is faster.
I'll look for an example.
There are a few times where bcf STATUS, C is not needed.
When I'm not sure I tend to err on side of caution.
There is no need to do decf foo, F, movf foo, F because decf already changes the zero flag.
I thought i had trouble with the counters. During debugging I tried
"testing for zero" a different way to make sure I understood. I should
have changed back (eliminated the movf foo,F) but didn't.
The real problem turned out to be "inc foo,F" doesn't affect Status C.
They are pretty small changes, but it all adds up.
Great dialog (all posters) . Any advice helps me by making me rethink
the way I approach the problem.
 
Last edited:

Thread Starter

Pencil

Joined Dec 8, 2009
272
This still is not really the algorithm, but more of a
"program summation in words". Can anybody see
faulty logic/process yet? I am working my way through this
whole process backwards:D.

Remember the original questions were,
"Is this a valid, error free routine?"
and "Will it produce accurate results throughout the
entire range for which it was intended?"

Note: This is intended to be used as a guide for
checking the code (way back in post 1). Any errors
may be in either place or both. (As a way of checking
myself I tried to write this independant of the program
and compare the two. I wanted to see it as anyone
else would.)
Rich (BB code):
Program flow for division routine

Purpose:  To calculate division of a 16 bit whole number dividend by an 8 bit
                  divisor.

Limitations: Variable registers are 8 bits wide.

Inputs:  16 bit dividend is entered into 2 registers as a "high byte" and a "low byte".
              Divisor is inverted (1/Divisor) and converted to "decimal binary" (.XXXXXXXX)
              and entered into a single register.

Outputs: 16 bit result is stored in 3 registers as a "high byte" and a "low byte" and
                1 register as a "decimal byte".
 
Routine begins below here.
                  
1. Enter dividend (whole number) in registers Dividend high byte and Dividend Low byte
2. Enter inverse of divisor (1/divisor) in register Divisor

3.  Set Result high byte to 0
4.  Set Result low byte to 0
5.  Set Result decimal byte to 0
6.  Set Temporary decimal byte to 0

7.  Set total bit test counter to 8
8.  Set interim bit test counter to 0

 (***Test Bit 7 Of Divisor***)

9.    Decrement total bit test counter (-1)
10.  Is bit 7 of Divisor =1?
            NO...goto step 22.
            Yes...continue.

 (***Shift and add dividend***)

11. Shift Dividend high byte to right (through Carry bit).
12. Shift Dividend low byte to right (through Carry bit).
13. Shift Temporary decimal byte to right.
14. Decrement interim bit test counter (-1).
15.  Is interim bit test counter=0?
            NO...goto step 11.
            Yes...continue.
16. Add Temporary decimal byte to Result  decimal byte.
17. Did Result decimal byte carry?
            Yes...add 1 to Result low byte then goto step 19.
             No...goto step19.
18. Did Result low byte carry?
            Yes...add 1 to Result high byte then goto step 19.
             No...continue.
19. Add Dividend low byte to Result low byte.
20. Did Result low byte carry?
            Yes...add 1 to Result high byte then goto step 21.
             No...continue.
21. Add Dividend high byte to Result high byte.

 (***Mange Counters, Shift Divisor, Test Divisor Bits***)

22. Decrement total bit test counter (-1).
23. Is total bit test counter =0.
             Yes...goto step 27 (computation complete).
              No...continue.
24. Shift Divisor byte to left.
25. Increment interim bit test counter (+1).
26. Is bit 7 of Multiplier =1?
             No...goto step 22.
             Yes...goto step 11.
27.  End
As always thanks.
 
Last edited:

MrChips

Joined Oct 2, 2009
30,708
I have not read your post but something you must be aware of: Hardware design such as block diagrams and timing diagrams must not be drawn after the design has been completed.

Similarly, software algorithms must not be written out after the code has been written. This is putting the carriage before the horse. Algorithms must dictate how the code is to be written. Not the other way around. If the algorithm does not make sense to begin with, the code would be a hopeless failure.

(I'll look at the post once the eggnog wears off.)

In the exercises, we begin with 8x8 multiply and divide, keeping things as simple as possible.
When we extend this to 16-bit operations we have to accept that things become more complex because we have to deal with multiple-byte operations.
In order to keep the algorithm simple to follow, we assume that multiple-byte operations are single operations. This way we treat high-byte and low-byte as a single entity. This reduces the number of steps in the algorithm and makes it easier to follow.

There is another reason for doing it this way. The 8-bit limitation is specific to that type of MCU. When we move to 16-bit and 32-bit processors the algorithm can remain the same.
 
Last edited:
Top