Pushing put pointer and routine into stack?

The name of the pictureThe name of the pictureThe name of the pictureClash 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!










share|improve this question







New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • 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














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!










share|improve this question







New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.



















  • 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












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!










share|improve this question







New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











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






share|improve this question







New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question







New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question






New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 56 mins ago









user115898

13218




13218




New contributor




user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






user115898 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











  • 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















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










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 JSRing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.






share|improve this answer






















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "648"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    noCode: true, onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    user115898 is a new contributor. Be nice, and check out our Code of Conduct.









     

    draft saved


    draft discarded


















    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






























    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 JSRing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.






    share|improve this answer


























      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 JSRing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.






      share|improve this answer
























        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 JSRing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.






        share|improve this answer














        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 JSRing via the pointer-1 address, greatly reduceing the overhead to 3 cycles.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 21 mins ago

























        answered 38 mins ago









        Raffzahn

        38.6k486155




        38.6k486155




















            user115898 is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            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.













             


            draft saved


            draft discarded














            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













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            Installing NextGIS Connect into QGIS 3?

            One-line joke