I have this code:
jsr cls
ldx #$00 ;loads 0 into x
stx tmp ; stores x in tmp
ldx #<scr1
ldy #>scr1
printToScreen
stx zpb 0
sty zpb 1
lda (zpb),y
ldx tmp. ; loads x from tmp
beq done
sta screen_start,x
inx
stx tmp ; stores new x in tmp
bne printToScreen
done
rts
tmp = $C8
zpb = $fb
scr1 byte 'some text'
byte 0
I want to create routine which prints a string to the screen. The arguments are the address of the string and the X register, which is used as a counter. Since X is used inside the function as well I'm storing its value in the tmp variable.
But this code prints nothing. I'm totally new to assembly, so probably I don't understand how this is supposed to work. Please see code comments. What am I doing wrong here?
CodePudding user response:
jsr cls
ldy #$10 ; loads $10 into x as a string length
lda #<scr1
sta zpb 0
lda #>scr1
sta zpb 1
printToScreen
lda (zpb),y
sta screen_start,y
dey
bne printToScreen
rts
I would do that way. To be honest I didn't test the code I've written above. I've changed it the way I think it should be done.
Concerning your code: It is not needed to overwrite zpb and zpb 1 in every loop iteration. You forgot to set Y index register before you do "lda (zpb),y" - and probably it should be zero. After "ldx tmp" you don't compare it wth anything (should be cpx #something) so as default you compare it with zero (beq done) and cpu quits the program because X==0. So your program writes one byte somewhere in the memory and just exits.
CodePudding user response:
Is .X supposed to be the length of the string that is being printed?
Your current code:
printToScreen
stx zpb 0
sty zpb 1
lda (zpb),y
ldx tmp.
beq done
sta screen_start,x
inx
stx tmp
bne printToScreen
What I think you are trying to do is:
- Pass the address of the string in .X and .Y
- Store this in
zpb
- Fetch the bytes using indirect addressing at zpb and store them to the screen at
screen_start
A couple of problems:
lda (zpb),y
is the correct addressing mode, but you never initialize the .Y register. So the .Y register at the first call is actually using the most significant byte of the address you passed to begin with- The combination of
inx
stx tmp
bne printToScreen
.. When you do theinx
andbne
you are saying "increase .X, save it, and if it is not equal to zero, branch toprintToScreen
". But that effectively looks like you are trying to copy 256 bytes. - Notwithstanding never initializing .Y, you also never change it, so it will effectively always get the same byte pointed to (indirectly) by
zpb
. - You are initialzing .X with #$00 and storing it in
tmp
, but that really doesn't need to be done with what I think you are trying to do. - If .X is supposed to be the length then you aren't actually defining that anywhere...you are effectively doing this for 256 bytes (unless that's what you want?)
- You keep storing .X and .Y in
zpb
, but that precludes you from actually using .X and .Y
That said, what I think might work for you is:
jsr cls ; assuming this is a routine to clear the screen
ldx #<scr1
ldy #>scr1
stx zpb 0
sty zpb 1
ldy #$00
printToScreen
lda (zpb),y
beq done
sta screen_start,y
iny
bne printToScreen
done
rts
scr1 .asc 'some text'
.byt 0
What this will do is:
- store the location of
scr1
inzpb
- loop through
scr1
and store it atscreen_start
, and end if:- the current byte is the 0 byte (it checks this before doing the actual copy); or
- .Y becomes zero (again, after initialization)