6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 10, 2024 3:55 pm

All times are UTC




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Jun 09, 2011 5:08 am 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
Hi all,
I have been playing around with printing strings in 6502 in a C64 emulator with code like this:


Code:
    LDY #$00
L0
    LDA L1,Y
    CMP #0
    BEQ L2
    JSR $FFD2
    INY
    JMP L0
L1
    .byte "hello world",0
L2
    RTS


and this works just nice and dandy :)

Now I want to try outputting some numbers (floating point) to debug floating point routines in my compiler.

This means I need to move a number to FAC1 (easy), convert it to ASCII string (easy), and then output the ASCII string pointed to by A/Y to the screen using $FFD2 (how?)

Code:
;load floating point number into FAC1
    LDA <L1
    LDY >L1
    JSR $BBA2
   
;convert number in FAC1 to ASCII (pointer in A & Y)
    JSR $BDDD
   
;How to print string at location in A & Y to screen using $FFD2?
;$FFD2 expects character in A?
   
    JMP L2
L1
    .byte "$87 $48 $00 $00 $00",0
L2
    RTS


Any ideas?

Would I need to store A/Y in memory somwhere (zerpage?) and load A from there in a loop like I did in the first example from a label?

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 6:12 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8538
Location: Southern California
Your CMP #0 is redundant, because it is already done automatically as part of the LDA L1,Y. Since the INY will always give a non-0 result, you could save a byte by replacing the JMP L0 with BNE L0.

See my Tip of the Day #38 here about raising the level of the assembly language by using macros when possible. (I don't know if it's possible with the assembler you're using for the C64.) Your source code will become more concise and need less debugging to get it going, with no penalty in speed or memory in the 6502 computer you're going to run it on. The overhead is all borne by the assembler.

Quote:
and then output the ASCII string pointed to by A/Y to the screen using $FFD2 (how?)

Code:
        STX   STR_ADR      ; (Swap these two if A holds the low byte of the str addr.)
        STA   STR_ADR+1
        LDY   #0

loop:   LDA   (STR_ADR),Y
        BEQ   done
        JSR   $FFD2        ; If the routine fools with Y, be sure to save and restore it.
        INY
        BNE   loop         ; (65C02 would normally use BRA, but BNE will work here.)
done:

STR_ADR will have to be in zero page, but the string it points does not need to be.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 7:00 am 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
GARTHWILSON wrote:
Your CMP #0 is redundant, because it is already done automatically as part of the LDA L1,Y. Since the INY will always give a non-0 result, you could save a byte by replacing the JMP L0 with BNE L0.


Ok, thanks for that tip...I obviously didn't know that little gem :)

GARTHWILSON wrote:
See my Tip of the Day #38 here about raising the level of the assembly language by using macros when possible. (I don't know if it's possible with the assembler you're using for the C64.) Your source code will become more concise and need less debugging to get it going, with no penalty in speed or memory in the 6502 computer you're going to run it on. The overhead is all borne by the assembler.


Nice tips Garth, cheers! Unfortunately the assember I am using win2c64 (http://www.aartbik.com/MISC/c64.html) doesn't currently support macros :(

Maybe I can add into my code generator a crude macro facility and do that part myself :)

Quote:
and then output the ASCII string pointed to by A/Y to the screen using $FFD2 (how?)

Code:
        STX   STR_ADR      ; (Swap these two if A holds the low byte of the str addr.)
        STA   STR_ADR+1
        LDY   #0

loop:   LDA   (STR_ADR),Y
        BEQ   done
        JSR   $FFD2        ; If the routine fools with Y, be sure to save and restore it.
        INY
        BNE   loop         ; (65C02 would normally use BRA, but BNE will work here.)
done:

STR_ADR will have to be in zero page, but the string it points does not need to be.[/quote]

Nice! Thanks mate :)

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 7:23 am 
Offline

Joined: Tue Nov 18, 2003 8:41 pm
Posts: 250
I think you want that

STX STR_ADR

to be

STY STR_ADR


Personally. I'd do it like this:

Code:
 sty string_adr
 sta string_adr+1
 ldy #$00
 beq ENTER

