Pushing put pointer and routine into stack?
Clash Royale CLAN TAG#URR8PPP
up vote
2
down vote
favorite
I am learning how to program the atari 800 by examining some tutorial code that came with the IDE/Assembler I am using. I am using the MADS assembler for this.
putchar_ptr = $346
csrhinh = 752
character = $80
rowcrs = $54
colcrs = $55
org $2000
.proc main
mva #1 csrhinh
mva #6 rowcrs
mva #16 colcrs
mva #0 character
next_character
ldx character
cpx #.len text
beq stop
lda text,x
jsr putchar
inc character
jmp next_character
stop jmp stop
.proc putchar
tax
lda putchar_ptr+$1
pha
lda putchar_ptr
pha
txa
rts
.endp
.local text
.byte 'Hi there!',$9b,'new line'
.endl
.endp
run main
I did reference the atari 800 manual and the MAD-Assembler manual but I didn't find anything. The specific question I am asking is, in the putchar procedure, why is the accumulator pushed onto the stack? From what I can tell all it is loaded with is the location of the routine pointer on the first push and the put pointer on the second. A few possibilities I see are that I could be mistaken on what the routine actually is (the atari 800 manual wasn't very informative about that) or the push might point to something else other than the stack. I would say the latter is true but then we aren't pushing the character we are trying to print because of the txa instruction and the accumulator being reloaded. Thank you in advance to anyone who responds here!
assembly 6502 atari-800
New contributor
add a comment |Â
up vote
2
down vote
favorite
I am learning how to program the atari 800 by examining some tutorial code that came with the IDE/Assembler I am using. I am using the MADS assembler for this.
putchar_ptr = $346
csrhinh = 752
character = $80
rowcrs = $54
colcrs = $55
org $2000
.proc main
mva #1 csrhinh
mva #6 rowcrs
mva #16 colcrs
mva #0 character
next_character
ldx character
cpx #.len text
beq stop
lda text,x
jsr putchar
inc character
jmp next_character
stop jmp stop
.proc putchar
tax
lda putchar_ptr+$1
pha
lda putchar_ptr
pha
txa
rts
.endp
.local text
.byte 'Hi there!',$9b,'new line'
.endl
.endp
run main
I did reference the atari 800 manual and the MAD-Assembler manual but I didn't find anything. The specific question I am asking is, in the putchar procedure, why is the accumulator pushed onto the stack? From what I can tell all it is loaded with is the location of the routine pointer on the first push and the put pointer on the second. A few possibilities I see are that I could be mistaken on what the routine actually is (the atari 800 manual wasn't very informative about that) or the push might point to something else other than the stack. I would say the latter is true but then we aren't pushing the character we are trying to print because of the txa instruction and the accumulator being reloaded. Thank you in advance to anyone who responds here!
assembly 6502 atari-800
New contributor
The routine does an indirect jump to the contents ofputchar_ptr
, becauserts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.
â dirkt
44 mins ago
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am learning how to program the atari 800 by examining some tutorial code that came with the IDE/Assembler I am using. I am using the MADS assembler for this.
putchar_ptr = $346
csrhinh = 752
character = $80
rowcrs = $54
colcrs = $55
org $2000
.proc main
mva #1 csrhinh
mva #6 rowcrs
mva #16 colcrs
mva #0 character
next_character
ldx character
cpx #.len text
beq stop
lda text,x
jsr putchar
inc character
jmp next_character
stop jmp stop
.proc putchar
tax
lda putchar_ptr+$1
pha
lda putchar_ptr
pha
txa
rts
.endp
.local text
.byte 'Hi there!',$9b,'new line'
.endl
.endp
run main
I did reference the atari 800 manual and the MAD-Assembler manual but I didn't find anything. The specific question I am asking is, in the putchar procedure, why is the accumulator pushed onto the stack? From what I can tell all it is loaded with is the location of the routine pointer on the first push and the put pointer on the second. A few possibilities I see are that I could be mistaken on what the routine actually is (the atari 800 manual wasn't very informative about that) or the push might point to something else other than the stack. I would say the latter is true but then we aren't pushing the character we are trying to print because of the txa instruction and the accumulator being reloaded. Thank you in advance to anyone who responds here!
assembly 6502 atari-800
New contributor
I am learning how to program the atari 800 by examining some tutorial code that came with the IDE/Assembler I am using. I am using the MADS assembler for this.
putchar_ptr = $346
csrhinh = 752
character = $80
rowcrs = $54
colcrs = $55
org $2000
.proc main
mva #1 csrhinh
mva #6 rowcrs
mva #16 colcrs
mva #0 character
next_character
ldx character
cpx #.len text
beq stop
lda text,x
jsr putchar
inc character
jmp next_character
stop jmp stop
.proc putchar
tax
lda putchar_ptr+$1
pha
lda putchar_ptr
pha
txa
rts
.endp
.local text
.byte 'Hi there!',$9b,'new line'
.endl
.endp
run main
I did reference the atari 800 manual and the MAD-Assembler manual but I didn't find anything. The specific question I am asking is, in the putchar procedure, why is the accumulator pushed onto the stack? From what I can tell all it is loaded with is the location of the routine pointer on the first push and the put pointer on the second. A few possibilities I see are that I could be mistaken on what the routine actually is (the atari 800 manual wasn't very informative about that) or the push might point to something else other than the stack. I would say the latter is true but then we aren't pushing the character we are trying to print because of the txa instruction and the accumulator being reloaded. Thank you in advance to anyone who responds here!
assembly 6502 atari-800
assembly 6502 atari-800
New contributor
New contributor
New contributor
asked 56 mins ago
user115898
13218
13218
New contributor
New contributor
The routine does an indirect jump to the contents ofputchar_ptr
, becauserts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.
â dirkt
44 mins ago
add a comment |Â
The routine does an indirect jump to the contents ofputchar_ptr
, becauserts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.
â dirkt
44 mins ago
The routine does an indirect jump to the contents of
putchar_ptr
, because rts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.â dirkt
44 mins ago
The routine does an indirect jump to the contents of
putchar_ptr
, because rts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.â dirkt
44 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
That's a usual way to an indirect JSR
with a 6502. The 6502 does not support indirect subroutine calls (*1), so it has to be done in software. Indirect subroutine calls are a usefull tool for function calls into OS/library functions which may change during runtime or by configuration - like when redirecting output to a different driver. By using a routine pointer for certein calls it's easy to overload/replace them by just changeing that pointer.
Lacking the indirect call the 6502 needs to emulate an indirect subroutine call in software by calling a subruetine which in turn pushes the pointer onto the stack (high first) and then jumping there by 'returning' to it. Adds some cycles, but also preserves the flexibility (*2)
In detail it works like this
LDA ptr+1 * high byte of target routine address
PHA * push down the stack
LDA ptr * high byte of target routine address
PHA * push down the stack
rts * 'returning' to the address at TOS
The TAX
/TXA
around is just to preserve the parameter (character to be printed) aroud the stack handling code.
Now, having said that, in above context it's a real waste of code and cycles. The pointer used is at a fixed location and not indexed again. Thus the whole routine can be replaced by an indirect jump.
.proc putchar
JMP (putchar_ptr)
.endp
Try it - only 3 bytes and 5 cycles, compared to 9 bytes and 23 cycles. This waste of space (and time) is often seen from programmers who lerned of the great use of the RTS
-'trick' for jump tables (like for an OS function switcher) and then use it even for non table indext ways, ignoring the handy JMP
indirect.
The NES-Dev Wiki offers a nice page about this topic.
*1 - On of the few realy missing instructions that could have been added rather easy. And a major hint that the 6502 wasn't defigned with a general purpose CPU in mind, but rather a microcontroller with it's fixed address locations, where such redirection is done during compile/linkage time.
*2 - Some OS did speed up this by puting a JMP
-opcode in front of every callable pointer, allowing a user programm to just JSR
ing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
That's a usual way to an indirect JSR
with a 6502. The 6502 does not support indirect subroutine calls (*1), so it has to be done in software. Indirect subroutine calls are a usefull tool for function calls into OS/library functions which may change during runtime or by configuration - like when redirecting output to a different driver. By using a routine pointer for certein calls it's easy to overload/replace them by just changeing that pointer.
Lacking the indirect call the 6502 needs to emulate an indirect subroutine call in software by calling a subruetine which in turn pushes the pointer onto the stack (high first) and then jumping there by 'returning' to it. Adds some cycles, but also preserves the flexibility (*2)
In detail it works like this
LDA ptr+1 * high byte of target routine address
PHA * push down the stack
LDA ptr * high byte of target routine address
PHA * push down the stack
rts * 'returning' to the address at TOS
The TAX
/TXA
around is just to preserve the parameter (character to be printed) aroud the stack handling code.
Now, having said that, in above context it's a real waste of code and cycles. The pointer used is at a fixed location and not indexed again. Thus the whole routine can be replaced by an indirect jump.
.proc putchar
JMP (putchar_ptr)
.endp
Try it - only 3 bytes and 5 cycles, compared to 9 bytes and 23 cycles. This waste of space (and time) is often seen from programmers who lerned of the great use of the RTS
-'trick' for jump tables (like for an OS function switcher) and then use it even for non table indext ways, ignoring the handy JMP
indirect.
The NES-Dev Wiki offers a nice page about this topic.
*1 - On of the few realy missing instructions that could have been added rather easy. And a major hint that the 6502 wasn't defigned with a general purpose CPU in mind, but rather a microcontroller with it's fixed address locations, where such redirection is done during compile/linkage time.
*2 - Some OS did speed up this by puting a JMP
-opcode in front of every callable pointer, allowing a user programm to just JSR
ing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.
add a comment |Â
up vote
2
down vote
That's a usual way to an indirect JSR
with a 6502. The 6502 does not support indirect subroutine calls (*1), so it has to be done in software. Indirect subroutine calls are a usefull tool for function calls into OS/library functions which may change during runtime or by configuration - like when redirecting output to a different driver. By using a routine pointer for certein calls it's easy to overload/replace them by just changeing that pointer.
Lacking the indirect call the 6502 needs to emulate an indirect subroutine call in software by calling a subruetine which in turn pushes the pointer onto the stack (high first) and then jumping there by 'returning' to it. Adds some cycles, but also preserves the flexibility (*2)
In detail it works like this
LDA ptr+1 * high byte of target routine address
PHA * push down the stack
LDA ptr * high byte of target routine address
PHA * push down the stack
rts * 'returning' to the address at TOS
The TAX
/TXA
around is just to preserve the parameter (character to be printed) aroud the stack handling code.
Now, having said that, in above context it's a real waste of code and cycles. The pointer used is at a fixed location and not indexed again. Thus the whole routine can be replaced by an indirect jump.
.proc putchar
JMP (putchar_ptr)
.endp
Try it - only 3 bytes and 5 cycles, compared to 9 bytes and 23 cycles. This waste of space (and time) is often seen from programmers who lerned of the great use of the RTS
-'trick' for jump tables (like for an OS function switcher) and then use it even for non table indext ways, ignoring the handy JMP
indirect.
The NES-Dev Wiki offers a nice page about this topic.
*1 - On of the few realy missing instructions that could have been added rather easy. And a major hint that the 6502 wasn't defigned with a general purpose CPU in mind, but rather a microcontroller with it's fixed address locations, where such redirection is done during compile/linkage time.
*2 - Some OS did speed up this by puting a JMP
-opcode in front of every callable pointer, allowing a user programm to just JSR
ing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.
add a comment |Â
up vote
2
down vote
up vote
2
down vote
That's a usual way to an indirect JSR
with a 6502. The 6502 does not support indirect subroutine calls (*1), so it has to be done in software. Indirect subroutine calls are a usefull tool for function calls into OS/library functions which may change during runtime or by configuration - like when redirecting output to a different driver. By using a routine pointer for certein calls it's easy to overload/replace them by just changeing that pointer.
Lacking the indirect call the 6502 needs to emulate an indirect subroutine call in software by calling a subruetine which in turn pushes the pointer onto the stack (high first) and then jumping there by 'returning' to it. Adds some cycles, but also preserves the flexibility (*2)
In detail it works like this
LDA ptr+1 * high byte of target routine address
PHA * push down the stack
LDA ptr * high byte of target routine address
PHA * push down the stack
rts * 'returning' to the address at TOS
The TAX
/TXA
around is just to preserve the parameter (character to be printed) aroud the stack handling code.
Now, having said that, in above context it's a real waste of code and cycles. The pointer used is at a fixed location and not indexed again. Thus the whole routine can be replaced by an indirect jump.
.proc putchar
JMP (putchar_ptr)
.endp
Try it - only 3 bytes and 5 cycles, compared to 9 bytes and 23 cycles. This waste of space (and time) is often seen from programmers who lerned of the great use of the RTS
-'trick' for jump tables (like for an OS function switcher) and then use it even for non table indext ways, ignoring the handy JMP
indirect.
The NES-Dev Wiki offers a nice page about this topic.
*1 - On of the few realy missing instructions that could have been added rather easy. And a major hint that the 6502 wasn't defigned with a general purpose CPU in mind, but rather a microcontroller with it's fixed address locations, where such redirection is done during compile/linkage time.
*2 - Some OS did speed up this by puting a JMP
-opcode in front of every callable pointer, allowing a user programm to just JSR
ing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.
That's a usual way to an indirect JSR
with a 6502. The 6502 does not support indirect subroutine calls (*1), so it has to be done in software. Indirect subroutine calls are a usefull tool for function calls into OS/library functions which may change during runtime or by configuration - like when redirecting output to a different driver. By using a routine pointer for certein calls it's easy to overload/replace them by just changeing that pointer.
Lacking the indirect call the 6502 needs to emulate an indirect subroutine call in software by calling a subruetine which in turn pushes the pointer onto the stack (high first) and then jumping there by 'returning' to it. Adds some cycles, but also preserves the flexibility (*2)
In detail it works like this
LDA ptr+1 * high byte of target routine address
PHA * push down the stack
LDA ptr * high byte of target routine address
PHA * push down the stack
rts * 'returning' to the address at TOS
The TAX
/TXA
around is just to preserve the parameter (character to be printed) aroud the stack handling code.
Now, having said that, in above context it's a real waste of code and cycles. The pointer used is at a fixed location and not indexed again. Thus the whole routine can be replaced by an indirect jump.
.proc putchar
JMP (putchar_ptr)
.endp
Try it - only 3 bytes and 5 cycles, compared to 9 bytes and 23 cycles. This waste of space (and time) is often seen from programmers who lerned of the great use of the RTS
-'trick' for jump tables (like for an OS function switcher) and then use it even for non table indext ways, ignoring the handy JMP
indirect.
The NES-Dev Wiki offers a nice page about this topic.
*1 - On of the few realy missing instructions that could have been added rather easy. And a major hint that the 6502 wasn't defigned with a general purpose CPU in mind, but rather a microcontroller with it's fixed address locations, where such redirection is done during compile/linkage time.
*2 - Some OS did speed up this by puting a JMP
-opcode in front of every callable pointer, allowing a user programm to just JSR
ing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.
edited 21 mins ago
answered 38 mins ago
Raffzahn
38.6k486155
38.6k486155
add a comment |Â
add a comment |Â
user115898 is a new contributor. Be nice, and check out our Code of Conduct.
user115898 is a new contributor. Be nice, and check out our Code of Conduct.
user115898 is a new contributor. Be nice, and check out our Code of Conduct.
user115898 is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f8022%2fpushing-put-pointer-and-routine-into-stack%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
The routine does an indirect jump to the contents of
putchar_ptr
, becauserts
jump to the contents just pushed on the stack. I don't know why they are doing it that way instead of using a plain indirect jump.â dirkt
44 mins ago