6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Apr 27, 2024 9:47 pm

All times are UTC




Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Fri Jun 22, 2018 11:36 am 
Offline

Joined: Thu Apr 19, 2018 12:53 pm
Posts: 25
Hello,

I my attempt to reassemble some code, I run into a problem.
The documentation is not very extensive, so I cannot find some stuff.
The original code is: (ttoutt&255)+1
If I understan this correctly, it transforms a decimal number from the label into a hex value and by adding 1, it prevents the outcome to be zero.
How do I get this done with the "Kowalski" program?

2nd Q, is there some more documentation? I have some things from Bill (Big....dynosaur) and his code for the POC V1, that's been a big help.... :D

BR/
Guus


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 22, 2018 2:08 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
I believe that in the Kowalski world you can't use parentheses in expressions. So try
1 + ttoutt & 255

I'm not at all sure how that +1 is supposed to help - can you supply a bit more context?

BTW the best and latest Kowalski version can be seen - with sources - in this thread:
viewtopic.php?f=8&t=5011

(I see BDD's additional txt file is in this post:
viewtopic.php?p=56765#p56765
but it's short enough to quote here:
Quote:
Code:
;KOWALSKI SIMULATOR ASSEMBLER DIRECTIVES — BigDumbDinosaur 2004/07/01
;
 IO_AREA           ;define console I/O area address (no leading dot in IO_AREA)
 .ASCII .BYTE .DB  ;generate static data, such as strings, tables, etc.
 .ASCIS            ;generate character string w/bit 7 of last byte set
 .DBYTE .DD        ;assemble big-endian word
 .DCB              ;equivalent to * = * + N, where N is arg to .DCB,...
                   ;w/optional initialization pattern, e.g., .DCB 10,$FF, which will
                   ;reserve 10 bytes & fill them with $FF
 .DS .RS           ;equivalent to * = * + N, where N is arg to .DS or .RS
 .DW .WORD         ;assemble little-endian word
 .ELSE             ;conditional assembly directive
 .END              ;mark end of source file, optional, but recommended
 .ENDIF            ;mark end of conditional assembly
 .ENDM             ;mark end of macro definition
 .ENDR             ;mark end of repeated text
 .ERROR            ;emit an error message & halt assembly,...
                   ;e.g., .ERROR "!!! operand out of range !!!"
 .EXITM            ;halt macro expansion prior to reaching .ENDM
 .IF               ;start conditional assembly. e.g., .IF FLAG == 1
 .INCLUDE          ;insert contents of named source file...
                   ;e.g., .INCLUDE "include/atomic.asm"
 .IO_WND           ;define console I/O window size (cols, rows)
 .MACRO            ;mark start of macro definition, w/optional comma-separated parameters
 .OPT              ;set global assembly options
 .ORG              ;set start of assembly address, same as * = <addr>
 .PARAMTYPE        ;determine macro parameter type: 1 = numeric, 2 = string,...
                   ;.IF .PARAMTYPE(.op) == 1
 .REF              ;determine if label/symbol was defined,...
                   ;e.g., .IF .REF(ABC) evaluates true if...
                   ;ABC has been defined; logic can be reversed...
                   ;with !.REF (ABC), which evaluates true if ABC has NOT been defined
 .REPEAT .REPT     ;repeat following text N times, terminated with .ENDR
 .ROM_AREA         ;set simulator's write-protected address range
 .SET              ;(re)define variable value, e.g., .SET ABC = 1 or ABC .= 1
 .START            ;set simulator start of execution address
 .STR .STRING      ;generate text string, 1st byte is length, 255 bytes maximum
 .STRLEN           ;determine macro parameter string length

;.IF evaluations can use the following binary operators:
;
;    ==  is equal to
;    !=  is not equal to
;    >   is greater than
;    <   is less than
;
;.IF .op means "if .op is non-zero".

)


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 22, 2018 2:22 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
I've just discovered that Kowalski's expression syntax allows square brackets, so we could use
[ttoutt&255]+1

