Looping in PIC 18F Assembler?

Thread Starter

spinnaker

Joined Oct 29, 2009
7,830
I am trying to learn assembler so I can incorporate a bit of assembler code in my C code.

I wrote a simple loop to loop through a 16bit word:

Rich (BB code):
unsigned int delay_ms= 10;

void main()
{
    

    _asm       loop:             decfsz delay_ms,1,1
                            goto loop
                            decfsz delay_ms+1,1,1
                            goto loop    
                                          
                              
                 _endasm
    
    while(1);

}
I quickly realized there is a flaw in my code. It works fine if delay_ms is 256 or greater but if it is 255 or less, the value in decfsz delay_ms+1 gets decremented to FF . How do I test if FF is zero before decrementing it?
 

thatoneguy

Joined Feb 19, 2009
6,359
you are only working on one byte, not both in the assembly routine. Check your compiler's help guide on accessing 16 bit variables through inline assembly (if supported).

Another option is it may be working fine, and the decrement is rolling over when the upper byte hits zero.
 

Markd77

Joined Sep 7, 2009
2,806
You probably want to a normal dec followed by checking the carry bit in STATUS.

<ed> This is just for the high byte. At the moment your loop will end at 0x0100 instead of 0x0000 </ed>
 
Last edited:

AlexR

Joined Jan 16, 2008
732
As the PIC 10/12/16/18 series of processors are 8 bit devices they don't have any instructions for dealing with 16 bit numbers so you will have to do it all yourself.

I have not tested the following code so it might fall down in a screaming heap but give it a go and see if it works. In any case it gives you the general idea.
Rich (BB code):
unsigned int delay_ms= 10;

void main()
{
    

    _asm     
        loop:       movf,  delay_ms, f        ;test low byte and set Z and N bit of status register
                    bz, hi_test               ;if low byte is zero check high byte
        low_dec:    decf, delay_ms, f         ;decrement low byte
                    goto loop                
        hi_test:    movf, delay_ms+1, f       ;test high byte
                    bz, finish                ;if both low and high bytes = 0 go to finish 
                    decf delay_ms+1, f        ;else decrement high byte
                    goto low_dec               ;jump back and decrement low byte so it rolls over to 0xFF
        finish:     _endasm
    
    while(1);
 
Last edited:
Top