First steps in ML (split/OT from: Vixen - [...])

Basic and Machine Language

Moderator: Moderators

Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

I'm going to stop being lazy, and answer my own question, from p7 of the wAx manual:
(The persistent counter) is especially useful when using BASIC programs for assembly.
So yes, Robbie, the BASIC stage does store the line-numbered assembly language, so you'll need to allocate enough space on the stage for that code (during development at least).

I think I'll use the upper half of BLK3 for the BASIC stage and assemble to BLK1-2 for the time being; that might make it easier to create the final build later.

↑70
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: First steps in ML (split/OT from: Vixen - [...])

Post by chysn »

Robbie wrote: Sat Oct 03, 2020 4:59 am I think I'll use the upper half of BLK3 for the BASIC stage and assemble to BLK1-2 for the time being; that might make it easier to create the final build later.

↑70
Yeah, that works. To add some color to this, note that ↑70 is a shortcut for ↑70 7E, which will be 3583 bytes free. You might prefer doing ↑70 80 NEW to allocate the whole 4K of the upper half of the block.

Expect to be able to fit about 250 lines worth of machine language code into a 4K BASIC program if you use the relocatable syntax like this

Code: Select all

100 @* JSR $FFD2
and about 220 lines with explicit addressing like this

Code: Select all

100 @1800 JSR $FFD2
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

chysn wrote: Sat Oct 03, 2020 5:59 am Yeah, that works. To add some color to this, note that ↑70 is a shortcut for ↑70 7E, which will be 3583 bytes free. You might prefer doing ↑70 80 NEW to allocate the whole 4K of the upper half of the block.
Will do!
chysn wrote: Sat Oct 03, 2020 5:59 am Expect to be able to fit about 250 lines worth of machine language code into a 4K BASIC program if you use the relocatable syntax like this

Code: Select all

100 @* JSR $FFD2
and about 220 lines with explicit addressing like this

Code: Select all

100 @1800 JSR $FFD2
Worth knowing, thanks.
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

Second Step in ML :D

I've been trying to figure out the most efficient way of incrementing and decrementing the 16-bit address I'm holding in $FB-$FC, and have come up with the following.

Is this how you do it, or is there a more efficient way (particularly for decrement)? I might be missing an obvious opcode, but I don't think so.

Increment $FB-$FC :

Code: Select all

     INC $FB
     BNE ->
     INC $FC
-@   .....
Decrement $FB-$FC :

Code: Select all

     LDA $FB
     BNE ->
     DEC $FC
-@   DEC $FB
     .....
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: First steps in ML (split/OT from: Vixen - [...])

Post by chysn »

Yeah, you've got it! Those are the canonical patterns for 16-bit increment and decrement.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Mike »

Robbie wrote:I might be missing an obvious opcode, but I don't think so.
Especially in the context of memory copy/fill routines, you'll often see the indirect-Y address mode "(),Y" combined with INY/DEY + fixup for the high-byte instead of incrementing/decrementing the full pointer in zeropage like you laid out.

This has been discussed here in Denial some time ago, see here: Counting "trick"/memory copy, with a link to 6502.org about Practical Memory Move Routines.
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

Silence normally means I'm thinking...

I'm re-writing what I've done using (),Y to see how it might compare efficiency-wise, but am still only on my second step in ML, so it's taking a good amount of thinking.
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

Mike wrote: Mon Oct 05, 2020 3:43 am Especially in the context of memory copy/fill routines, you'll often see the indirect-Y address mode "(),Y" combined with INY/DEY + fixup for the high-byte instead of incrementing/decrementing the full pointer in zeropage like you laid out.
I've finally managed to figure out how to do the same thing using "(),Y" and for my code it comes in as 63 cycles per character moved, as opposed to 72 cycles the other way, which feels pretty significant, particularly if I'm moving quite a chunk of characters.
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Mike »

Robbie wrote:I've finally managed to figure out how to do the same thing using "(),Y" and for my code it comes in as 63 cycles per character moved, as opposed to 72 cycles the other way, which feels pretty significant, particularly if I'm moving quite a chunk of characters.
Well, a common memory copy like pointed to at 6502.org normally weighs in at 17 cycles per byte moved (LDA [6 cycles, worst case] + STA [6 cycles] + INY [2 cycles] + BNE [3 cycles, branch taken, same page]), ignoring the time spent in the fix-up code. So you either were counting the cycles wrong, or your routine does something more complicated than a simple byte copy.
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