Edit: note that adding 1 after the AND operation means you could get 256 ($100) which won't fit in a byte, so this is probably not what you want to do.

Also note that the source repository contains a text file explaining the directives:
https://github.com/mikekov/6502/blob/ma ... ctives.txt


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 22, 2018 7:31 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
Guus Assmann wrote:
Hello,

I my attempt to reassemble some code, I run into a problem.
The documentation is not very extensive, so I cannot find some stuff.
The original code is: (ttoutt&255)+1
If I understan this correctly, it transforms a decimal number from the label into a hex value and by adding 1, it prevents the outcome to be zero.
How do I get this done with the "Kowalski" program?

2nd Q, is there some more documentation? I have some things from Bill (Big....dynosaur) and his code for the POC V1, that's been a big help.... :D

BR/
Guus

You can write the above expression as [ttoutt & 255] + 1. In the Kowalski assembler, square brackets are used in the same way parentheses would be used in algebraic notation.

As long as Guus has brought up the use of the bit-wise operator &, here is an example program that may be assembled in the Kowalski assembler to illustrate the various operators.

Code:
   .opt proc65c02,caseinsensitive
;KOWALSKI ASSEMBLER LOGICAL, BITWISE & ARITHMETIC OPERATORS
;
;
;   number radices...
;
;       @     binary, e.g., @01011010
;       $     hex, e.g., $5a
;       none  decimal
;
test0001 =@00001111
test0002 =test0001 << 4        ;logical shift left 4 bits
test0003 =test0002 >> 4        ;logical shift right 4 bits
test0004 =test0001 & test0002  ;bitwise AND
test0005 =test0001 | test0002  ;bitwise OR
test0006 =test0001 && test0002 ;logical AND
test0007 =test0001 || test0002 ;logical OR
test0008 =!0                   ;bitwise NOT
test0009 =$5a ^ test0005       ;bitwise XOR
test0010 =4 == 3               ;equality test
test0011 =4 == 4               ;equality test
test0012 =4 != 3               ;inequality test
test0013 =4 != 4               ;inequality test
test0014 =4 > 3                ;greater-than test
test0015 =4 < 3                ;lesser-than test
test0016 =~1                   ;2s complement
;
;
;   arithmetic operators...
;
;       +   addition
;       -   subtraction
;       *   multiplication
;       /   division
;       %   modulo
;
sum      = 5   + 6             ;evaluates to 11
diff     = sum - 6             ;evaluates to 5
prod     = 5   * 6             ;evaluates to 30
quot     =prod / diff          ;evaluates to 6
mod      =prod % sum           ;evaluates to 8
;
;
;   example using square brackets to alter evaluation precedence...
;
test0017 =5 + 6 * 2            ;strictly left-to-right: evaluates to 17
test0018 =[5 + 6] * 2          ;sum of 5 & 6 computed 1st: evaluates to 22
;
   .end

Assembling the above produces the following listing:

