Searching \ for '[PIC] Beginner assembler questions concerning loop' 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/begin.htm?key=pic
Search entire site for: 'Beginner assembler questions concerning loop'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] Beginner assembler questions concerning loop'
2007\01\25@211241 by Balthasar Indermuehle

picon face
Hi all,

I'm a newcomer to assembler (in general, despite having been a high level
language programmer for 15 years) and I have a bit of a confusion going on
with MPLab's assembler: All "useful" conditional expressions and loop
statements appear to be some sort of preprocessor directive which then gets
translated further by MPLab, but are not "direct" machine code calls. the
"while" statement is a good example: MPLab expands a while statement to a
flat piece of code, very long, and very big. Not efficient at all (space
wise that is).

What are the "pure" assembler ways of writing a conditional branch and while
statement for the PIC? For simplicity's sake, can someone show me (or
comment on my attempt)? Is this the proper way of doing things or am I
completely off? Thanks for your patience with a noob like me...

1. a while loop:

Pseudo code:
while x > y {
   do something
   decrement x
}


my attempt at translating this, for x = 255 and y = 32

   movlw 0xff        ; put 255 into w
   movwf x            ; put 255 into x
   movlw 0x20       ; put 32 into w
   movwf y            ; put 32 into y

WhileLoop
   movfw x            ; put x into w
   movwf diff          ; put w into diff (diff = x)
   movfw y            ; put y into w
   subwf diff            ; subtract w from x (diff = x - y)
   decfsz diff        ; decrement diff, skip if 0
   goto EndWhile
   addwf diff           ; add w back to diff (to obtain original X, but
decremented by one)
   movfw diff        ; put diff into w
   movwf x           ; put w back into x
   
   do something

   goto WhileLoop
EndWhile

Accordingly, if the loop is to execute while x >= y, y would need to be
decremented by one initially. Correct?

2. an IF statement:

Pseudo code:
if (x > y) {
   do something
}

my attempt:
Not the slightest clue how this might be done! Possibly need to use ANDWF to
compare for equalness? But how do you implement > and <...? subtract and
check for carry flag (i.e. whether result is negative)?

Thanks a bunch!

- Balt

2007\01\25@230827 by John Chung

picon face

--- Balthasar Indermuehle <spam_OUTbindermuehleTakeThisOuTspamgmail.com>
wrote:

{Quote hidden}

 Depends on the situation. As long as x is greater or
equal to the the value y. Decrement is a way to ensure
that the loop end when x is 0x20

> 2. an IF statement:
>  
> Pseudo code:
> if (x > y) {
>     do something
> }
>  

 do the same as above but this time add an extra line
after subwf, which is sublw 0x1. Check for Zero again.
Work it out on paper and you will get it.


John

{Quote hidden}

> --

2007\01\25@233659 by Balthasar Indermuehle

picon face
> > 2. an IF statement:
> >  
> > Pseudo code:
> > if (x > y) {
> >     do something
> > }
> >  
>
>   do the same as above but this time add an extra line
> after subwf, which is sublw 0x1. Check for Zero again.
> Work it out on paper and you will get it.
>
>

Thanks John,

So an if statement essentially has to loop through? Is there no bit wise
operator that lets me figure out which value of two is larger?

I'm new to the bit-level way of thinking as you can see...

Cheers

- Balt

2007\01\26@015006 by John Chung

picon face

--- Balthasar Indermuehle <.....bindermuehleKILLspamspam@spam@gmail.com>
wrote:

{Quote hidden}

 Correct me if I am wrong but basic NOT AND and XOR
can building all sort of gates which ultimately can
build comparators. But what you want is whether the
bitwise operator can do comparison when they are equal
which lives in the instruction set. Unfortunately
subwf is a better alternative for you to determine
whether it is greater or not. Here is a macro that
uses the subwf

;macro                  movff
;args                  arg1 - file register,src
;                          arg2 - file register,dest
;comment          move the contents from arg1 to arg2
;results          now arg2 has arg1
movff        macro arg1,arg2
       movfw arg1
       movwf arg2
endm