Mike wrote: Fri Oct 09, 2020 1:22 am So you either were counting the cycles wrong, or your routine does something more complicated than a simple byte copy.
Yeah Mike, byte copy is the core of the code, but the main loop iterates between two addresses, moving each byte up one.

There are lots of 16-bit increments, decrements and comparisons, which I'm sure I can streamline.

I shall have a mess with it this afternoon, but if you're able to look it over when I'm done, I'd really appreciate your input.
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

After much tinkering, I think I've got my first mini-program working ok, and I can't see any way to make it more efficient.
If anyone's masochistic enough I'd appreciate comments for improvements, or advice on where I've done things in unconventional ways.
No pressure as I can imagine that reading someone else's ML is pretty dreary, but I'm keen to improve and have never written any ML that's worked before, so I'm really proud! :D

The code is for a text editor, and basically inserts a new character at the address referenced in ($5FFB-$5FFC), moving everything after that point to the end of the file ($5FFD-$5FFE) up one.

Variables:
$5FFD-$5FFE = Last address in text file => Activated to $FD-$FE and used as iterator
$5FFB-$5FFC = Cursor / Insertion Point => Activated to $FB -$FC
$5FFF = Character to insert

The test data I used inserts W into 'HELLO ORLD":
@5FFD : 09 40 (End of File - becomes Iterator)
@5FFB : 06 40 (Insertion point)
@5FFF : 57 (char to insert) = W
@4000 "HELLO ORLD"

Code: Select all

@2000 		LDA 	$5FFB 	:	STA 	$FB	; Activate variables to ZP
		LDA 	$5FFC	:	STA	$FC
		LDA	$5FFD	:	STA	$FD
		LDA	$5FFE	:	STA	$FE

		LDX	#$00
		LDY	#$01
		
	-L	LDA	($FD,X)	; Copy character to next address
		STA	($FD),Y
		
		LDA	$FD	; 16-bit Compare Iterator to Insertion point
		CMP	$FB
		BNE	-Z
		LDA	$FE
		CMP	$FC
		BNE	-Z

		LDA	$5FFF	; Insert new character
		STA	($FD,X)
		
		INC	$5FFD	; 16-bit Increment End of File
		BNE ->
		INC	$5FFE
	-@	RTS
	
	-Z	LDA	$FD	;  16-bit Decrement Iterator
		BNE	->
		DEC	$FE
	-@	DEC	$FD
	
		LDA	#$00	; Loop
		BEQ	-L
User avatar
Mike
Herr VC
Posts: 4841
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Mike »

For small inserts, that code is surely o.k. However with slightly larger inserts, one of the copy routines in 6502.org could easily be adapted to your parameter definition for an easy 3x speed up.

Actually you should though do a read up on the buffer gap data structure for text editors. This data structure allows inserts (and deletes) at essentially zero cost - only when the cursor is moved, small amounts of the text need to be copied to keep the gap at the new cursor position.

Just this one:
Robbie wrote:

Code: Select all

		LDA	#$00	; Loop
		BEQ	-L
... should really be:

Code: Select all

JMP -L
... ;)

Greetings,

Michael
Robbie
Vic 20 Dabbler
Posts: 84
Joined: Tue Aug 11, 2020 4:36 am
Location: England

Re: First steps in ML (split/OT from: Vixen - [...])

Post by Robbie »

Thanks Mike, I shall have a look at those things.

I can't believe I missed that 6502 has the JMP opcode! :roll:
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: First steps in ML (split/OT from: Vixen - [...])

Post by chysn »

Robbie wrote: Sun Oct 11, 2020 2:09 pm I can't believe I missed that 6502 has the JMP opcode! :roll:
:D

But if you ever do want to do an unconditional relative branch, try

Code: Select all

CLV
BVC label
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
srowe
Vic 20 Scientist
Posts: 1340
Joined: Mon Jun 16, 2014 3:19 pm

Re: First steps in ML (split/OT from: Vixen - [...])

Post by srowe »

That still occupies 3 bytes and takes 5/6 cycles when a JMP only takes 3 cycles. Having relocatable code isn't usually worth that.
Post Reply