LOOP
 jsr FFD2
 iny
ENTER
 lda (string_adr),y
 bne LOOP


but that does assume that the string will never be more than 256 bytes


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 8:05 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8538
Location: Southern California
Quote:
I think you want that

STX STR_ADR

to be

STY STR_ADR

Woops, yeah, he did say A/Y, not A/X.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 12:12 pm 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
Thanks for the help so far guys :)

I have two questions though still:

1) I haven't had much luck in getting the ASCII value of the number to print out though...I am starting to think that it isn't a null-terminated string, but something else.

I don't suppose if any of you know the format of a FAC1 number converted to ASCII using the FOUT ($BDDD) C64 ROM routine?

I don't suppose it might have the string length first, then the string digits?

I haven't been able to find out anything online so far...

2) Has any of you had experience using an assembler called KickStart?

It seems pretty good, has a scripting language built into it, and also does macros :)

I am thinking of using it now in my project ;)

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 1:55 pm 
Offline

Joined: Fri Aug 30, 2002 2:05 pm
Posts: 347
Location: UK
Quote:
I don't suppose if any of you know the format of a FAC1 number converted to ASCII using the FOUT ($BDDD) C64 ROM routine?

It should return a null terminated string with the pointer to it in AY.

Lee.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 8:51 pm 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
leeeeee wrote:
Quote:
I don't suppose if any of you know the format of a FAC1 number converted to ASCII using the FOUT ($BDDD) C64 ROM routine?

It should return a null terminated string with the pointer to it in AY.

Lee.


Ok, then the only thing I can think of going wrong is that I am outputting the c64 floating point number (5-byte) in the wrong order then to the assembler...

I will have to try it the other way around, thanks :)

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 09, 2011 9:00 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1042
Location: near Heidelberg, Germany
paul_nicholls wrote:
Code:
;load floating point number into FAC1
    LDA <L1
    LDY >L1
    JSR $BBA2



Shouldn't that be
Code:
;load floating point number into FAC1
    LDA #<L1
    LDY #>L1
    JSR $BBA2


Note the '#' signs for immediate addressing mode, so the low and high byte of the address L1 are loaded into A and Y respectively, not the values read from memory at adresses <L1 and >L2...

André


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 09, 2011 9:06 pm 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
fachat wrote:
paul_nicholls wrote:
Code:
;load floating point number into FAC1
    LDA <L1
    LDY >L1
    JSR $BBA2



Shouldn't that be
Code:
;load floating point number into FAC1
    LDA #<L1
    LDY #>L1
    JSR $BBA2


Note the '#' signs for immediate addressing mode, so the low and high byte of the address L1 are loaded into A and Y respectively, not the values read from memory at adresses <L1 and >L2...

André


OMG! I didn't notice that foobar...D'OH!

I will fix that and try again :oops:

Thanks André...

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Jun 09, 2011 9:14 pm 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
It works!!! Yay!

This input:

Code:
program Test;
begin
  WriteLn(102);
end;


Generated this assembler:

Code:
    .org $0800 ; start at BASIC
    .byte $00 $0c $08 $0a $00 $9e $20 $32 ; encode SYS 2064
    .byte $30 $36 $34 $00 $00 $00 $00 $00 ; as BASIC line

Lab2064
    JMP main
main
;load floating point number into FAC1
    LDA #<L1
    LDY #>L1
    JSR $BBA2
   
;convert number in FAC1 to ASCII (pointer in A & Y)
    JSR $BDDD
   
;store address in zero-page
    STA $FB
    STY $FB + 1
    LDY #$00
L0
    LDA ($FB),Y
    BEQ L2
    JSR $FFD2
    INY
    JMP L0
L1
    .byte $87 $4C $00 $00 $00
L2
    RTS


And this in turn ran on the C64 emulator and printed out the number I entered in the program :)

Thanks all!!

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 17, 2011 10:27 pm 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
AAAHHHH!!! sometimes changing assemblers can be a real pain in the arse! LOL

I had this code which worked using win2c64:
Code:
    LDY #$00
L0
    LDA L1,Y
    BEQ L2
    JSR $FFD2
    INY
    JMP L0
