Shop OBEX P1 Docs P2 Docs Learn Events
Warning - BST don't warn if you use labels from another DAT section!!! — Parallax Forums

Warning - BST don't warn if you use labels from another DAT section!!!

pik33pik33 Posts: 2,397
edited 2012-06-06 17:58 in Propeller 1
... and I wasted some hours to find it...
dat
(some pasm code)

linenum long 0

dat
(some pasm code for another cog)

     mov linenum, #0

(rest of code)


It should generate a compile error - or warning - unresolved "linenum" symbol in second DAT section.

Instead it compiled it and then.... my program started to behave very strange... didn't know, why until I found this bug.

I don't know if Propeller Tool do the same, but warning: you have to check twice if you don't use symbols from one pasm section in another one...

Comments

  • Heater.Heater. Posts: 21,230
    edited 2012-06-06 04:42
    Why should the be a warning? It does what it is advertised to do. Assemble all your DAT sections into a single DAT area for that object. All reference resolved correctly.

    The compiler knows nothing of your intention that different DAT sections may be run in a different cogs.

    Try compiling an object with multiple interspersed DAT and PUB sections with the listing option switched on. You will see in the listing that all the DAT code gets placed into a single DAT area for the object in RAM.
  • pik33pik33 Posts: 2,397
    edited 2012-06-06 05:01
    These are two different dat modules for two different cogs. Something unknown was calculated and placed there. Some cog register was set to zero with this line of code. I don't even know, what the compiler put in place of "linenum".. it doesn't exist in this cog's space.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-06 05:48
    What do you mean "two different DAT modules for two different cogs"?
    You can have multiple DAT sections in a Spin object source file. They will be assembled and concatenated into a single DAT area in RAM for that object. So the end result is the same as if you had put them in a single DAT section.

    Let's take this as an example:
    PUB junk
       moreJunk
    
    
    DAT
    
    
    label_1 long 1
    label_2 long 2
    label_3 long 3
    
    
    PUB moreJunk
        evenMoreJunk
        repeat
    
    
    DAT
        mov label_1, label_2
    
    
    PUB evenMoreJunk
        repeat
    
    
    DAT
        mov label_2, label_1
        jmp #label_3
    

    Let's compile that and see what is in the listing file:
    |===========================================================================|
    Objects : -
    Untitled1
    
    
    Object Address : 0010 : Object Name : Untitled1
    
    
    Binary Image Information :
    PBASE : 0010
    VBASE : 0048
    DBASE : 0050
    PCURR : 0038
    DCURR : 0054
    |===========================================================================|
    |===========================================================================|
    Object Untitled1
    Object Base is 0010
    |===========================================================================|
    Object Constants
    |===========================================================================|
    |===========================================================================|
    Object DAT Blocks
    |===========================================================================|
    0020(0000) 01 00 00 00 | label_1 long 1
    0024(0001) 02 00 00 00 | label_2 long 2
    0028(0002) 03 00 00 00 | label_3 long 3
    002C(0003) 01 00 BC A0 |     mov label_1, label_2
    0030(0004) 00 02 BC A0 |     mov label_2, label_1
    0034(0005) 02 00 7C 5C |     jmp #label_3
    |===========================================================================|
    |===========================================================================|
    Spin Block junk with 0 Parameters and 0 Extra Stack Longs. Method 1
    PUB junk
    
    
    Local Parameter DBASE:0000 - Result
    |===========================================================================|
    2                         moreJunk
    Addr : 0038:             01  : Drop Anchor   
    Addr : 0039:          05 02  : Call Sub 2    
    Addr : 003B:             32  : Return        
    |===========================================================================|
    Spin Block moreJunk with 0 Parameters and 0 Extra Stack Longs. Method 2
    PUB moreJunk
    
    
    Local Parameter DBASE:0000 - Result
    |===========================================================================|
    11                          evenMoreJunk
    Addr : 003C:             01  : Drop Anchor   
    Addr : 003D:          05 03  : Call Sub 3    
    Addr : 003F: Label0004
    Addr : 003F: Label0005
    Addr : 003F: JMP Label0004
    Addr : 003F:          04 7E  : Jmp 003F -2   
    Addr : 0041: Label0006
    Addr : 0041:             32  : Return        
    |===========================================================================|
    Spin Block evenMoreJunk with 0 Parameters and 0 Extra Stack Longs. Method 3
    PUB evenMoreJunk
    
    
    Local Parameter DBASE:0000 - Result
    |===========================================================================|
    18                          repeat
    Addr : 0042: Label0004
    Addr : 0042: Label0005
    Addr : 0042: JMP Label0004
    Addr : 0042:          04 7E  : Jmp 0042 -2   
    Addr : 0044: Label0006
    Addr : 0044:             32  : Return        
    


    Here we see all DAT sections pulled together into a single area of RAM space, under "Object DAT Blocks". Everything is just fine.

    As I said, the complier has no idea that you are going to launch different parts of that DAT blob into different COGs. It just compiles it into a single runnable thing.

    Now, iy you are wanting multiple DAT blocks to be run in different cogs I would sugget:
    1) Put them into different source files. You will have a lot less trouble with such label naming mix ups that way.
    2) or besure to put "ORG 0" statements at the beginning of each DAT block that is to be run separately in different cogs. That way the linker can do it's thing properly. Each cogs section will be compiled to be run from offset zero in a cog rather than whatever would normally come next.
    3) For completeness use FIT at the end of a cogs piece of code.
  • pik33pik33 Posts: 2,397
    edited 2012-06-06 06:04
    There is org 0 at start of each of these dat blocks.

    I discovered earlier that labels have to be unique in all piece of .spin file, but I thought it should generate an error, when it finds a label before this org 0 - in previous cog's code.

    How did you generate this listing in second code block?
  • Heater.Heater. Posts: 21,230
    edited 2012-06-06 06:14
    In BST under the "view" menu there is the "Compiler Listing" option. Turn that on and recompile. You will then get a new window displaying the listing.

    Thing is "org 0" does not say "this a new piece of PASM that will be run in a different cog" it only specifies the location in cog where this code will be loaded to and run from. It is required when for example you have multiple bits of code in a source file that will be loaded to different cogs. Or less obviously when you have code that may get moved around in COG or loaded into a specific address in COG.

    For example in earlier versions of my Z80 emulator I used code overlays in order to be able to write everything in PASM and run it in a single COG. Those overlays were loaded by the emulator when required to a specific address in COG. So that address had to be specified at the start of each overlay section. (Later versions of the emulator use LMM instead).
  • Cluso99Cluso99 Posts: 18,069
    edited 2012-06-06 06:46
    As heater has said, there are particular uses for this. It is not a compiler errer but a programmer error. I would be almost certain this is as per the proptool and homespun and the new open compiler too.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-06 08:45
    I do sympathize with the OP, though. Combining multiple PASM programs can be a real pain, since all DAT labels are global (notwithstanding the colon-prefixed :labels, which are useful but inadequate). What is needed is a way to declare separate namespaces that can be pushed onto a dictionary stack during compilation. Even the lowly Z8 assembler had label scoping. PASM should have it, too.

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2012-06-06 09:23
    Phil,

    What? Most assemblers I have used took care of label scoping/name spaces by having you put code into different source files. As does the C language. Given that Spin is not designed for programming "in the large" I would not expect it to have such a feature.
  • pik33pik33 Posts: 2,397
    edited 2012-06-06 09:26
    I don't know how to use this kind of code. Yes, it is my error: i used undeclared variable.
    .. but it was declared in another piece of PASM code.

    This caused very strange program behaviour: in 99% cases it worked, because (maybe) this place in second cog's ram, at which this variable pointed, ( I have to recreate this error and make a listing to know, what the heck the compiler did with this label) was unused. Then, after adding some lines of code, it started to display garbage on the screen, or even it resets a Propeller. This was all random and very hard to find.

    Compiler should warn, as it is doing when write djnz without a #.

    "Warning - label xxx points to another dat block"

    I had to make labels for second cog like "linenum2"... etc - it is very -- very --- easy to make a mistake.. Such warning wil be very useful if added to new version of compiler.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-06 09:27
    heater wrote:
    Given that Spin is not designed for programming "in the large" I would not expect it to have such a feature.
    Oh, please! Anytime you have two PASM cogs in one object, you run into this problem. It's not at all uncommon for this to be an issue.

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2012-06-06 09:37
    Ah, got me there Phil. I have run into exactly that problem when trying to build a multi-cog z80 emulation. Still that's not exactly large.
  • pik33pik33 Posts: 2,397
    edited 2012-06-06 11:57
    Tested this.

    "linenum" was at $9D in the first cog.
    In the second cog, the same $D9 value was used as destination in MOV code.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-06-06 12:19
    Symbols defined in DAT sections have two different addresses, which are the hub RAM address and the cog RAM address. Hub RAM addresses are relative to the start of the object and reference a byte address. Cog RAM addresses start from zero, or can be set by the org psuedo-op. They reference long locations. The res psuedo-op is also used to adjust the hub cog address, and a "res N" instruction is equivalent to "org $+N".
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-06 12:33
    Dave Hein wrote:
    The res psuedo-op is also used to adjust the hub address, ...
    You mean "cog address."

    -Phil
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-06-06 17:58
    Yes, I meant cog address. I fixed my previous comment. Thanks Phil.
Sign In or Register to comment.