CompuServe Thread

Bruce Dawson Review

22 messages in this thread
#28457From: microsmithsJan 2, 1989 5:54 PM
My main complaint with the Aztec assembler is that you can't create branch tables and have the assembler flag errors if something moves out of range. IE, if you have a list of "bra.s someplace" statements, and one or more go out of range, Aztec will just make that one into a bra.l, which creates havoc if you use jmp xx(pc,dn.w) to do a switch. With CAPE, if you say "bra.s" and a branch goes out of range, it generates an error message. …cheath
#28515From: New memberJan 2, 1989 10:48 PM
Hi charlie. Do you use the Aztec assembler from the "C" package of is there a seperate (and different) program? I had some trouble using the Manx assembler with the 1.3 relese.
#28528From: microsmithsJan 2, 1989 11:15 PM
Yes, I use the MANX AS from the C package … but I've still got V3.4, have not updated to V3.6 yet. Have you tried running without Shell-Seg? There may have been some changes in the BCPL linkages with the new shell, which might collide with the way Jim handles processes. I'd think other folks would have noticed this by now though.
#28542From: New memberJan 3, 1989 12:21 AM
Hum I hav indeed had trouble with the 1.3 Shell and programs written for or rather with Manx C. Im told a new version slated for Jan will take care of that and (I hope and pray) Time().
#28669From: Richard Rae/SYSOPJan 3, 1989 9:55 PM
Not sure I follow the reference to "jmp xx(pc,dn.w)" creating havoc. The proper way to do this would be to vector off of an address picked up from a label table. In this manner the offsets are always correct regardless of what the assembler or YOU might change. It looks as if you're loading up a precalculated offset or somesuch, which is asking for trouble. Or are you talking about phase errors during assembly? Completely confused, Rick
#28744From: microsmithsJan 4, 1989 12:40 AM
THe problem is that the table being jumped into by jmp xx(pc,dn) expects all short branches, but with Manx AS, no error is generated if an explicit "bra.s" instruction actually assembles into a "bra.l" instruction. This throws the table off. For example: jmp mylab(pc,D0) mylab: bra.s Func1 bra.s Func2 bra.s Func3 Here, if the bra.s Func2 instruction actually becomes bra.l without warning, when you try to execute "bra.s Func3" you actually wind up trying to execute the word offset "Func2". …cheath
#28834From: Richard Rae/SYSOPJan 4, 1989 8:28 PM
Aha. Well that's the problem then; you're doing it wrong. 8) I will point out that even if the assembler DIDN'T hink with your branches you'd have the same problem. If one of your branches was OOR you'd have to change it to a long yourself, and then you can't use a calculated offset into the table, because the entries are of different sizes (unless you make them ALL longs). Blech. No, make that double blech. Much better is the approach I suggested in the previous message: the one I THOUGHT you were using. Never, EVER build a table of branches, that's simply asking for trouble (as you have pointed out). Instead, build a table of ADDRESSES. Index into the table (which will always remain orthogonal), pick up the address, then do an indirect jump, branch, or call as needed. Using your example it would be something like: LSL #2,D0 ASSUMES D0 CONTAINS BASE ZERO ORDINAL OF VECTOR LEA MYLAB,A0 LOAD BASE OF VECTOR TABLE INTO A0 MOVEA.L 0(A0,D0.W),A0 PICK UP ADDRESS OF ROUTINE TO USE JMP (A0) JUMP INDIRECT OFF OF A0 MYLAB: DC.L FUNC1,FUNC2,FUNC3,…FUNCN There are a zillion ways to code it, of course… this one is intended for clarity. <continued>
#28888From: microsmithsJan 4, 1989 10:54 PM
That way is fine if you need longword jumps, but it takes up twice as much space as a short branch table if you can do the switch with short branches. With CAPE, you can build short branch tables without having to review the code generated, because it will tell you if any entry in the table has gone out of range. It's also possible to do something like you're doing but with a word-offset table rather than using full longword addresses, if everything is within +/- 32K bytes of a base address. …cheath
#28974From: Richard Rae/SYSOPJan 5, 1989 11:53 AM
Right, but with word addresses you have the same problem, I.E., if one of them won't fit into a +/- 32K range, you've got to stick in a longword, which blows up the table, or insert an island branch somewhere. This approach is absolutely, completely foolproof. As far as size is concerned, if I was writing code for an embedded control system with limited ROM (which I happen to be doing at the moment, but that's a whole 'nother story), I'd keep an eye on it. But good heavens, even if you have a hundred entry vector table (which would be huge), we're only talking about an overhead of two hundred bytes here. (If you compare it with short branches, that's STILL only 300 bytes.) In even a lil' 512K machine 200 bytes is trivial. AND if it comes down to it, I'd wager a good programer could find far more than 200 bytes wasted in a progam large enough to require a 100 entry vector table. Here, change those modules you are JUMPing to to subroutines and CALL them with longwords. Now the end of each one returns to just after the vectored jump, and you can then swing back into your main loop. A RTS is one byte shorter than a short branch; tada… there's 100 bytes right there. I'll leave it to you to find the other byte. 😉 I'd rather squander space on solid, reliable code and clean up dregs elsewhere. (Which I'm sure you would as well; I'm not accusing you of anything.) Rick
#29003From: Scott BallantyneJan 5, 1989 3:45 PM
Yes, but using bra.s or word offsets can save you about 20 bytes or so of relocation info per reference. a hundred entry vector table is actually costing you many more disk bytes, that's something to consider also.
#29061From: Richard Rae/SYSOPJan 5, 1989 10:31 PM
Scott, I'll have to ask you to explain your comments about relocation info and disk space, please? Rick
#29114From: Scott BallantyneJan 6, 1989 2:51 AM
With branches or word offsets from a table base don't have to be relocated on a load, but a table of 32bit absolute addresses has to be relocated by the loader, so the overhead is something like hunkmarker + 4bytes for zero end marker + hunkend + 8 bytes for hunk number and count which gives 24 bytes for the first reference, and then you have another 4 bytes for each additional reference, so a 100 address table would occupy 800+20 bytes on disk, which compares with 200 bytes for a word offset table, which is a pretty big savings in disk space, although once in memory the difference is much less, as you pointed out. sdb
#29197From: Richard Rae/SYSOPJan 6, 1989 7:56 PM
Ah, I hadn't thought of that; I see what you mean now. This is typical of why I enjoy hanging out here. Geez, if you think you don't have anything to learn, don't toss bits with THESE guys. 😉 Rick
#29014From: Bill HawesJan 5, 1989 5:49 PM
Rick, A RTS is one byte shorter than a short branch? You must not be programming the Amiga — they're both 2 bytes long on the 68000, last time I checked. Bill
#29062From: Richard Rae/SYSOPJan 5, 1989 10:31 PM
<URP!> You're wrong and right. I AM programming the Amiga — among other machines. But the 68000 RTS *IS* two bytes (4E 75, to be exact). Every other CPU I program has a byte-wide RTS, and I forgot the 68000 was different in this regard. Thanks for keeping me honest. On the OTHER hand, if we assume the code segments being vectored to are too far away from the re-entry point to be reached with a short branch (which is why Cheath's table approach blows up in the first place), then the jump back would be FOUR bytes long, not two… and now we've recovered all 200 bytes. 8) Rick
#29183From: Bill HawesJan 6, 1989 6:23 PM
Rick, When I set up jump tables I usually try to use BYTE size relative offsets, as the savings in the table nearly always makes up for the extra instruction to load the offset before adding it to the jump address. This lets me make forward references of up to 256 bytes before overflowing the operand. Bill
#29053From: Dean BrownJan 5, 1989 10:23 PM
Rick, Here's how I handle it assuming all references fit into a single source file. The code fragment: lsl.w #1,d0 ;multiply index by 2 for table offset lea cmdtable(pc),a0 ;get address of table move.w 0(a0,d0.w),d0 ;get routine offset adda.w d0,a0 ;calculate routine address jsr (a0) ;jsr to routine The table: cmdtable: dc.w (FUNC1 – cmdtable) dc.w (FUNC2 – cmdtable) … The advantage of this is that there is no relocation data needed in the load file, which makes the code directly ROMable and self-relocating. If you for some reason need a long offset, the assembler will let you know by telling you the value is too large to fit into the defined word. You can then fix it by simply doing a S/R for a 'dc.w' and replace with a 'dc.l', and finally changing the 'lsl.w #1,d0' to a 'lsl.w #2,d0'. -Dean
#29191From: Richard Rae/SYSOPJan 6, 1989 7:54 PM
Looks like a nice clean approach, Dean. I'm going to keep it in mind for the next time I have to code such a table. Thanks. Rick
#29165From: microsmithsJan 6, 1989 5:20 PM
Sure, and if you like you could change every bra.s in your program into a jmp.l #nnnn, and it would only cost you four bytes for each time you do it. But why are you bothering to write in assembler if you don't want smaller & faster code? Using a bra.s table is 100% reliable if you have an assembler that generates an error if you go out of range. …cheath
#29198From: Richard Rae/SYSOPJan 6, 1989 7:56 PM
Re your comments on the reliability, granted… IF your assembler doesn't hink with your code. But if it does, surprise! Of course we both realize that this isn't an important issue… it's back to the old saw of as many was to code as there are coders, eh? Rick
#29261From: microsmithsJan 7, 1989 12:23 AM
I guess the most important thing for me is that I know what my tools are doing, and preferably that they don't leave holes that are easy to fall into. With CAPE I can trust that it's doing what I want it to do to my source code, though I wish it would optimize forward references to short branches. If I saY "bra.s" or "bra.l", I want the assembler to do exactly that, but if I say "bra" I'm asking it to do optimization for me. …cheath
#28835From: Richard Rae/SYSOPJan 4, 1989 8:29 PM
<continuation> We should both acknowledge that this is a side issue seperate from assembler design. On THAT point, I acknowledge that I'd feel uncomfortable about an assembler doing ANYTHING to my code that I don't know about. Compilers, okay; assemblers, no. Give me a switch so I can enable/disable branch optimization and the like or don't give it to me at all. (I've coded all my 68000 code using explicit .B/.W./.L extenders on EVERYTHING. I aways assumed it was being left alone. Now I begin to wonder. Maybe I've just been lucky?) Rick