Code:
00001  ;KOWALSKI ASSEMBLER LOGICAL, BITWISE & ARITHMETIC OPERATORS
00002  ;
00003  ;
00004  ;   number radices...
00005  ;
00006  ;       @     binary, e.g., @01011010
00007  ;       $     hex, e.g., $5a
00008  ;       none  decimal
00009  ;
00010    000F          test0001 =@00001111
00011    00F0          test0002 =test0001 << 4        ;logical shift left 4 bits
00012    000F          test0003 =test0002 >> 4        ;logical shift right 4 bits
00013    0000          test0004 =test0001 & test0002  ;bitwise AND
00014    00FF          test0005 =test0001 | test0002  ;bitwise OR
00015    0001          test0006 =test0001 && test0002 ;logical AND
00016    000F          test0007 =test0001 || test0002 ;logical OR
00017    0001          test0008 =!0                   ;bitwise NOT
00018    00A5          test0009 =$5a ^ test0005       ;bitwise XOR
00019    0000          test0010 =4 == 3               ;equality test
00020    0001          test0011 =4 == 4               ;equality test
00021    0001          test0012 =4 != 3               ;inequality test
00022    0000          test0013 =4 != 4               ;inequality test
00023    0001          test0014 =4 > 3                ;greater-than test
00024    0000          test0015 =4 < 3                ;lesser-than test
00025    FFFE          test0016 =~1                   ;2s complement
00026  ;
00027  ;
00028  ;   arithmetic operators...
00029  ;
00030  ;       +   addition
00031  ;       -   subtraction
00032  ;       *   multiplication
00033  ;       /   division
00034  ;       %   modulo
00035  ;
00036    000B          sum      = 5   + 6             ;evaluates to 11
00037    0005          diff     = sum - 6             ;evaluates to 5
00038    001E          prod     = 5   * 6             ;evaluates to 30
00039    0006          quot     =prod / diff          ;evaluates to 6
00040    0008          mod      =prod % sum           ;evaluates to 8
00041  ;
00042  ;
00043  ;   example using square brackets to alter evaluation precedence...
00044  ;
00045    0011          test0017 =5 + 6 * 2            ;strictly left-to-right: evaluates to 17
00046    0016          test0018 =[5 + 6] * 2          ;sum of 5 & 6 computed 1st: evaluates to 22
00047  ;
00048     .end

Although the above code shows whitespace around the various operators in some cases, it's only for clarity. I usually leave out whitespace where it isn't needed to avoid evaluation ambiguity.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Fri Jun 22, 2018 9:19 pm 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
Sorry to remark, but to me the comment to line 45 "strictly left-to-right: evaluates to 17" is highly irritating. "evaluation with operator precedence" would clear explain what is evaluated. To me "strictly left-to-right" means: there are no operator precedences at all.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 8:49 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
GaBuZoMeu wrote:
Sorry to remark, but to me the comment to line 45 "strictly left-to-right: evaluates to 17" is highly irritating. "evaluation with operator precedence" would clear explain what is evaluated. To me "strictly left-to-right" means: there are no operator precedences at all.