L1
    .byte "hello world",0
L2
    RTS


but when I switched over to Kick Assembler and altered the code so it would compile like so:

Code:
    ldy #$00
L0
    lda L1,y
    beq L2
    jsr $ffd2
    iny
    jmp L0
L1
    .text "hello world"
    .byte 0
L2
    rts


outputting the code in the c64 emulator stopped working, ie printing out garbage + changing colours. I couldn't figure out why for days!!

I only discovered yesterday that with the Kick Assembler, I had to put the text to output in CAPITAL LETTERS to work!!

Code:
 .text "HELLO WORLD"


Damn that was annoying! :D

I hope this helps someone else :)

EDITED: removed the cmp #0 from the code...

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


Last edited by paul_nicholls on Sat Jun 18, 2011 2:43 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jun 17, 2011 10:34 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8538
Location: Southern California
And again, for efficiency, remember you never need CMP #0 after an LDA. It's an implied automatic integral part of it. Same with ADC and others.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 18, 2011 2:16 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8479
Location: Midwestern USA
paul_nicholls wrote:
AAAHHHH!!! sometimes changing assemblers can be a real pain in the arse! LOL

I had this code which worked using win2c64:
Code:
    LDY #$00
L0
    LDA L1,Y
    CMP #0
    BEQ L2
    JSR $FFD2
    INY
    JMP L0
L1
    .byte "hello world",0
L2
    RTS


but when I switched over to Kick Assembler and altered the code so it would compile like so:

Code:
    ldy #$00
L0
    lda L1,y
    cmp #0
    beq L2
    jsr $ffd2
    iny
    jmp L0
L1
    .text "hello world"
    .byte 0
L2
    rts


outputting the code in the c64 emulator stopped working, ie printing out garbage + changing colours. I couldn't figure out why for days!!

I only discovered yesterday that with the Kick Assembler, I had to put the text to output in CAPITAL LETTERS to work!!

Code:
 .text "HELLO WORLD"


Damn that was annoying! :D

I hope this helps someone else :)

cheers,
Paul

The reason has nothing to do with the assembler per se, and everything to do with PETSCII, Commodore's modified form of ASCII. HELLO WORLD in ASCII comes out as hello world in PETSCII on an assembler that is not CBM-specific. hello world in ASCII is not part of the PETSCII character set, and instead maps to PET graphics and control characters. win2c64 maps your text strings into PETSCII, so it seems to work right.

Also, as Garth previously noted, CMP #0 is unnecessary. The status register flags are automatically conditioned by load, arithmetic or logical operations (including R-M-W instructions). Hence the acting of loading a null into .A sets the .Z flag, causing the BEQ branch to succeed.

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


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jun 18, 2011 2:44 am 
Offline

Joined: Wed Jan 19, 2011 10:20 pm
Posts: 42
GARTHWILSON wrote:
And again, for efficiency, remember you never need CMP #0 after an LDA. It's an implied automatic integral part of it. Same with ADC and others.


Sorry guys...I remember that little tidbit now...I just hadn't removed the cmp #0 from the code example :( My bad...I have removed it now :)

BigDumbDinosaur wrote:
The reason has nothing to do with the assembler per se, and everything to do with PETSCII, Commodore's modified form of ASCII. HELLO WORLD in ASCII comes out as hello world in PETSCII on an assembler that is not CBM-specific. hello world in ASCII is not part of the PETSCII character set, and instead maps to PET graphics and control characters. win2c64 maps your text strings into PETSCII, so it seems to work right.


Thanks BigDumbDinosaur I guessed that might have been the reason after I got it working :D

I might look up the PETSCII codes and see if I can maybe convert upper-case chars to PETSCII shifted versions, and lowercase characters to normal upper-case characters as I am doing now :)

This could be handy if I want to do lower/upper-case characters in the other text mode on the C64...

Speaking of which, does any here know how to set the c64 text mode to upper-case only, or both lower/upper case?

cheers,
Paul

_________________
"The plastic veneer of civilization is easily melted in the heat of the moment" - Paul Nicholls


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


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: