Searching \ for '[PIC] PIC16F 690 Assembler Question' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=16F
Search entire site for: 'PIC16F 690 Assembler Question'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] PIC16F 690 Assembler Question'
2008\12\18@010937 by solarwind

picon face
In the LPC demo board examples, this is ho they are defining a delay loop:

Note: W has been loaded with 0xFF beforehand.

; Delay Function.  Enter with number 771uS delays in Wreg
Delay:
    movwf     Delay2         ;
DelayLoop:
    decfsz    Delay1,f       ; Waste time.
    goto      DelayLoop      ; The Inner loop takes 3 instructions
per loop * 256 loopss = 768 instructions
    decfsz    Delay2,f       ; The outer loop takes and additional 3
instructions per lap * 256 loops
    goto      DelayLoop      ; (768+3) * 256 = 197376 instructions /
1M instructions per second = 0.197 sec.
                             ; call it a two-tenths of a second.
    return


I am interested in that code right under the "Delay:" label.

1. What would the default value of a variable be when declared in the cblock?
2. So I'm assuming Delay2 is getting loaded with 0xFF and counting
down. So what about Delay1? There is no setting of Delay1's value in
the code. How is it going to decrement Delay1 if a default value has
not been set? Is there just some random data in there? Isn't that poor
programming practice? What's going on here...
3. In my own delay loop, I've defined as follows:

Delay:
       movlw   0x00
       movwf   delay1
       movwf   delay2
DelayLoop:
       decfsz  delay1, 1
       goto    DelayLoop                        ; The inner loop takes 3 instructions per loop *
256 loops = 768 instructions
       decfsz  delay2, 1                        ; The outer loop takes and additional 3
instructions per lap * 256 loops
       goto    DelayLoop                        ; (768+3) * 256 = 197376 instructions / 1M
instructions per second (@ 4 MHz) = 0.197 sec.

       return

Note that I move 0x00 into delay1 and delay2 variables. This is not
making a difference whether I'm loading 0x00 or 0xFF. What's going on?

I'm assuming that, by loading the two variables with 0xFF, I'm
preparing them for a countdown. And by making them zero, it will skip
the loop... But it's not...


--
..::[ solarwind ]::..

2008\12\18@011412 by solarwind

picon face
Update: I noticed that loading up values like 0x2F does make a
difference but I still don't understand why loading up 0x00 and 0xFF
seem to be the same and I still don't understand why the example code
is only loading up delay2 variable and not touching delay1...

I tried reading the data sheet, even went through all the
instructions, but it's still not clear to me...

2008\12\18@011701 by solarwind

picon face
Here's my code to show that I'm trying to learn:

#include <p16F690.inc>
   __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_ON
& _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_ON & _IESO_OFF)

cblock 0x20
       display
       delay1
       delay2
endc
       org 0

Start:
       bsf     STATUS, RP0                        ; Select register page 1

       movlw   0x00                                ; Ports are all output
       movwf   TRISA
       movwf   TRISB
       movwf   TRISC

       bcf     STATUS, RP0                        ; Select register page 0

Loop:
       movlw   0xFF                                ; PORTC is high
       movwf   PORTC
       call    Delay

       movlw   0x00                                ; PORTC is off
       movwf   PORTC
       call    Delay

       goto    Loop                                ; Repeat

       goto    $                                        ; Hang
       

Delay:
       movlw   0x1F
       movwf   delay1
       movwf   delay2
DelayLoop:
       decfsz  delay1, 1
       goto    DelayLoop                        ; The inner loop takes 3 instructions per loop *
256 loops = 768 instructions
       decfsz  delay2, 1                        ; The outer loop takes and additional 3
instructions per lap * 256 loops
       goto    DelayLoop                        ; (768+3) * 256 = 197376 instructions / 1M
instructions per second (@ 4 MHz) = 0.197 sec.

       return

       end

Also added some comments, added some configuration options and
formatted neatly as possible.

2008\12\18@011852 by solarwind

picon face
Pastebin because it looks ugly in email: http://pastebin.com/f39fb1a4e

2008\12\18@012644 by Mark Rages

face picon face
On Thu, Dec 18, 2008 at 12:09 AM, solarwind <spam_OUTx.solarwind.xTakeThisOuTspamgmail.com> wrote:
>
> Delay:
>        movlw   0x00
>        movwf   delay1
>        movwf   delay2
> DelayLoop:
>        decfsz  delay1, 1
>        goto    DelayLoop                       ; The inner loop takes 3 instructions per loop *
> 256 loops = 768 instructions
>        decfsz  delay2, 1                       ; The outer loop takes and additional 3
> instructions per lap * 256 loops
>        goto    DelayLoop                       ; (768+3) * 256 = 197376 instructions / 1M
> instructions per second (@ 4 MHz) = 0.197 sec.
>
>        return
>
> Note that I move 0x00 into delay1 and delay2 variables. This is not
> making a difference whether I'm loading 0x00 or 0xFF. What's going on?
>

Read carefully about "decfsz" in the instruction set.  Try loading 0x01.

About initialization, what is the value of delay1 and delay2 when the
loop exits?

Regards,
Mark
markrages@gmail
--
Mark Rages, Engineer
Midwest Telecine LLC
.....markragesKILLspamspam@spam@midwesttelecine.com

2008\12\18@013412 by solarwind

picon face
part 1 520 bytes content-type:text/plain; charset=GB2312 (decoded quoted-printable)

Syntax: [ label ] DECFSZ f,d
Operands: 0 f 127
d [0,1]
Operation: (f) - 1 (destination);
skip if result = 0
Status Affected: None
Description: The contents of register 'f' are
decremented. If 'd' is '0', the result
is placed in the W register. If 'd' is
'1', the result is placed back in
register 'f'.
If the result is '1', the next
instruction is executed. If the
result is '0', then a NOP is
executed instead, making

This is all it says... I don't get it.



part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2008\12\18@013707 by William \Chops\ Westfield

face picon face

On Dec 17, 2008, at 10:09 PM, solarwind wrote:

> 2. So I'm assuming Delay2 is getting loaded with 0xFF and counting
> down. So what about Delay1? There is no setting of Delay1's value in
> the code. How is it going to decrement Delay1 if a default value has
> not been set? Is there just some random data in there? Isn't that poor
> programming practice? What's going on here...