;macro                  cmp16ff
;args                  arg1 - addr of file register,16 bits
;                          arg2 - addr of the file register,16 bits
;                          arg3 - tmp value
;comment          compares arg1 and arg2
;results          arg1>arg2 -set C ,arg1==arg2 set
Z,arg2>arg1 unset C
cmp16ff        macro arg1,arg2,arg3
       movfw arg2
       subwf arg1
       movwf arg3

       btfsc STATUS,Z
       goto next_byte

       btfss STATUS,C
       goto end_cmp16ff


next_byte
       movlf arg2,FSR
       incf FSR
       movff INDF,arg3
       movlf arg1,FSR
       incf FSR
       movfw arg3
       subwf INDF
       goto end_cmp16ff

end_cmp16ff

endm

John


> I'm new to the bit-level way of thinking as you can
> see...
>
> Cheers
>
> - Balt
>
> --

2007\01\26@044104 by Alan B. Pearce

face picon face
>Is there no bit wise operator that lets me
>figure out which value of two is larger?

Have a look at the macros included with Olins development environment at
http://www.embedinc.com/pic/ which has a nice list of more understandable
macros for comparing than the Microsoft ones. Also get the PDF file from
Jan-Erik that describes the various macros in Olins file. The link to the
file is in Olins pages.

Do be careful though, as there is a set of macros that are used for other
compares of multiple byte numbers which are not the ones you want.

2007\01\26@052446 by Michael Rigby-Jones

picon face


{Quote hidden}

This is because these statments are not designed for use as operational constructs within your code, they are pre-processor directives to simplify some assembly tasks that would otherwise be tedious, e.g. the while is used to insert a block of code a number of times into your program.


{Quote hidden}

When you have a compare at the start of a loop like this, it's usualy more efficienct to physicaly place it at the end of the loop and then jump to the compare when you first enter the loop.  Something like this:

   goto    compare
loop_start
   ; do something here
   decf    x
compare
   movf    x,w
   subwf   y,w
   skpc        ; MPASM built in macro equivalent to 'btfss OPTION_REG,C'
   goto    loop_start


{Quote hidden}

This is exactly the same construct as used in the while loop, but without the decrement and goto

   movf    x,w
   subwf   y,w
   skpnc   ; equivalanet to btfsc OPTION_REG,C
   goto    do_nothing
       ; do something here
do_nothing


The tricky part in these examples is understanding how the subwf instruction affects the status bits.  I'd suggest you keep a copy of midrange reference manual handy to refer to.

Regards

Mike

=======================================================================
This e-mail is intended for the person it is addressed to only. The
information contained in it may be confidential and/or protected by
law. If you are not the intended recipient of this message, you must
not make any use of this information, or copy or show it to any
person. Please contact us immediately to tell us that you have
received this e-mail, and return the original to us. Any use,
forwarding, printing or copying of this message is strictly prohibited.
No part of this message can be considered a request for goods or
services.
=======================================================================

2007\01\26@063939 by Alan B. Pearce

face picon face
>    skpnc   ; equivalanet to btfsc OPTION_REG,C
...

>The tricky part in these examples is understanding how the
>subwf instruction affects the status bits.  I'd suggest
>you keep a copy of midrange reference manual handy to refer to.

This is where Olin has some macros that help, in the form of skip_wle and
skip_wgt (or they might be skip_wlt and skip_wge) when dealing with adds and
subtracts in w. They assemble to the same code as the Microchip macros.
Still need to have the manual handy, but when looking over the code again
these are more explanatory.

2007\01\26@074241 by John La Rooy

flavicon
face
 Correct me if I am wrong but basic NOT AND and XOR

> can building all sort of gates which ultimately can
> build comparators.


Inversion is the key. NAND and NOR gates can be combined to
make AND and OR gates, but there is no way to construct NAND
or NOR gates from only AND and OR :)

2007\01\26@111429 by Jan-Erik Söderholm

face picon face
Also note that the PIC18-series has an expanded set of
"greater then"/"lower then"/"equal" comparisions.

On the PIC16-series the subtract operations seems to be
the most common way to solve that.

Jan-Erik.

Alan B. Pearce skrev:
{Quote hidden}

