Jump to content
IGNORED

Assembly developers: Have you ever used RORG with address?


ralphb

Recommended Posts

I have a question for all assembly developers, irrespective of particular assembler used: In your programs, have you ever used the RORG directive with an address, like RORG >1000? If so, what was your motivation for doing so, e.g., did you want to reserve memory at the beginning of the program, or did you want the listing to show a particular address range, or did you want to use the address the program will be placed at later, or ...?

I'm asking this question because I'm unsure about one detail regarding the new xas99 linker.

The E/A loader, on the other hand, is quite primitive. It will load any relocatable program (i.e., one using RORG) relative to memory address >A000, which means that any RORG address >6000 or higher cannot be loaded by E/A.  When loading two relocatable programs, the second program will be loaded relative to the end of the first program. Thus, if you load multiple programs with RORG >1000, you'll get a lot of unused space.

For compatibility, the xas99 linker uses the same logic.  But there is one special case, where a RORG programs conflicts with an AORG program, which the loader ignores.  For xas99, I'm thinking of two possible solutions to resolve conflicts, and for deciding on one solution I would need to know some opinions on why one would use RORG with address -- I never have used this construct.

(Programs can have both RORG and AORG parts, but I dont't want to complicate things too much here.)

  • Like 1
Link to comment
Share on other sites

Never used it.

 

Not sure if you have the capability, but I would also test with how GenLINK handles RORG on the Geneve.  I know several of us use Paul Charlton's GenProg package.  If you do not have a Geneve, you should be able to use a MAME system if you need to see/test something.

 

The linker (LINK aka GenLINK) is very versatile as you can set memory boundaries as blocks (pages or 8K memory boundaries) for putting code and modules together.  You can find the documentation for GenLINK by going to http://9640news.ddns.net:8080 as it is on the home page there if you are not familiar with it.  There is also Clint Pulley's linker, however it has been 25 years since I used that software.  I think people that use it are any programmers for "c" for MDOS which I have not heard or seen anyone developing things in a number of years.

 

Beery

 

Link to comment
Share on other sites

Yes, I have used it. I used it as a workaround for a specific problem I was having with Cory Burr’s Asm994a.exe Assembler. RORG was not working as expected when a dummy block was inserted into relocatable code, which may have been due to a misunderstanding on my part. Nevertheless, I saved the address before DORG and restored it as follows:

_RORG1 EQU  $
       DORG 0
...
       RORG _RORG1
...

 

...lee

  • Like 1
Link to comment
Share on other sites

2 hours ago, Lee Stewart said:

Yes, I have used it. I used it as a workaround for a specific problem I was having with Cory Burr’s Asm994a.exe Assembler. RORG was not working as expected when a dummy block was inserted into relocatable code, which may have been due to a misunderstanding on my part. Nevertheless, I saved the address before DORG and restored it as follows:


_RORG1 EQU  $
       DORG 0
...
       RORG _RORG1
...

 

...lee

So does RORG _RORG1 restore the address count to what it was at _RORG1? It sounds like Ralph is saying that the E/A loader interprets it to add _RORG1 to the first free address and continue there.

 

The listing file should sort that out..   or its a bug in the loader.

 

 

 

Link to comment
Share on other sites

Paul Charlton's GenASM does some pretty weird things with RORG in the object code, which I find rather ugly, but it seems to work, obviously. This is what TIImageTool produces from one of my program (and I surely did not use RORG).

 


          IDT  '21:06:04'
          DEF  START
          
START     B    @>0000
R0004     TEXT 'ABS('
R0008     TEXT '    ? status='
R0016     TEXT '    '
          BYTE >0D
          BYTE >0A
          DATA >0009
R001E     DATA >FFFE
          DATA >FFFF
          DATA >0000
          DATA >0001
          DATA >0002
          DATA >7FFE
          DATA >7FFF
          DATA >8000
          DATA >8001
          DATA >0006
R0032     LWPI >F000
          RORG $-52
R0002     DATA R0032+2
R0004     BSS  52
R0038     LIMI >0000
          LI   R8,R001E
          MOV  *R8+,R9
R0042     MOV  *R8,R6
          LI   R1,>FC00
          LST  R1
          ABS  R6
          STST R7
          MOV  *R8+,R0
          LI   R1,R0008
          BL   @>0000
          MOV  R7,R0
          LI   R1,R0016
          BL   @>0000
          LI   R0,>0027
          LI   R1,R0004
          CLR  R2
          XOP  @R0032,0
          DEC  R9
          JNE  R0042
          BLWP @>0000
R0078     TEXT '0123456789ABCDEF'
R0088     MOV  R0,R3
          RORG $-42
R0060     DATA R0088
          RORG $-12
R0056     DATA R0088
R0058     BSS  50
R008A     LI   R2,>0004
R008E     SRC  R3,12
          MOV  R3,R4
          ANDI R4,>000F
          MOVB @R0078(R4),*R1+
          DEC  R2
          JNE  R008E
          RT  
          
          END

 

 

(If only these silly emojis could be deactivated, at least in a code block ...)

  • Haha 1
Link to comment
Share on other sites

5 hours ago, FarmerPotato said:

So does RORG _RORG1 restore the address count to what it was at _RORG1? It sounds like Ralph is saying that the E/A loader interprets it to add _RORG1 to the first free address and continue there.

 

The listing file should sort that out..   or its a bug in the loader.

 

It does, indeed, restore the address count to what it was at _RORG1. My listing file from Asm994a showed that to be the case.

 

As I read the E/A Manual, if there is an RORG operand, the Assembler sets the relocation program counter to that value.

 

If there is no RORG operand, the Assembler does the following:

  1. Following absolute (AORG) or dummy (DORG) code, picks up where relocatable code before AORG/DORG left off. If it is the first occurrence of relocatable data/code, it will be >0000.
  2. Following relocatable code, it has no effect.

It was in (1) above where I believe Asm994a failed me.

 

...lee

Link to comment
Share on other sites

1 hour ago, Lee Stewart said:

 

It does, indeed, restore the address count to what it was at _RORG1. My listing file from Asm994a showed that to be the case.

 

As I read the E/A Manual, if there is an RORG operand, the Assembler sets the relocation program counter to that value.

 

If there is no RORG operand, the Assembler does the following:

  1. Following absolute (AORG) or dummy (DORG) code, picks up where relocatable code before AORG/DORG left off. If it is the first occurrence of relocatable data/code, it will be >0000.
  2. Following relocatable code, it has no effect.

It was in (1) above where I believe Asm994a failed me.

 

...lee

I don't think I ever mixed them.

I found uses for DORG 0 at the top of a file, like building struct offsets, then RORG for the code.

I wrote whole programs with AORG (for XB environment or cart images).

 

Link to comment
Share on other sites

34 minutes ago, FarmerPotato said:

I don't think I ever mixed them.

I found uses for DORG 0 at the top of a file, like building struct offsets, then RORG for the code.

I wrote whole programs with AORG (for XB environment or cart images).

 

I used RORG because the original TI Forth programmers used it. They, however, did not use it with an operand. It followed an embedded dummy block. When I tried to assemble that code with Asm994a, it did not work as expected. That is when I used the workaround with the operand—mainly because I did not want to use the E/A Assembler (or learn another) at the time. I also used RORG with fbForth 1.0 because it was a clone of TI Forth, with the major change from sector-based Forth blocks to file-based Forth blocks.

 

Obviously, for the cartridge-based development of fbForth 2.0, I had to use AORG, which requires an operand, so how to handle embedded dummy blocks was a little more obvious.

 

...lee

Link to comment
Share on other sites

Oh wow, that's interesting!  Thanks to all who responded.

 

The Geneve is a good point I'll have to check.  But other than that, no one is really using RORG with address -- I'll change the xas99 linker accordingly.

 

And please keep in mind that what I stated above only applies to loading multiple object codes (with E/A #3).  Using multiple RORGs with address within one program unit (i.e., everything you assemble in one go) will not be additive.  For example,

RORG >1000
DATA 1
RORG >2000
DATA 2

places data at >B000 and >C000, but splitting this into two programs

RORG >1000
DATA 1

and

RORG >2000
DATA 2

will place it >B000 and >D002.  Go figure.

Link to comment
Share on other sites

Note that the RORG magic in the code is just done by GenASM, not by TASM that is also used on the Geneve. So it is not a requirement for the platform, and I did not use it in the source code.

 

And actually, RORG does not appear in the object code; it is my TIImageTool that inserts these RORGs because the location counter was changed at that point in the tagged object code.

 

Here is the tagged object code for reference.

 


000000: 01 00 a0 32 31 3a 30 36 3a 30 34 41 00 00 42 04     ...21:06:04A..B.
000010: 60 42 00 00 42 41 42 42 53 28 42 20 20 42 20 20     `B..BABBS(B  B  
000020: 42 29 3a 42 20 73 42 74 61 42 74 75 42 73 3d 42     B):B sBtaBtuBs=B
000030: 20 20 42 20 20 42 0d 0a 44 00 41 00 1e 42 00 09       B  B..D.A..B..
000040: 42 ff fe 42 ff ff 42 00 00 42 00 01 46 20 20 20     B..B..B..B..F   
000050: 42 00 02 42 7f fe 42 7f ff 42 80 00 42 80 01 42     B..B..B..B..B..B
000060: 00 06 42 02 e0 42 f0 00 41 00 02 43 00 34 41 00     ..B..B..A..C.4A.
000070: 38 42 03 00 42 00 00 42 02 08 43 00 1e 42 c2 78     8B..B..B..C..B.x
000080: 42 c1 98 42 02 01 42 fc 00 42 00 81 42 07 46 42     B..B..B..B..B.FB
000090: 02 c7 42 c0 38 42 02 01 43 00 08 42 06 a0 46 20     ..B.8B..C..B..F
0000a0: 42 00 00 42 c0 07 42 02 01 43 00 16 42 06 a0 42     B..B..B..C..B..B
0000b0: 00 00 42 02 00 42 00 27 42 02 01 43 00 04 42 04     ..B..B.'B..C..B.
0000c0: c2 42 2c 20 43 00 32 42 06 09 42 16 e7 42 04 20     .B, C.2B..B..B.
0000d0: 42 00 00 42 30 31 42 32 33 42 34 35 42 36 37 42     B..B01B23B45B67B
0000e0: 38 39 42 41 42 42 43 44 42 45 46 42 c0 c0 46 20     89BABBCDBEFB..F
0000f0: 41 00 60 43 00 88 41 00 56 43 00 88 41 00 8a 42     A.`C..A.VC..A..B
000100: 02 02 42 00 04 42 0b c3 42 c1 03 42 02 44 42 00     ..B..B..B..B.DB.
000110: 0f 42 dc 64 43 00 78 42 06 02 42 16 f8 42 04 5b     .B.dC.xB..B..B.[
000120: 35 00 00 53 54 41 52 54 20 46 20 20 20 20 20 20     5..START F      
000130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                     
000140: 3a 20 47 65 6e 41 53 4d 20 76 31 2e 30 33 2c 20     : GenASM v1.03,
000150: 28 43 29 20 31 39 38 38 2c 31 39 38 39 20 62 79     (C) 1988,1989 by
000160: 20 4a 2e 20 50 61 75 6c 20 43 68 61 72 6c 74 6f      J. Paul Charlto
000170: 6e 2e 20 41 73 73 65 6d 62 6c 65 64 3a 20 30 36     n. Assembled: 06
000180: 2d 32 32 2d 31 39 20 32 31 3a 30 36 3a 30 34 20     -22-19 21:06:04

Edited by mizapf
Link to comment
Share on other sites

Reading the manual of GenASM, I now know why it creates such a strange code: It is a one-pass assembler. For that reason, it writes object code with forward references using a 0000, then rewinds the location counter when the symbol appears, inserts the values, then forwards again. What a nonsense. Why should one do a one-pass assembler? Just to save some time? I'd rather get a reasonable object code, I'm not so short of time.

 

I think I'll return to TASM again.

 

 

Link to comment
Share on other sites

Switch the location pointer to relocatable mode and optionally set its value ("Relocatable origin"). The location pointer is the address pointer used by the assembler and the loader.

 

In contrast, AORG ("Absolute origin") switches to absolute (non-relocatable) mode and places the argument into the location pointer. The code after this directive will be loaded starting from the provided address. To switch back to relocatable mode, you have to use RORG.

Edited by mizapf
Link to comment
Share on other sites

These assembler directives are directed at the linking loader (E/A option 3, Extended Basic loader, Geneve LDR).

 

As I once said, what we - in the TI world - disparagingly call "just E/A 3" actually corresponds to Windows EXE files or Linux ELF files. The "E/A option 5" files correspond to the COM files in MSDOS. I know, it is a matter of loading speed for us.

Link to comment
Share on other sites

1 hour ago, mizapf said:

Reading the manual of GenASM, I now know why it creates such a strange code: It is a one-pass assembler. For that reason, it writes object code with forward references using a 0000, then rewinds the location counter when the symbol appears, inserts the values, then forwards again. What a nonsense. Why should one do a one-pass assembler? Just to save some time? I'd rather get a reasonable object code, I'm not so short of time.

 

I think I'll return to TASM again.

Assemble MDOS or another large set of source files and you may appreciate the one-pass assembler's speed. I would abandon using my real hardware for development without the use of Paul's Genprog package.  (To me, the object code is just an interim step to linking the resulting program image; I rarely find a need to inspect the object code with an image handy)

 

My only recollection of using RORG with a directive is for some self-modifying relocatable code. I have seen its use sporadically in other source, less frequently than DORG and AORG.

Link to comment
Share on other sites

I did not yet assemble GeneveOS/MDOS, but I do have some projects (TIC or assembly language) that have several source files (XModem e.g. has 14 source files, Fractals' executable files use 29K together). If one assembler takes 5 minutes and the other 8 minutes, I don't care, but this is just my personal view, of course.

 

(I admit, at some time I stripped down the set of systems in MAME to the TI family when I built MAME, as I started to get annoyed from waiting 15 minutes every time that I started a build during debugging; now I am down to five minutes.)

 

Link to comment
Share on other sites

On 1/18/2020 at 12:09 PM, ralphb said:

 


RORG >1000
DATA 1
RORG >2000
DATA 2

places data at >B000 and >C000, but splitting this into two programs


RORG >1000
DATA 1

and


RORG >2000
DATA 2

will place it >B000 and >D002.  Go figure.

 

The first example is as expected; the RORG value is absolute with respect to its location counter (i.e. the value is not an offset, but the relocatable address).

 

I don't see the second result with TASM - or did you mean separately loaded object code (e.g. multiple calls of E/A option 3)?

 

This is RORG1_S:


       RORG >1000
       DATA 1

       COPY "RORG2_S"

       END

 

This is RORG2_S:


       RORG >2000
       DATA 2

       RORG >2800
       DATA 3

 

The resulting object code:


01 28 02 20 20 20 20 20 20 20 20 41 10 00 42 00     .(.        A..B.
01 41 20 00 42 00 02 41 28 00 42 00 03 46 20 20     .A .B..A(.B..F  
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                     
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                     
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                     
3a 20 20 20 39 39 2f 34 41 20 61 6e 64 20 39 36     :   99/4A and 96
34 30 20 43 72 6f 73 73 2d 41 73 73 65 6d 62 6c     40 Cross-Assembl
65 72 20 20 20 20 20 20 20 20 20 20 20 20 20 20     er

 

with tags as text:


A 1000
B 0001
A 2000
B 0002
A 2800
B 0003
F
:   99/4A and 9640 Cross-Assembler

 

I think for compatibility's sake you should allow for RORG <address>.

Link to comment
Share on other sites

8 minutes ago, mizapf said:

I don't see the second result with TASM - or did you mean separately loaded object code (e.g. multiple calls of E/A option 3)?  [...]

I think for compatibility's sake you should allow for RORG <address>.

Yes, I'm talking about the loader of E/A 3, which basically does the linking.  I'm not preventing the use of RORG with address in sources, but I wonder (a) if I should follow the approach of E/A and waste(?) a lot of space and (b) if and how I should resolve conflicts.  Another example:

RORG >1000
DATA 1

and

AORG >1000
DATA -1

When loading both programs in E/A 3, one program will overwrite the other, as the loader doesn't check for address conflicts between absolute and relocatable segments.

 

And alas, so far no one could name a use for RORG <addr>, so we don't know if the offset really is waste.

Link to comment
Share on other sites

You mean AORG >B000? (Assuming that the relocatable location counter starts at A000.)

 

Overwriting would be - I'd say - intentional. (Or: The program author just deserves it. ;-) )

 

One more suggestion from the section "1% of the people actually thought about this, but much less actually need it": You could think about including PSEG / CSEG / DSEG for your linker - just in case we discover that we could need that. (I actually included it in TIMT's disassembler. Just in case.)

Edited by mizapf
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...