GroovyBee Posted September 11, 2010 Share Posted September 11, 2010 I thought I'd list the quirky things I find in AS1600 here. For jzintv-1.0-beta3 :- LISTING "off" doesn't quite do what I thought it would do. I'd expect the assembler to mute all output to the listing file after this point. However, it doesn't . The assembler still adds the hex values for any code or data produced. The instruction "mvii #'0'-32, r0" isn't valid syntax for the reason explained here. Instead it must be replaced with "mvii #asc('0',0)-32, r0". Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 11, 2010 Share Posted September 11, 2010 I thought I'd list the quirky things I find in AS1600 here. For jzintv-1.0-beta3 :- LISTING "off" doesn't quite do what I thought it would do. I'd expect the assembler to mute all output to the listing file after this point. However, it doesn't . The assembler still adds the hex values for any code or data produced. The instruction "mvii #'0'-32, r0" isn't valid syntax for the reason explained here. Instead it must be replaced with "mvii #asc('0',0)-32, r0". GroovyBee: I have great news for you. I think I've fixed both issues. Wanna try the latest as1600? What OS are you on? Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 11, 2010 Author Share Posted September 11, 2010 GroovyBee: I have great news for you. I think I've fixed both issues. Wanna try the latest as1600? What OS are you on? Yep! I'll give them a go. I'm on Windows XP Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 11, 2010 Share Posted September 11, 2010 GroovyBee: I have great news for you. I think I've fixed both issues. Wanna try the latest as1600? What OS are you on? Yep! I'll give them a go. I'm on Windows XP Okey dokey! I will get that built and posted shortly. BTW, this version also has some new features which I think you'll find handy. Here's what I added to the documentation: ------------------------------------------------------------------------------ label QSET expr => "Quiet" SET label QEQU expr => "Quiet" EQUate ------------------------------------------------------------------------------ These directives behave identically to SET/EQU, except that they mark the symbol as "quiet." A "quiet" symbol functions like an ordinary symbol, but will not appear in AS1600's symbol table output. This is useful inside macros to keep macro-internal symbols from cluttering up the symbol table and listing output files. ------------------------------------------------------------------------------ WMSG "string" => Warning message CMSG "string" => Comment message SMSG "string" => Status message ------------------------------------------------------------------------------ These three related directives write out messages of various forms: -- WMSG writes out an assembler warning from "string" -- CMSG writes out a comment message in the listing from "string" -- SMSG writes out a status message in the listing and to stdout from "string" ------------------------------------------------------------------------------ Stringification operators: $( expr-list ) => Stringify expr-list $#( expr ) => Render expr as signed decimal string $$( expr ) => Render expr as a 4 character hex string $%( expr ) => Render expr as an 8 character hex string ------------------------------------------------------------------------------ These operators produce strings that are usable in most contexts that require or accept strings. The only exceptions are INCLUDE, ORG and LISTING directives. The generic stringify operator $( ) produces a string from the lower byte of each value in expr-list. If one of the expressions in the list is undefined or not computable, stringify will substitute in a question mark ('?'). The numeric stringify operators $#( ), $$( ), and $%( ) return a string rendered either as a signed decimal value, 4 character hex value or 8 character hex string. If the value is undefined or not computable, the stringify operator will return an appropriate number of question marks. NOTE: The generic stringify operator $( ) assumes no character translation is currently active, and will warn if it detects that a translation table is currently active. It warns due to the potential for a subtle interaction between these two features. Strings decay to expression lists as needed. AS1600 applies character translations when converting strings to expression lists. The stringify operator takes expression lists and converts them back into strings. That makes complicated expressions such as this work: SMSG $(" Game size: $", $$(_SIZE), " (", $#(_SIZE), " decimal) words") However, when a character translation table is active, the string gets converted when decaying to an expression list. When $( ) then converts the list back into a string, there is no way to do a reverse mapping. I also have an experimental "symbol array" feature in this version. Here's how I described it in an email to Arnauld previously (with some minor tweaks): I just added the last of the nifty assembler features for now. First off, SET/EQU with an expression list will now initialize a symbol as an array. So, this example works now: foo SET "Hello world!" This will initialize foo[0] through foo[11] to the ASCII string indicated. It also sets "foo" to 11 to indicate that that's the highest initialized index. Next up, I've added an array slice syntax. This allows you to request a set of consecutive array elements as an expression list. The syntax is "array[first_index, last_index]". Example: DECLE foo[1,3] In this example, that'll pull out "ell" from "Hello world!". The first_index can be after the last_index. This specifies a slice that goes backwards: DECLE foo[3,1] That gives you "lle" instead of "ell". You can combine slices with SET. Check out this nifty example: foo SET "Hello world!" bar SET foo[foo, 0] DECLE foo[0, foo] ; Gives "Hello world!" DECLE bar[0, bar] ; Gives "!dlrow olleH" For this last example, recall that the array name by itself gives the highest observed array index so far, although you can reset it. This means you need to be a little careful when assigning more than one string to an array, such as you might in a complex macro that you reuse: foo SET "Hello world!" ; foo = 11, foo[0,foo] = "Hello world!" foo SET "Bob" ; foo = 11, foo[0,foo] = "Boblo world!" To avoid that silliness, you can reset the watermark whenever you like: foo SET "Hello world!" ; foo = 11, foo[0,foo] = "Hello world!" foo SET 0 foo SET "Bob" ; foo = 3, foo[0,foo] = "Bob" Make sense? I'm not 100% overloading "SET" like this is the right thing to do. Part of me wonders if I should instead add a new directive, "ASET" for "Array SET". It would at least make code a little clearer. At the same time, this does work just as I have it, and I'm not terribly inclined to change it. It feels a little Perl-like, doesn't it? If I were to change anything, I would make "SET exprlist" always reset the base label to the new array length, so that the "SET 0" in the most recent example isn't needed. Oh, and did I mention that multidimensional arrays work? So, you can say "foo[x][y]" if you like. Also, array slices work on multidimensional arrays, but only on the last dimension. ie. "foo[x][a,b]" is OK, but "foo[a,b][y]" is not. Also, you can assign to an array slice: foo SET "Hello world!" foo[0,4] SET foo[4,0] ; foo[0,foo] = "olleH world!" Array references can be code labels. So, you can actually have macro-local labels now, after a fashion: _add_if[0] QSET 0 MACRO skip_add_if cc, src, dst B%cc% _add_if[_add_if + 1] ADDR %src%, %dst% _add_if[_add_if]: ENDM skip_add_if OV, R0, R1 skip_add_if NOV, R1, R0 This correctly assembles as two short forward branches, as can be seen in the listing: 0x0 _add_if[0] QSET 0 MACRO skip_add_if cc, src, dst B%cc% _add_if[_add_if + 1] ADDR %src%, %dst% _add_if[_add_if]: ENDM ORG $5000 ; skip_add_if OV, R0, R1 5000 0202 0001 BOV _add_if[_add_if + 1] 5002 00c1 ADDR R0, R1 0x3 _add_if[_add_if]: ; skip_add_if NOV, R1, R0 5003 020a 0001 BNOV _add_if[_add_if + 1] 5005 00c8 ADDR R1, R0 0x6 _add_if[_add_if]: ERROR SUMMARY - ERRORS DETECTED 0 - WARNINGS 0 If you really wanted to know all the addresses of the local labels, you could print them like so: _i QSET 0 REPEAT _add_if + 1 SMSG $( "_add_if[", $#(_i), "] = $", $%(_add_if[_i])) _i QSET _i + 1 ENDR which will print out: _add_if[0] = $00000000 _add_if[1] = $00005003 _add_if[2] = $00005006 which is what we expected. (Note that _add_if[0] is supposed to be 0. I could've set _add_if[-1] to 0 instead.) I could imagine turning the above loop into a debug macro. And yes, I do the move through an intermediate array, so the example above does work as advertised, despite the fact that the source and destination slices overlap. I do know of one caveat with the array feature: It doesn't work with strings of length 1. Anyway, let me know what you think of the new features. I'll post a link to update binaries shortly. Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 11, 2010 Share Posted September 11, 2010 Ok, I've put the latest build of jzIntv and AS1600 over here: http://spatula-city.org/~im14u2c/intv/dl/jzintv-20100911.zip This new version of jzIntv has a vastly upgraded debugger, BTW. And it should automatically toggle between fullscreen and windowed when you hit a breakpoint. Use '?' inside the debugger to get the updated usage info. The new --sym-file flag lets you load AS1600's symbol table into the debugger, too. Note that this version of jzIntv also has new graphics scaling code and dirty rectangle updates. It's the version I run myself, and I haven't seen any issues in this latest version. If you see any, let me know. The as1600 binary has the new features I mentioned above, and fixes for 'LISTING "off"' and characters-in-expressions. What I did was treat single character single quoted strings as their own special type distinct from strings. This type decays to an expression rather than an expression list. I don't think it should break most things. The few things that do get broken are easily fixed. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 11, 2010 Author Share Posted September 11, 2010 Thanks for the updated tools link. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 12, 2010 Author Share Posted September 12, 2010 I've tried the new version of the assembler with my project and encountered the following :- 1) Macro names now have to start in the label field. In the previous version they could start after some whitespace. This isn't an issue it just makes the assembler behaviour consistent. 2) I had this macro defined :- MACRO GROM_INDEX(idx) (ASC(%idx%,0)-32) SHL 3 ENDM The new assembler now gives the following error in the listing :- ; mvii #GROM_INDEX(' ')+C_BLK, r0 mvii #(ASC(' ',0)-32) SHL 3 castle.asm:151: ERROR - syntax error at/before token "' " Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted September 12, 2010 Share Posted September 12, 2010 Ok, I've put the latest build of jzIntv and AS1600 over here: http://spatula-city.org/~im14u2c/intv/dl/jzintv-20100911.zip This new version of jzIntv has a vastly upgraded debugger, BTW. And it should automatically toggle between fullscreen and windowed when you hit a breakpoint. Use '?' inside the debugger to get the updated usage info. The new --sym-file flag lets you load AS1600's symbol table into the debugger, too. Note that this version of jzIntv also has new graphics scaling code and dirty rectangle updates. It's the version I run myself, and I haven't seen any issues in this latest version. If you see any, let me know. The as1600 binary has the new features I mentioned above, and fixes for 'LISTING "off"' and characters-in-expressions. What I did was treat single character single quoted strings as their own special type distinct from strings. This type decays to an expression rather than an expression list. I don't think it should break most things. The few things that do get broken are easily fixed. Joe, Any chance of getting that packaged for OS X? -dZ. Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 12, 2010 Share Posted September 12, 2010 I've tried the new version of the assembler with my project and encountered the following :- 1) Macro names now have to start in the label field. In the previous version they could start after some whitespace. This isn't an issue it just makes the assembler behaviour consistent. I'm not sure what you mean here. Can you give me an example? 2) I had this macro defined :- MACRO GROM_INDEX(idx) (ASC(%idx%,0)-32) SHL 3 ENDM The new assembler now gives the following error in the listing :- ; mvii #GROM_INDEX(' ')+C_BLK, r0 mvii #(ASC(' ',0)-32) SHL 3 castle.asm:151: ERROR - syntax error at/before token "' " *d'oh* This is a direct consequence of making single character strings "special." That change ripples through a few places. I'll go make sure the new not-quite-a-string gets handled properly. Unfortunately, AS1600 has a number of anti-patterns in it, being full of case-and-paste. It was like that already when I started, and I haven't made it much better. FWIW, the ASC(...,0) part isn't necessary any longer. You can just say ' '-32. (That is emphatically not an excuse for my breaking it though. I'll go fix it now.) Joe, Any chance of getting that packaged for OS X? -dZ. Certainly! Let me go fix up some of the breakage that GroovyBee pointed out, and I'll post a new build for both OSes after. The OS X one may be delayed slightly, depending on how much StarCraft II my wife decides to play today. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 12, 2010 Author Share Posted September 12, 2010 I'm not sure what you mean here. Can you give me an example? Certainly! If you define a macro like this :- MACRO Test(aValue) %aValue% SHL 3 ENDM Notice the spaces before the words MACRO and ENDM the assembler generates the following :- MACRO Test(aValue) castle.asm:44: ERROR - Unexpected MACRO or ENDM directive castle.asm:44: ERROR - syntax error at/before token "Test" %aValue% SHL 3 castle.asm:45: ERROR - syntax error at/before character "%" ENDM castle.asm:46: ERROR - Unexpected MACRO or ENDM directive If I remove the whitespace it assembles as per normal. Looking back at my bug report post I should have same "Macro directives" instead of "Macro names". Sorry for the misdirection. Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 12, 2010 Share Posted September 12, 2010 (edited) I'm not sure what you mean here. Can you give me an example? Certainly! If you define a macro like this :- MACRO Test(aValue) %aValue% SHL 3 ENDM Notice the spaces before the words MACRO and ENDM the assembler generates the following :- MACRO Test(aValue) castle.asm:44: ERROR - Unexpected MACRO or ENDM directive castle.asm:44: ERROR - syntax error at/before token "Test" %aValue% SHL 3 castle.asm:45: ERROR - syntax error at/before character "%" ENDM castle.asm:46: ERROR - Unexpected MACRO or ENDM directive If I remove the whitespace it assembles as per normal. Looking back at my bug report post I should have same "Macro directives" instead of "Macro names". Sorry for the misdirection. By golly, it does work with whitespace before the MACRO/ENDM directives in Beta3. I don't think that was ever intended, but that said, I don't see why it ought to be disallowed. I think I know which change introduced this. Going through my SVN logs: Use strpbrk instead of strtok to tokenize a string. strtok has the undesirable characteristic that it treats a string of separators as a single separator. While this is ok for whitespace, it isn't ok for other syntactical elements. The new code compresses whitespace to a single character and then uses strpbrk on the result. This fixes a bug where the following macro invocation was considered to have 3 arguments instead of 2: macro(a, b), c Previously, this was hacked around by putting a space between the ')' and the ','. Now as1600 / IMASM handle this correctly it appears. I think this change may have also changed the tokenization behavior for the first token on the line, since the code that looks for "MACRO" and "ENDM" always looks for those in token #0, and had even in Beta3. I'll keep digging, and if I can restore the Beta3 behavior I will. EDIT: Aha, the manpage for strtok brings enlightenment (emphasis mine): A sequence of two or more contiguous delimiter characters in the parsed string is considered to be a single delimiter. Delimiter characters at the start or end of the string are ignored. Edited September 12, 2010 by intvnut Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 12, 2010 Share Posted September 12, 2010 Ok, I think I've fixed both issues. The ASC, STRLEN and CHARDEF directives now correctly handle the new single-character single-quoted pseudo-string. The MACRO/ENDM directives allow whitespace before them again. I've made OS X and Win32 builds. jzIntv/as1600 for Win32 jzIntv/as1600 for OS X I'm also updating the "Examples" directory and will upload that in a little bit as a separate download. Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 12, 2010 Author Share Posted September 12, 2010 Thanks for the fast bug fixes. Is there a way to do manual single stepping in the jzintv debugger without continually typing "s1"? Its driving me nuts . A single command for "execute this subroutine but don't tell me about it in the trace" would be good. The accumulated cycle time seems to be missing in the latest build too. Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 12, 2010 Share Posted September 12, 2010 (edited) Thanks for the fast bug fixes. It's exciting to see someone using my stuff. I also hate it when my bugs hold anyone else up. Is there a way to do manual single stepping in the jzintv debugger without continually typing "s1"? Its driving me nuts . Yes. Just hit enter to single step. Actually, more precisely from jzIntv's online help: [enter] [enter] with no command is the same as "s1" or "t1", depending on whether "s" or "t" was used most recently A single command for "execute this subroutine but don't tell me about it in the trace" would be good. The "t" command, when executed while stopped at a JSR will tell jzIntv to "trace over" it. It even tries to detect arguments after the JSR. Example: 00FC 7000 0000 0000 01FE 103D 02f1 103D ------iq JSR R5,$101d > t Returned from JSR at $103D. 00FC 4800 0000 0000 01FE 1041 02f1 1041 ------iq MVII #$00fe,R0 > u103d $103D: 0004 0110 001d JSR R5,$101d $1040: 0048 SLL R0 $1041: 02b8 00fe MVII #$00fe,R0 $1043: 02bc 0102 MVII #$0102,R4 There's a 1 byte argument to the function at $101D stored immediately after the JSR at $1040. jzIntv will actually detect the CPU reads after the JSR and will move the trace-over point forward. Trace-overs like this are ephemeral. I'm guessing you want to make them persistent? ie. "Always trace-over this function"? The accumulated cycle time seems to be missing in the latest build too. It's not gone, it's just that you're less likely to see it. I used to display all of the CPU's code fetches, but that's a lot of worthless noise. But, each of those fetches would also show the current time stamp. I should probably show the timestamp elsewhere, or add a command to print the current time. What do you think of just putting the timestamp in the prompt? ie. 00FE 4800 0000 0000 0102 1041 02f1 1045 ------iq JSR R5,$1738 0000012883 > or similar? EDIT: Hold on, I do have a timestamp feature already and the ability to print out all the CPU reads and writes. From jzIntv's debugger online help: z Toggle showing timestamps during 'step' x Toggle showing CPU reads and writes during 'step' Example: 0000 0000 0000 0000 0000 1003 0000 1026 -------- MVII #$02f1,R6 > 0000 0000 0000 0000 0000 1003 02f1 1028 ------i- JSR R5,$1a83 > 0000 0000 0000 0000 0000 102B 02f1 1A83 ------i- PSHR R5 > 0000 0000 0000 0000 0000 102B 02f2 1A84 -------- PSHR R0 > z Now showing timestamps during step > 0000 0000 0000 0000 0000 102B 02f3 1A85 -------- PSHR R1 53 > 0000 0000 0000 0000 0000 102B 02f4 1A86 -------- MVII #$01f0,R4 62 > 0000 0000 0000 0000 01F0 102B 02f4 1A88 ------iq MVII #$000e,R0 70 > 000E 0000 0000 0000 01F0 102B 02f4 1A8A ------iq JSR R5,$1738 78 > x Now showing CPU reads/writes during step > RD a=1A8A d=0004 CP-1610 (PC = $1A8A) t=78 RD a=1A8B d=0114 CP-1610 (PC = $1A8A) t=78 RD a=1A8C d=0338 CP-1610 (PC = $1A8A) t=78 000E 0000 0000 0000 01F0 1A8D 02f4 1738 ------iq PSHR R5 91 > RD a=1738 d=0275 CP-1610 (PC = $1738) t=91 RD a=1739 d=01ED CP-1610 (PC = $1738) t=91 WR a=02F4 d=1A8D CP-1610 (PC = $1738) t=91 000E 0000 0000 0000 01F0 1A8D 02f5 1739 -------q CLRR R5 100 > RD a=1739 d=01ED CP-1610 (PC = $1739) t=100 RD a=173A d=0270 CP-1610 (PC = $1739) t=100 000E 0000 0000 0000 01F0 0000 02f5 173A ---Z--iq PSHR R0 106 > Edited September 12, 2010 by intvnut Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 12, 2010 Author Share Posted September 12, 2010 I think I need to go and read the manual now . Nothing is really a problem or holding me up. I'm just trying to get to my goal of getting a game working. I think the cycle time should be on a command on its own. I'm mainly interested in cycle times for runs of code or complete functions. I think that it would be too cluttered otherwise. Quote Link to comment Share on other sites More sharing options...
intvnut Posted September 12, 2010 Share Posted September 12, 2010 (edited) I think I need to go and read the manual now . Nothing is really a problem or holding me up. I'm just trying to get to my goal of getting a game working. I think the cycle time should be on a command on its own. I'm mainly interested in cycle times for runs of code or complete functions. I think that it would be too cluttered otherwise. Yeah, just hit '?' in the debugger to get a command summary. With the cycle toggle command ('Z') does that get you far enough? It puts the cycle numbers at the right. Also, I have a bit of a hack I wrote. It mostly works, but I never considered it quite production worthy. You're welcome to give it a try, though. This program takes the "dump.hst" file that jzIntv's history logger writes along with the listing file from as1600, and attempts to put together a function-level and loop-level profile of the program. (It would probably do a better job if as1600 gave an exact listing of the PROC/ENDP locations.) Here's an excerpt of what it gives from a recent run on Space Patrol: Total profiled cycles: 40818306 Function | Range | Cycles | % of Tot ENGINE1 | 53F9-5658 | 8115735 | 19.88% RUNENG | 5FE8-6080 | 5849072 | 14.33% WAIT_SONG1 | BE3A-BE56 | 3006972 | 7.37% UPSPP | 59B0-5ADE | 2921163 | 7.16% UPMUX | 5E13-5E9B | 2644002 | 6.48% UPBGP | 58BF-599D | 2099166 | 5.14% DBHC | CDAB-CDB3 | 1666140 | 4.08% UPSFX | BD13-BD3F | 1217325 | 2.98% UPD_PSG | BF24-BF77 | 1135974 | 2.78% CKGGB | 5B14-5C31 | 1074220 | 2.63% CKBRC | 572F-5793 | 1007051 | 2.47% UPSPA | 5E9C-5EEB | 922604 | 2.26% MENUINP | CD71-CDA6 | 719445 | 1.76% UPANI | 5CF8-5D19 | 669931 | 1.64% ....a bunch deleted.... Loop breakdown for each function over 1% FUNCTION: ENGINE1 | 53F9-5658 | 8115735 FUNCTION: RUNENG | 5FE8-6080 | 5849072 LOOP: RUNENG.loop | 5FF2-6014 | 3109405 | 53.16% LOOP: RUNENG.loop | 5FF2-6040 | 5820198 | 99.51% LOOP: RUNENG.loop | 5FF2-6057 | 5845930 | 99.95% FUNCTION: WAIT_SONG1 | BE3A-BE56 | 3006972 LOOP: WAIT_SONG1.spin | BE3E-BE52 | 3006843 | 100.00% FUNCTION: UPSPP | 59B0-5ADE | 2921163 LOOP: UPSPP.l | 5A30-5A52 | 1405072 | 48.10% FUNCTION: UPMUX | 5E13-5E9B | 2644002 LOOP: UPMUX.gp1skip | 5E26-5E33 | 184107 | 6.96% LOOP: UPMUX.gp1mobl | 5E28-5E4A | 740096 | 27.99% LOOP: UPMUX.gp2skip | 5E5D-5E6A | 658104 | 24.89% LOOP: UPMUX.gp2mobl | 5E5F-5E81 | 1050887 | 39.75% ... a bunch more deleted ... I've attached the C code for the profiler (renamed to .c.txt due to silly filter rules) in case you want to give it a whirl. profile.c.txt Edited September 12, 2010 by intvnut Quote Link to comment Share on other sites More sharing options...
GroovyBee Posted September 13, 2010 Author Share Posted September 13, 2010 The symbol table exporter/importer in as1600/jzintv is a boon to productivity . Would it be possible to have it display :- "label (absolute address in hex)" instead of its current form of :- "absolute address in hex (label)" In my mind if you have the symbol table loaded it should take priority over the absolute address. Ideally I'd like to switch the absolute address display off with a command to reduce the clutter. Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted September 14, 2010 Share Posted September 14, 2010 Ideally I'd like to switch the absolute address display off with a command to reduce the clutter. The symbol table usage in the debugger is great, but I would also like the ability to switch the absolute address on or off. -dZ. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.