2007\01\26@122026 by William Chops Westfield

face picon face
On Jan 26, 2007, at 8:14 AM, Jan-Erik Söderholm wrote:

> On the PIC16-series the subtract operations seems to be
> the most common way to solve that.
>
Perhaps a step backwards...

At the assembly level, most conditional flow on most CPUs is
accomplished by using using conditional branch instructions that
operate based on "status flags" or a "status register" that is
updated by certain ALU operations.  Typically there is a bit
to indicate that the result is zero, a bit that duplicates the
sign bit of the result, and a bit to indicate the output of the
hardware carry logic out of the MSB of the ALU.  If you look at
the hardware that implements an ALU, these bits typically represent
signals generated as side effects of doing math, so all that is
needed is to store them for a bit.

For math comparisons ("if A < B") one usually uses a subtraction
operation in the ALU.  Many CPUs have a "compare" instruction that
has the ALU do a subtraction but does not store any result EXCEPT
for the flags.  For bit checking, you usually want an AND operation
in the ALU, and most CPUs have a "test" instruction that will do the
AND without store results other than the flags.

So in a "generic" sense, to implement something like
       while (A < B) {
          A = A+1;
    }
you use, in assembly, code that looks like

whileloop:
         compute A-B
    if carryflag goto endwhile  /* A > B */
    if zeroflag goto endwhile   /* A = B */
      increment A
         goto whileloop
endwhile:

The tricky part is doing the computation without trashing variables
that you don't want to trash, and figuring out which combinations of
status bits reflect which mathematical results.  For example, the PIC16
doesn't have the compare instruction, so you have to do a real subtract
and throw away the result explicitly, and it sets the carry flag to
the opposite of many other CPUs, and it doesn't do conditional branches
so much as conditional SKIPs, so the above example becomes more like:

whileloop:
       temp = A - B
    skip if ZERO NOT set in status
           goto endwhile   /* A = B */
    skip if CARRY set in status
           goto endwhile  /* A > B */
    increment A
    goto whileloop
endwhile:

(I may still have the carry check wrong.)

Many instruction sets, or assemblers, or macro packages will define
mnemonics that go with "normal" math expressions, more like:
whileloop:
   compare A,B
   jumpge endwhile  /* ge means Greater or Equal */

In addition, there are frequently special instructions to accomplish
"common" conditional execution scenarios.  The PIC can test any single
bit in any register and skip if set or clear without having to do an
AND operation (which would require the "W" register.)  It also has
increment or decrement and test if zero (in a single instruction,
for any register.)  The Z80 had conditional CALL instructions that
matched the conditional jumps.  The PDP-10 had "add one to both halves
and jump if negative" and "test the right half of the word, compliment
the tested bits, and skip if they were originally all zeros" and other
abominations ("flip-flops and bit drops and TRCE's in triples"; Google
knows.)  A skip-based architecture like the PIC lets you fit a single
instruction that doesn't HAVE to be a branch in a test, which can make
for tight code.  Sometimes.  Not ALL instructions modify the flags,
and part of the assembly programer's task is to keep track of all that
in an optimal way...

Is that helpful?

BillW


 

2007\01\26@122807 by John Chung

picon face
Thanks for the correction. I always forget inversion
is the key. Any good tips in remembering such critical
stuff for digital electronics.

Thanks
John


--- John La Rooy <EraseMEpiclist.jlrspam_OUTspamTakeThisOuTlarooy.com> wrote:

{Quote hidden}

> --

2007\01\26@141735 by Brooke Clarke

flavicon
face
Hi Balt:

I think you are confusing "assembler directives" with program code.  To
learn what program code a particular family of uCs supports see it's
data sheet and the family data sheet.  The part number data sheet has a
short description of the commands for that part and the family data
sheet has more details on each of the commands.  The good thing about a
Harvard architecture is that there are a small number of commands (35 in
the case of the mid range PICs).  When figuring out how to do somehing
it's good to review all the commands.

Have Fun,

Brooke Clarke

--
w/Java http://www.PRC68.com
w/o Java www.pacificsites.com/~brooke/PRC68COM.shtml
http://www.precisionclock.com

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