首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >6502 randy hyde子例程问题"JSR INCRTN“

6502 randy hyde子例程问题"JSR INCRTN“
EN

Stack Overflow用户
提问于 2019-12-14 00:34:43
回答 2查看 136关注 0票数 0

我正在遵循兰迪·海德的书“使用6502汇编语言”中的A教程。在第14章第7节中,他写了"jsr incrtn“,问题是他没有创建一个名为incrtn的子例程,这里是完整的代码,

代码语言:javascript
复制
    PRTSTR:
     STA ASAVE
     STY YSAVE
     PLA ;GET RETURN ADDRESS FROM
     STA RTNADR ;THE 6502 STACK
     PLA
     STA RTNADR+$1
     ;
     JSR INCRTN ;INCREMEOT THE RETURN ADDRESS
     LDY #$0
     LDA (RTNADR),Y ;GET L.O. ADDRESS OF STRING
     STA ZPAGE
     INY
     LDA (RTNADR),Y ;GET H.O.ADDRESS OF STRING
     STA ZPAGE+$1
     ;
     JSR INCRTN ;MOVE RTNADR PAST THE ADDRESS
     JSR INCRTN ;BYTES
     ;
     ;
     ; AT THIS POINT, ZPAGE POINTS TO THE STRING WHICH
     ; IS SUPPOSED TO BE OUTPUT
     ;
     DEY ;RESET Y REG TO ZERO
     LDA (ZPAGE),Y ;GET THE LENGTH OF THE STRING
     STA LENGTH ;AND STORE IT IN "LENGTH"
     PRTS1 INY ;MOVE TO THE NEXT CHARACTER
     CPY LENGTH ;ARE WE THROUGH YET?
     BEQ PRTS2
     ;
     LDA (ZPAGE),Y ;GET THIS CHARACTER
     JSR COUT ;AND OUTPUT
     JMP PRTS1 ;MOVE TO NEXT CHAR AND REPEAT
     ;
     PRTS2 LDA ASAVE ;RESTORE THE REGISTERS
     LDY YSAVE
     JMP (RTNADR) ;SIMULATE AN RTS
     ;
     ;
     ;
     ASAVE EPZ $0 ;ZERO PAGE WORKSPACE
     YSAVE EPZ ASAVE+$1
     ZPAGE EPZ YSAVE+$1
     RTNADR EPZ ZPAGE+$2
     COUT EQU $FDED ;COUT ROUTINE
     END

有谁可以帮我?

更新,如果有人想知道如何以更简单的方式打印文本,这里有一些有效的代码

代码语言:javascript
复制
           LDX #$0
  LOOP     INX 
           LDA STRING,X 
           JSR $FDF0 
           CPX STRING 
           BLT LOOP 
           RTS  
  STRING   STR "hello world"
         END
EN

回答 2

Stack Overflow用户

发布于 2019-12-14 03:59:23

在处理器具有堆栈或足够的寄存器之前,参数通常通过“内联”参数传递,即在JSR或call类型的指令之后传递参数,方法是将值或指针直接放在call指令之后,要求被调用者在返回以恢复调用者时跳过它们。

正如你所知道的,调用指令捕获一个返回地址(以某种方式,在某个地方:可能在堆栈或子例程的代码内存中!),该返回地址可用于获取放置在调用指令之后的参数。*返回地址递增以获得连续的参数,完成后,需要再递增一次(递增1或2)以返回调用者的实际代码,而不是返回内联参数,这些参数当然是数据,而不是代码。

对于这个PRTSTR,海德使用的样式就是这个内联参数机制。

下面是此PRTSTR的用法

代码语言:javascript
复制
    ...
STRING STR "HELLO THERE"
    ...
START
    JSR PRTSTR    # call to print string
    ADR STRING    # pointer parameter passed "inline" within code, 
                  # this is data, to be used and then skipped over by print string
    ...           # actual return location to resume code in START

考虑到6502同时具有调用堆栈和寄存器,使用内联机制进行调用有点倒退,但肯定已经完成了。(内联参数传递机制早于调用堆栈和大量寄存器,就像我们今天在现代处理器中所拥有的那样。)

在堆栈但寄存器很少的情况下,一些具有大量参数的调用可以将参数放到堆栈上,而另一些调用则通过传入可用的寄存器来完成。

在纯汇编代码中,您可以为每个函数创建自定义调用约定。只有C和其他高级语言的出现才会产生对规范、常规和可预测的调用约定的要求,这些约定可以在编译器中编码。

我必须承认我不理解三条JSR INCRTN指令中的第一条。(我理解后两条指令-它们跳过指向字符串的指针(JSR后面的内联参数),由于指针是两个字节,地址需要递增2个字节-但这三条指令中的第一条在我看来是错误的。)* 6502上没有ADR操作码,所以我不得不假设它是一个汇编伪运算码,形成了一个指向标签的2字节指针。

我的假设在某种程度上得到了海德在14-6中的确认,其中说:

代码语言:javascript
复制
    JSR SASIGN ;STRING ASSIGNMENT
    ADR DEST ;DEST = SOURCE
    ADR SOURCE

上面是一个7字节的序列(即1个用于JSR操作码,2个用于SASIGN (JSR的操作数),2个分别用于ADR DESTADR SOURCE)。

因此,当代码执行JSR INCRTN时,RTNADRRTNADR + 1处的16位变量需要加1。

我相信,通过更直接地使用索引寄存器作为指针,而不是在索引寄存器Y中使用内存间接和整数,可以大大改善这个代码序列。

此外,由于我无法理解第一个JSR INCRTN,并且第二个被调用两次,因此它也可以简单地递增2,而不是递增1,两次。

票数 4
EN

Stack Overflow用户

发布于 2020-01-27 05:13:38

这个INCRTN子例程应该看起来像这样:

代码语言:javascript
复制
INCRTN:
    INC RTNADR      ; Add 1 to RTNADR
    BNE INCRTNEX
    INC RTNADR+$01  ; If the pointer passes a page boundary,
INCRTNEX:           ; advance to the next page.
    RTS

这将在RTNADR对象上执行16位增量。

另一种需要在A中输入值,但更灵活的替代版本是使用以下内容:

代码语言:javascript
复制
ADD2RTN:
    CLC
    ADC RTNADR
    STA RTNADR
    BCC ADD2RTNX
    INC RTNADR+$01
ADD2RTNX:
    RTS

这会将一个8位值(在A中提供)添加到16位RTNADR对象。

我提供的第一段代码完全符合您给出的示例,而第二段代码的性能要快得多,需要添加超过两个字节的代码。

在您给出的代码中,您可以替换加载字符串地址并推进返回地址的代码,如下所示:

代码语言:javascript
复制
LDY #$01
LDA (RTNADR),Y
STA ZPAGE
INY
LDA (RTNADR),Y
STA ZPAGE+$1
LDA #03
JSR ADD2RTN
;
LDY #0        ; Manually reset Y to 0 instead of using DEY twice to save time

它的执行速度比原始代码快几个周期(JSR和RTS各需要6个周期,而INC使用5个周期,因为RTNADR在0页上),并且不会添加任何代码。在处理6502时,节省的每个字节和执行周期都会提高性能。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59326514

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档