In the expression 5 + 6 * 2, the assembler assigns no algebraic precedence to the two arithmetic operators, evaluating them in the order in which they appear when read left-to-right. I'm not sure what would be "highly irritating" about an assembler behavior that is actually fairly common.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 9:05 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
(I think it is evaluating right to left, BDD. As ever, it's worth sprinkling some parentheses, or in this case brackets, unless you're extremely confident about a given implementation's precedence rules.)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 9:14 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
BigEd wrote:
(I think it is evaluating right to left, BDD. As ever, it's worth sprinkling some parentheses, or in this case brackets, unless you're extremely confident about a given implementation's precedence rules.)

Yep! Chalk it up to late night "thinking." :oops:

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 9:23 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
It's probably worth having both examples, to illustrate the point:
5 + 6 * 2
2 * 6 + 5
(the present example looks like it illustrates precedence, but it's a trick of the light.)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 7:32 pm 
Offline

Joined: Thu Apr 19, 2018 12:53 pm
Posts: 25
Some more context:

[i]toutt = 300 ;Time out for screen off in seconds[/i]

In the beginning of the program. eg. User settings.
Later in the program:

[i];*** Data table for non-zero variables
;
vart2
.db $80 ;devmodout
.db $80 ;devmodinp
.db $80 ;outret
.db $80 ;inpret
.db $80 ;invst
.db $1E ;monesc
.db $82 ;stattog
.db (toutt&255)+1 ;toutil
.db (toutt>>8)+1 ;toutih
.db (toutt&255)+1 ;toutl
.db (toutt>>8)+1 ;touth
.db $FF ;toutf
[/i]
And I now understand that all I have to do is replace "(.....)" with "[....]"
Then it will be assembled and calculate a timeout value for the screen.

BTW: I'm trying to get the source for a DOS65 system in a compilable state, so I can optimise it for 65C02 and later for 65C816.
Just as an excersise to get my "assembly feet" wet again.

BR/
Guus

P.S.
I've also seen that :
[i]<word [/i]gives the low byte of a two byte address.
And
[i]>word [/i]gives the high byte.

These kind of things may be very logical for many experienced users. For me it takes some gettings used to again.


Last edited by Guus Assmann on Sat Jun 23, 2018 8:01 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 7:57 pm 
Offline

Joined: Thu Apr 19, 2018 12:53 pm
Posts: 25
About calculations, there's also someting called "reverse Polisch notation" on a calculator.
For those who don't know, it works like this:
5 [enter]
6 [enter]
2 [enter]
Now the numbers are on the stack, the operators are punched in.
If you'dd enter * and then + the result would be 2*6 and then + 5.
And entering +, would give 2+6 and then the result *5.

It's not really importand how it works, you'd just have to be aware.

For arthmatic in the school, I learned that one has to multiply first and than do the addition.
There's what we call a "donkey brigde" for this. (= Help me remember, I'm a dumbass :D or have selective Alzheimers)
Mijnheer = Mister (Raise to a power)
Van (Multiplication)
Dale (Devision)
Wacht = Waits (Roots)
Op = for (Addition)
Antwoord = Answer (Substraction)

The first word is in Dutch, my native language.


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 9:25 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8144
Location: Midwestern USA
Guus Assmann wrote:
I've also seen that :
[i]<word [/i]gives the low byte of a two byte address.
And
[i]>word [/i]gives the high byte.

These kind of things may be very logical for many experienced users. For me it takes some gettings used to again.

After a while it will be second nature to you.

Parenthetical note: the Kowalski assembler internally stores all numbers as 32 bit quantities, which feature has some interesting programming implications when writing for the 65C816. The lesser-than and greater-than notations can only act on bits 0-15. If you want to get at bits 16-31, the most significant word (MSW), you will have to right-shift 16 bits, e.g., msw = operand >> 16. A macro I often use is:

Code:
xwordgen .macro .op            ;generate XWORD value
         .word .op & $ffff
         .byte .op >> 16 & $ffff
         .endm

The above takes the internal value of the macro's argument (symbolized by the local variable .op) and generates a three-byte, little-endian value from it that may be used to set up a direct page "long" pointer. Such a pointer gives the 65C816 access to the full 16 MB address space, using [<dp>] and [<dp>],Y addressing.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 23, 2018 9:28 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10793
Location: England
Thanks Guus. I'm still a bit concerned about those +1 - when you add one to the high byte, you're adding 256 to the 16 bit value. Is that really intended?
Code:
.db   [toutt&255]+1   ;toutil
.db   [toutt>>8]+1    ;toutih


If the idea is to store a value one greater than toutt, you'd need something more like
Code:
.db   [toutt+1]&255   ;toutil
.db   [toutt+1]>>8    ;toutih


I think you'll also get the same using
Code:
.db   [toutt+1]%256   ;toutil
.db   [toutt+1]/256   ;toutih

which might (or might not) be easier to read.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 24, 2018 1:28 pm 
Offline

Joined: Thu Apr 19, 2018 12:53 pm
Posts: 25
Thanks for the help so far, I've learnt something again.

Still the assembly program is not behaving.
So I've uploaded the complete source code.
What's wrong? The 2nd pass of the assembly errs out at line 362.
It claims that the label "output" is not defined.
But it most definitively is.
And I tried different names as well. Same problem.
For test, I also made a comment out of this instruction.
Then it goes one line more and the same error for "in"
This is the case for almost all the jmp instructions. (Reset en NMI go ok, as do a couple more)

BTW: I've also seen that adding .b or .f with a label in the BNE or BEQ doesn't work in this assembler. (I'll correct that)


Attachments:
IO65_all_parts.65s.txt [73.79 KiB]
Downloaded 144 times
Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 24, 2018 2:56 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
I guess that the invalid numeric labels cause pass1 to fail and therefore subsequent labels don't make it to the symbol table.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 35 posts ]  Go to page 1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 19 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: