It is currently Thu Nov 23, 2017 1:34 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Fri Oct 20, 2017 7:42 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
I wanted to print some debug messages using .assert, but the values being debugged aren't necessarily known at assembly time, and I really want to display exactly how off the numbers are, rather than just stating that they're off. Since .sprintf won't take non-constant numbers, I came up with this hack:

Code:
.repeat 20, i
   .assert number <> i, ldwarning, .sprintf("number is %d", i)
.endrepeat

It looks kludgy as hell, but it works for small ranges. I'm still wondering though, is there a better way to do this? Especially if the range of values is way bigger than in the example above. Am I just being stupid?


Top
 Profile  
 
PostPosted: Sat Oct 21, 2017 4:37 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
I'm not aware of a good way, but personally I've used a macro that outputs the value in a special "build log" segment, which is then directed to a separate file in the linker configuration. Note that since we don't know the value of the variable, we always have to output a constant number of characters and pad it from the left with spaces or zeros. You can of course also output explanatory strings with .byte in the build log segment.

Here's the macro: (https://github.com/fo-fo/ngin/blob/mast ... e.inc#L409)
Code:
.macro __ngin_decimalInteger integer
    .local divider
    divider .set 100000000
    .local value
    value = integer

    ; \note .charmap isn't a problem here, because string/character literals
    ;       are not used.
    ; \todo This doesn't seem to work properly for signed numbers (try
    ;       e.g. $FFFFFFFF).

    .repeat 9, i
        ; Output the corresponding digit, or a space if the digit and all the
        ; more significant digits are zeroes. Unless we're outputting the least
        ; significant digit, which is always displayed (so that 0 is displayed).
        .byte .lobyte( __ngin_choice \
            (value/divider) <> 0 .or divider = 1, \
            (value/divider) .mod 10 + ngin_Ascii::kZero, \
            ngin_Ascii::kSpace )
        divider .set divider/10
    .endrepeat
.endmacro

I'm not sure why I chose to output only 9 characters (this may have been what caused it not to work with $FFFFFFFF as seen in the TODO comment). Seems like it should be 10 characters to cover the full range of a 32 bit variable. It's easy to modify this to output hexadecimal, if desired (see the __ngin_hexInteger macro in the above link).

__ngin_choice is a ternary macro defined as:
Code:
.define __ngin_choice( condition, if, else ) \
    ((!!(condition)) * (if) + (!(condition)) * (else))

ngin_Ascii is defined as:
Code:
.enum ngin_Ascii
    kLf     = 10
    kCr     = 13
    kSpace  = 32
    kQuote  = 34
    kZero   = 48
    kNine   = kZero+9
    kPlus   = 43
    kMinus  = 45
    kDot    = 46
    kA      = 65
.endenum


EDIT: Added __ngin_hexInteger reference.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Last edited by thefox on Sat Oct 21, 2017 11:40 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat Oct 21, 2017 11:27 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
That's a pretty good idea, thanks.


Top
 Profile  
 
PostPosted: Sat Nov 11, 2017 4:01 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10118
Location: Rio de Janeiro - Brazil
I ended up going with this (it writes non-constant numbers to a text file):
Code:
   .macro Assembler_WRITE_NUMBER _Number, _Base, _Places, _Divisor
      .ifblank _Divisor
         Assembler_WRITE_NUMBER _Number, _Base, _Places, 1
      .else
         .if _Places > 0
            Assembler_WRITE_NUMBER _Number, _Base, (_Places) - 1, (_Divisor) * _Base
            .local _Digit
            _Digit = ((_Number) / (_Divisor)) .mod _Base
            .lobytes _Digit + $30 + (_Digit > 9) * $07
         .endif
      .endif
   .endmacro

Then I can write numbers in any base with any number of places (I don't do anything about leading zeroes). This is how I would check the value of a label in PRG-ROM (base 16, 4 places):
Code:
Assembler_WRITE_NUMBER SomeLabel, 16, 4


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Donqustix and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group