gnupic: Thread: More nocturnal programming problems


[<<] [<] Page 1 of 1 [>] [>>]
Subject: More nocturnal programming problems
From: David Willmore ####@####.####
Date: 15 Mar 2004 10:20:44 +0000
Message-Id: <200403151013.i2FADHs5017304@localhost.localdomain>

Hello, again.

Same situation as before, sorry.

Can anyone enlighten me as to why:

msg_len		EQU	(message_end - message_start)

message_start:
	retlw	b'00000000'
 [... etc ...]
	retlw	b'11111111'
message_end:

Gives me a:
/usr/home/willmore/src/pic/test/10/test.asm:35:Error [116] Value of symbol "message_len" differs on second pass
 pass 1=0,  pass 2=125
Error code : 256

It seems that it's upset that when it first evaluates the
expression, it has no values for message_end and message_start,
so their difference is 0, but after having a longer look at
things, it decides that it's now 125.  This causes a bit of
confusion and an error.

Again, am I missing some common trick or am I expecting
the wrong things out of my tools?  i.e. pilot error or
pilot error. :)

Cheers,
David
Subject: Re: More nocturnal programming problems
From: Craig Franklin ####@####.####
Date: 16 Mar 2004 02:07:11 +0000
Message-Id: <1079402794.1454.11.camel@r2d2>

On Mon, 2004-03-15 at 04:13, David Willmore wrote:
> Hello, again.
> 
> Same situation as before, sorry.
> 
> Can anyone enlighten me as to why:
> 
> msg_len		EQU	(message_end - message_start)
> 
> message_start:
> 	retlw	b'00000000'
>  [... etc ...]
> 	retlw	b'11111111'
> message_end:
> 
> Gives me a:
> /usr/home/willmore/src/pic/test/10/test.asm:35:Error [116] Value of symbol "message_len" differs on second pass
>  pass 1=0,  pass 2=125
> Error code : 256
> 
> It seems that it's upset that when it first evaluates the
> expression, it has no values for message_end and message_start,
> so their difference is 0, but after having a longer look at
> things, it decides that it's now 125.  This causes a bit of
> confusion and an error.
> 
> Again, am I missing some common trick or am I expecting
> the wrong things out of my tools?  i.e. pilot error or
> pilot error. :)
> 

Symbols assigned a value using EQU can't be changed.  gpasm checks the
value on each pass to make sure they match.  On the first pass
message_end and message_start have a value of 0.  So msg_len has a value
of 0.  On second pass message_end is 125, so msg_len changes.

You can change to the SET directive or use a #define.  A few other
options exist. Pick the one that suits you best.  


> Cheers,
> David
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ####@####.####
> For additional commands, e-mail: ####@####.####
> 

Subject: Re: More nocturnal programming problems
From: "Paul B. Webster" ####@####.####
Date: 17 Mar 2004 11:59:01 +0000
Message-Id: <1079524721.3402.30378.camel@dads.webstermed>

On Wed, 2004-03-17 at 13:36, Craig Franklin wrote:

> gpasm does allow forward references to symbols, so this isn't always
> true.  It takes two passes of the source code.

  Oops!  That *is* what two-pass assemblers are about, of course.  I am
pontificating without, at this point, actually using the thing - in
fact, I am woefully out of practice - it shows, doesn't it?

  OK, it perhaps doesn't matter whether the code block itself is early
or late in the program as long as dependent variables (the "EQU" one)
follow after all variables upon whose actual value they depend.  Pass
one generates the symbol table defining the value of all the symbols,
which may then be used wherever referenced in pass two.

  Pass two actually resolves all the symbols again, but only to check
them against those already present in the symbol table, giving the error
specified if they disagree.

> Without seeing all of his source code, it is difficult to know which is
> best.

  As a general approach to string handling, the only matter of concern
is whether the "message" is binary or text.  Text data is almost
universally (FORTH excepted) stored in zero-terminated strings (as I
recall, MPASM provides for these,) because you only require a single
pointer to represent the string.  For binary strings, you require either
start and end(+1) pointers, or a pointer to the string which is itself
prefixed by a length descriptor (byte or word, depending on the maximum
length string to be permitted).

  There can be few exceptions to the rule that passing a single pointer
is more concise than passing two pointers because the code required to
load the second pointer for every call is always (much) more expensive
than either the terminator (null) word or the length prefix to the
corresponding string (especially where the string is used more than
once), and within the output subroutine, a test (branch) for zero or
iteration counter (DJNZ) is far more efficient than a comparison-for-end
procedure.

  Revisiting the code in question, if "message" is in fact binary and
strings limited to less than 256, we should be able to use:

message_start:
      retlw   msg_len-1
      retlw   b'00000000'
  [... etc ...]
      retlw   b'11111111'
 message_end:

 msg_len               EQU     (message_end - message_start)

  ... in conjunction with a subroutine that reads the first element into
the loop counter.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  My apologies - I had not noticed that this list works in a most
annoyingly non-standard fashion, and my reply went to Craig only!

On Wed, 2004-03-17 at 13:36, Craig Franklin wrote:

On Tue, 2004-03-16 at 06:34, Paul B. Webster wrote:

> On Tue, 2004-03-16 at 13:06, Craig Franklin wrote:
> 
> > Symbols assigned a value using EQU can't be changed.
> 
>   But really, that's not the most important thing.  What is important,
> is the concept of the "pass" - that message_start and message_end must
> be defined before *anything* that uses them.
> 
>   Your code then needs to read:
> 
> message_start:
>       retlw   b'00000000'
>   [... etc ...]
>       retlw   b'11111111'
> message_end:
> 
> msg_len               EQU     (message_end - message_start)
> 
>   ... and by the same token, whatever code uses msg_len, must follow
> after all three declarations.
> 