Delay1 is assumed to contain zero because that's where the code leaves  
it from the previous loop (exits inner loop with decfsz, so at the  
exit, delay1 == 0.)
Probably cblock variables initialize to zero as well, but it doesn't  
really matter after the very first time the Delay function is called.  
(if delay1 has random contents, the first execution of Delay could be  
off by "almost" one 768 instruction "inner tick", the equivalent of  
being off-by-one in the initial count contained in W:
> ; Delay Function.  Enter with number 771uS delays in Wreg

BillW


2008\12\18@014917 by Matthew Mucker

flavicon
face
{Quote hidden}

There are two loops here, one nested inside the other.  The inner loop
counts down Delay1, the outer loop counts down Delay2. The w register is
used to set Delay2, the value for the outer loop.

Now, the first time through the loop, Delay1 looks (from the code you've
posted) to be uninitialized, and I'd agree that yes, this is bad programming
practice.  (Assuming you've copied all of the relevant code; it's possible
that Delay1 was initialized somewhere else.  Have you stepped through the
code in the simulator to see what's happening?)

However... once the inner loop has completed the first time, and the code
gets to the decfsz Delay2 instruction, what is the value of Delay1?  When
the outer loop iterates back to the top, and the inner loop is executed for
the second time, Delay1 still has that value, so in actuality, Delay1 *is*
initialized for the second (and subsequent) time through the inner loop.

I encourage you to step through the code in the simulator and watch what
happens to each of these values as each instruction is executed. The
simulator makes it easy to see what values are changed by highlighting any
changed values in red when each instruction is simulated.


2008\12\18@015053 by solarwind

picon face
On Thu, Dec 18, 2008 at 1:36 AM, William Chops Westfield <westfwspamKILLspammac.com> wrote:
> Delay1 is assumed to contain zero because that's where the code leaves
> it from the previous loop (exits inner loop with decfsz, so at the
> exit, delay1 == 0.)
> Probably cblock variables initialize to zero as well, but it doesn't
> really matter after the very first time the Delay function is called.
> (if delay1 has random contents, the first execution of Delay could be
> off by "almost" one 768 instruction "inner tick", the equivalent of
> being off-by-one in the initial count contained in W:
>> ; Delay Function.  Enter with number 771uS delays in Wreg
>
> BillW

So my question is, how does it decrement from 0?

--
..::[ solarwind ]::..

2008\12\18@020613 by solarwind

picon face
Good idea, I'll step through it.

2008\12\18@030853 by William \Chops\ Westfield

face picon face

On Dec 17, 2008, at 10:50 PM, solarwind wrote:

> So my question is, how does it decrement from 0?

Decrement 0, and you get 0xFF (which is -1 if you're doing 2's  
complement, or 255 if you're unsigned, but the hardware gives you the  
same result either way.)

BillW

2008\12\18@031327 by Jinx

face picon face
part 1 1489 bytes content-type:text/plain; charset=gb2312 (decoded quoted-printable)

> Syntax: [ label ] DECFSZ f,d
> Operands: 0 f 127
> d [0,1]
> Operation: (f) - 1 (destination);
> skip if result = 0
> Status Affected: None
> Description: The contents of register 'f' are
> decremented. If 'd' is '0', the result
> is placed in the W register. If 'd' is
> '1', the result is placed back in
> register 'f'.
> If the result is '1', the next
> instruction is executed. If the
> result is '0', then a NOP is
> executed instead, making

> This is all it says... I don't get it

"my" pdf concludes with

..... it a two-cycle instruction

There are two destinations for many instructions. eg an example
using the register TEMP

If TEMP = 0x72

DECFSZ TEMP,1 ; results in TEMP = 0x71
DECFSZ TEMP,0 ; results in TEMP still = 0x72 and W = 0x71

It is common, more readable and considerate to use F for 1 and W for 0, ie

DECFSZ TEMP,F (or simply DECFSZ TEMP)
DECFSZ TEMP,W

If you had this code, and TEMP = 2

DECFSZ TEMP,F ;decrement TEMP, now TEMP = 1, so do not skip
                                ;the next instruction
GOTO ROUTINE ;program jumps to ROUTINE
BSF LED     ;and the LED is lit

Repeating, with TEMP now = 1

DECFSZ TEMP,F ;decrement TEMP, now TEMP = 0, so skip
                                ;the next instruction
GOTO ROUTINE ;this is skipped
BSF LED     ;and the LED is lit

> So my question is, how does it decrement from 0?

To 0xFF




part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2008\12\18@031736 by Jinx

face picon face
Grrr, that'll teach me to Copy/Paste

I wrote

DECFSZ TEMP,F ;decrement TEMP, now TEMP = 1, so do not skip
                                ;the next instruction
GOTO ROUTINE ;program jumps to ROUTINE
BSF LED     ;and the LED is lit

LED is *** NOT *** lit, BSF is not executed unitl TEMP = 0



2008\12\18@041922 by Tamas Rudnai

face picon face
> So my question is, how does it decrement from 0?

Think if decfsz was written in C:

// the variable defined as:  unsigned char delay1;
if (--delay1)
  <instruction>  // skip this instruction if the delay1 becomes 0...

This is that simple is that. I think it is a good practise to understand how
to read that instruction set details in DataSheet as it saves you time in
the feature.

Tamas



On Thu, Dec 18, 2008 at 6:50 AM, solarwind <.....x.solarwind.xKILLspamspam.....gmail.com> wrote:

{Quote hidden}

> -

2008\12\18@072805 by olin piclist

face picon face
solarwind wrote:
> DelayLoop:
>     decfsz    Delay1,f       ; Waste time.
>     goto      DelayLoop      ; The Inner loop takes 3 instructions

Start by thinking about what just these two instructions do.  The DECFSZ
will decrement DELAY1 by one (assuming the bank is set correctly), and skip
the GOTO when DELAY1 reaches 0.  So the initial value in DELAY1 sets how
many times the GOTO will be executed and the loop repeated - 1.

To really see how this kind of code works, run it on the simulator.

> 1. What would the default value of a variable be when declared in the
> cblock?

Variables aren't declared in CBLOCKs.  CBLOCK is for defining sets of
constants with sequential values, sortof like ENUMs in C.  Only RES defines
variables.

> 2. So I'm assuming Delay2 is getting loaded with 0xFF and counting
> down. So what about Delay1? There is no setting of Delay1's value in
> the code. How is it going to decrement Delay1 if a default value has
> not been set? Is there just some random data in there? Isn't that poor
> programming practice? What's going on here...

If the outer loop is run many times, then not initializing DELAY1 will only
make the time of the first inner loop uncertain the first time the routine
is run.  Maybe whoever wrote this didn't care about that level of accuracy,
but I agree it's sloppy programming.  If you don't initialize DELAY1 for a
reason, there should be a comment saying so.

The code you showed also totally disregarded the bank setting without any
comment explaining that the bank must be set by the caller or that the
variables are in the access bank.  More sloppy programming.

{Quote hidden}

At least build your code and run it on the simulator before asking about it
here.  If you had, you would have gotten lots of warnings and maybe errors
from the assembler.  Labels start in column 1 and opcodes in column 2 or
greater.

Fix the code, run it on the simulator, then come back if you still have any
questions about it.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@072957 by olin piclist

face picon face
solarwind wrote:
> Update: I noticed that loading up values like 0x2F does make a
> difference but I still don't understand why loading up 0x00 and 0xFF
> seem to be the same and I still don't understand why the example code
> is only loading up delay2 variable and not touching delay1...

Note that DELAY1 is left as 0 after the inner loop completes.  Therefore it
will be initialized on all but the first time the inner loop is run.

> I tried reading the data sheet, even went through all the
> instructions, but it's still not clear to me...

What specifically are you unclear about?


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@073341 by olin piclist

face picon face
solarwind wrote:
> cblock 0x20
> display
> delay1
> delay2
> endc

Never ever try to define variables this way.  Only RES (REServe) allocates
memory for variables.  I know there is a lot of ancient absolute mode code
out there that does this, but that doesn't make it right.  Most examples out
there suck, including many from Microchip.

> org 0

Never ever use ORG.  That is a left over from the archaic absolute mode.
Use CODE instead.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@073748 by olin piclist

face picon face
William Chops" Westfield" wrote:
> Probably cblock variables initialize to zero as well,

Argh!  Don't you start doing this too.  First, CBLOCK doesn't create
variables.  Second, RAM is not initialized on power up.  General RAM is all
undefined at power up.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@075436 by olin piclist

face picon face
solarwind wrote:
> So my question is, how does it decrement from 0?

That is a good question for someone not familiar with the binary
representation of numbers and how binary arithmetic is performed.  Most
micrcontroller references, including the PIC data sheets, are written
assuming you already understand this.

I haven't looked, but I expect there are a lot of basic binary math
descriptions out there.  Now that you know what you're looking for, it
should be easy to find material that explains this in detail.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@085209 by Bob Ammerman

picon face
part 1 2884 bytes content-type:text/plain; format=flowed; charset="gb2312"; reply-type=original (decoded quoted-printable)




> Syntax: [ label ] DECFSZ f,d

A description of how to write the instruction. An optional label, followed by the instruction mnemonic "DECFZ", followed by two operands, one called 'f' and the other called 'd'. So, then what are 'f' and 'd'? Read on...

> Operands: 0 f 127

Ok, 'f' is a value in the range 0 through 127, inclusive. What this means is that there is a 7-bit long field in the instruction to hold this value. If you read the introductory material before the actual instruction descriptions, you'll find out that 'f' is really the (low-order 7 bits of) the address of a memory location or special function register (an aside: the high order bits of the address are elsewhere and *MUST* be properly set before the DECFZ instruction is executed, see BANKSEL for some details, also see RP0 and RP1 bits int the STATUS register).

> d [0,1]

Oh, and 'd' is either a 0 or 1 (as physically encoded in the instruction). But what does that mean? Again, the introductory information before the actual instructions tells you that 'd' determines whether the result of the instruction goes back into the register specified by 'f', or else goes into the "W" register. When writing the instruction you specify either the letter F (to have the result go back into the register specified by 'f') or W (to have the result go back into the W register).

> Operation: (f) - 1 (destination);

(f) means: get the value of whatever is in the memory location or special function register pointed to be the address 'f' (and the RP0/RP1 bits in STATUS).

-1 means: subtract one from that value

(destination) means store the resulting value either back info the register pointed to be 'f' (when d is the letter F) or into the W register (when d is the letter W)

> skip if result = 0

This means if the result of the decrement is zero, then the next instruction is skipped, otherwise it is executed.

> Status Affected: None

This means that none of the bits in the STATUS register are affected by this instruction. (ie: the C (carry) and Z (zero) bits (and other bits) in the status register are not changed)




Perhaps an explanation of the use of the instruction in context will help:


   movlw    10.        ; number of iterations of loop
   movwf    COUNTER    ; save it in a memory location
loop_start:
   <instructions that need to execute 10. times go here>
   decfsz   COUNTER,F  ; subtract one from COUNTER, skip next instruction when we get to zero
   goto     loop_start ; go thru the loop again
   <instruction following the loop go here>

Note that the 'goto loop_start' instruction will be skipped the tenth time the 'decfsz COUNTER,F' is executed. This will result in the loop executing exactly 10 times.



hope this helps,

-- Bob Ammerman
RAm Systems



part 2 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2008\12\18@162146 by solarwind

picon face
On Thu, Dec 18, 2008 at 7:35 AM, Olin Lathrop <olin_piclistspamspam_OUTembedinc.com> wrote:
> solarwind wrote:
>> cblock 0x20
>> display
>> delay1
>> delay2
>> endc
>
> Never ever try to define variables this way.  Only RES (REServe) allocates
> memory for variables.  I know there is a lot of ancient absolute mode code
> out there that does this, but that doesn't make it right.  Most examples out
> there suck, including many from Microchip.
>
>> org 0
>
> Never ever use ORG.  That is a left over from the archaic absolute mode.
> Use CODE instead.


Can you give a short example on how to use that (CODE and RES)? I
searched it up but got nothing useful...


--
solarwind

2008\12\18@165236 by Jan-Erik Soderholm

face picon face
solarwind wrote:

> Can you give a short example on how to use that (CODE and RES)? I
> searched it up but got nothing useful...

The MPASM online help in MPLAB (and I'm sure also in
the MPASM PDF manual) has some examples.

Or did you ment that you *did* find them but you
didn't find them useful ?


2008\12\18@165852 by solarwind

picon face
No, I searched on the internet and couldn't find anything.

--
solarwind

2008\12\18@170220 by Richard Seriani, Sr.

picon face

----- Original Message -----
From: "solarwind" <@spam@x.solarwind.xKILLspamspamgmail.com>
To: "Microcontroller discussion list - Public." <KILLspampiclistKILLspamspammit.edu>
Sent: Thursday, December 18, 2008 4:21 PM
Subject: Re: [PIC] PIC16F 690 Assembler Question


{Quote hidden}

Check out lesson #16 for a quick intro to relocatable code:
http://www.amqrp.org/elmer160/lessons/

Good luck,
Richard


2008\12\18@172039 by Jan-Erik Soderholm

face picon face
solarwind wrote:

> No, I searched on the internet and couldn't find anything.
>

Why on earth did you do that ?
Why not simply look in the documentation ?

2008\12\18@172612 by olin piclist

face picon face
solarwind wrote:
> Can you give a short example on how to use that (CODE and RES)? I
> searched it up but got nothing useful...

Here is a contrived example:

        udata               ;don't care what bank these go in
myvar    res     1           ;my very own variable


mymod   code                ;code for my module
        ...
        banksel myvar       ;set bank for access to my variable
        rlf     myvar, w    ;get value x 2
        andlw   b'11111110' ;mask off garbage bit shifted in
        addwf   myvar, w    ;add another 1x
        movwf   myvar       ;update with triple original value


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\12\18@180841 by solarwind

picon face
On Thu, Dec 18, 2008 at 5:02 PM, Richard Seriani, Sr.
<spamBeGonerichard_s633spamBeGonespamcox.net> wrote:
> Check out lesson #16 for a quick intro to relocatable code:
> http://www.amqrp.org/elmer160/lessons/
>
> Good luck,
> Richard

Thanks for the site!



--
solarwind

More... (looser matching)
- Last day of these posts
- In 2008 , 2009 only
- Today
- New search...