gpasm does allow forward references to symbols, so this isn't always
true.  It takes two passes of the source code.

>  In practice, this demands that your message blocks appear after the
> initial "start        jmp     begin" code, and before the subroutines
which
> reference them.
> 
>   Of course, most message print routines use a zero-terminated string
> anyway, because the code to detect the zero is vastly more concise
than
> code which requires two parameters (pointer and length) to call.
> 
>   Have I missed something?

Without seeing all of his source code, it is difficult to know which is
best.
-- 
  Cheers,
    Paul B.

Subject: Re: More nocturnal programming problems
From: David Willmore ####@####.####
Date: 17 Mar 2004 17:09:48 +0000
Message-Id: <200403171700.i2HH0NqX025665@localhost.localdomain>

> Paul wrote:
>   OK, it perhaps doesn't matter whether the code block itself is early
> or late in the program as long as dependent variables (the "EQU" one)
> follow after all variables upon whose actual value they depend.  Pass
> one generates the symbol table defining the value of all the symbols,
> which may then be used wherever referenced in pass two.
> 
>   Pass two actually resolves all the symbols again, but only to check
> them against those already present in the symbol table, giving the error
> specified if they disagree.

This would seem to preclude forward references.  If the symbol has no
value (is not defined) when it is used, then a later definition will
no propogate back?

> > Without seeing all of his source code, it is difficult to know which is
> > best.

It's no secret, it's just no complete and I couldn't see how any more than
what was shown was meaningful, sorry.  Shall I post it here?  It's still
not quite complete, so please pardon the mess. :)  Basically, before
that table, there is a little prolog that goes:
data_lookup:
	movwf	PCL_tmp
	movlw	LOW data_table	; load in the low byte of the table data start address
	addwf	PCL_tmp,f
	movlw	HIGH data_table	; load in the high byte of the table data start address
	btfsc	STATUS,C	; skip if carry clear
	addlw	1		; stuff in the carry bit
	movwf	PCLATH		; stick it in the high byte PC latch
	movf	PCL_tmp,w	; load in the PCL value
	movwf	PCL		; jump
data_table:
	; Char  1 'W'
	retlw   b'01111110'
	retlw   b'10000000'
	retlw   b'01111000'
...
data_end:

You set the index in w and call data_lookup.  Yeah, there's probably a
cleaner way to do this, but it handles tables up to 256 bytes and they
can straddle pages.  And, it wouldn't be all too hard to extend it to
being able to use all of memory.

The site using the EQU just runs a counter from 0 up until the length
define value -1.  (it's a modulo operation as the message is a scrolling
banner that loops forever).

>   As a general approach to string handling, the only matter of concern
> is whether the "message" is binary or text.  Text data is almost
> universally (FORTH excepted) stored in zero-terminated strings (as I
> recall, MPASM provides for these,) because you only require a single
> pointer to represent the string.  For binary strings, you require either
> start and end(+1) pointers, or a pointer to the string which is itself
> prefixed by a length descriptor (byte or word, depending on the maximum
> length string to be permitted).

For really specific strings, I just have a binary string and a programatic
constant for the length.  Call it 'none of the above'. :)  Maybe a pascal
string with a displaced length value?

>   There can be few exceptions to the rule that passing a single pointer
> is more concise than passing two pointers because the code required to
> load the second pointer for every call is always (much) more expensive
> than either the terminator (null) word or the length prefix to the
> corresponding string (especially where the string is used more than
> once), and within the output subroutine, a test (branch) for zero or
> iteration counter (DJNZ) is far more efficient than a comparison-for-end
> procedure.

What about addressing the buffer with the pointer % the length? :)

>   Revisiting the code in question, if "message" is in fact binary and
> strings limited to less than 256, we should be able to use:
> 
> message_start:
>       retlw   msg_len-1
>       retlw   b'00000000'
>   [... etc ...]
>       retlw   b'11111111'
>  message_end:
> 
>  msg_len               EQU     (message_end - message_start)
> 
>   ... in conjunction with a subroutine that reads the first element into
> the loop counter.

Which precludes using the length as a literal value--now it has to be in a
memory location or register.  For embeddid (i.e. tiny) processors that can
count precious bytes.

> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
>   My apologies - I had not noticed that this list works in a most
> annoyingly non-standard fashion, and my reply went to Craig only!

That's a religious argument for another day! ;)


Thanks for the advice. 

Cheers,
David
Subject: Re: More nocturnal programming problems
From: David Willmore ####@####.####
Date: 18 Mar 2004 22:59:52 +0000
Message-Id: <200403182259.i2IMxA0t030814@localhost.localdomain>

> > msg_len		EQU	(message_end - message_start)
> 
> Symbols assigned a value using EQU can't be changed.  gpasm checks the
> value on each pass to make sure they match.  On the first pass
> message_end and message_start have a value of 0.  So msg_len has a value
> of 0.  On second pass message_end is 125, so msg_len changes.
> 
> You can change to the SET directive or use a #define.  A few other
> options exist. Pick the one that suits you best.  

VARIABLE	msg_len=(message_end - message_start)

works perfectly.  I tried SET, but it requires the variable to be
defined first, so why not put the value in the VARIABLE statement
in the first place?  I looked at the opcodes produced and they've
got the right value in them (sublw msg_len comes out as 0x3C7D
and the msg_len is 125 or 0x7D).

Thanks, Craig and everyone else.  Does the list take attachements?
If so, I'll post a version of the code for everyones enjoyment. :)

Cheers,
David
[<<] [<] Page 1 of 1 [>] [>>]


Powered by ezmlm-browse 0.20.