易码技术论坛

 找回密码
 加入易码
搜索
查看: 169816|回复: 7

[收集]程序跳转的几种方法~

[复制链接]
发表于 2005-1-23 16:52:00 | 显示全部楼层
我有个小建议~当JMP较短时~可以使用SEC BCS的方法跳转~这样当移动这段程序到别的地方时就不必改动跳转了~因为BCS是相对的~
 楼主| 发表于 2005-1-23 16:54:00 | 显示全部楼层
嗯,是的,很多情况用sec,bcs就可以搞定,但对那些每个分支处理得代码较长(象GVmaker解释器)分支很多时就不合适了
发表于 2005-1-23 17:30:00 | 显示全部楼层
为什么把JMP$XXYY送C000~DFFF这块呢?看不明白~
 楼主| 发表于 2005-1-23 17:37:00 | 显示全部楼层
这个方法果然BT,看不太明白,难道是修改中断列表?
发表于 2005-1-23 17:45:00 | 显示全部楼层
利用$C000-$DFFF与$4000-$5FFF的映射关系(RAM04)
[此贴子已经被作者于2005-1-23 17:52:44编辑过]

发表于 2005-1-23 17:51:00 | 显示全部楼层
原来是忽悠我们的~故意复杂化~
 楼主| 发表于 2005-1-23 18:54:00 | 显示全部楼层
以下是引用QIQI在2005-1-23 18:45:37的发言:

怎么我的帖子被删了?

这个方法不安全还是怎么的?


??那个帖子被删了?

不是在上面吗?
 楼主| 发表于 2005-1-23 16:38:28 | 显示全部楼层 |阅读模式
我们编程时很可能会碰到需要分支程序的地方,也就是要根据不同的情况程序需要跳转到不同的地方。当分支比较少时,用

                               LDA Value
                               CMP Value1
                               BNE Label1
                               JMP Address1
Label1:                    CMP Value2
                               BNE Label2
                               JMP Address2
                                  ....  

就可以搞定了,但可以想象,当分支一多,这种方法是比较繁琐的,这是我们一般用查表的方法:

1。查表法:

                LDA Value               // 此处的Value是计算值或是用户响应值.
                LDX #$00
Compare_Value:  CMP Value_List,X
                BEQ Found
                INX
                CPX #Count              // 此处的Count是分支的个数.
                BCC Compare_Value       // 找下一个.
                BCS Illegal_Value       // 无此情况.
Found:      TXA
                ASL
                TAX
                LDA Addr_List,X         // 取得要转向的地址低字节
                STA $80
                LDA Addr_List+1,X       // 取得要转向的地址低字节
                STA $81
                JMP ($0080)这种方法对分支多时显然比一开始讲的有效的多,但程序要用到$80,$81两个零叶地址,如果恰好这两个地址也存储了数据,那么就必须先对其进行保护,跳转后再恢复,这样也很繁琐了(当然这种情况一般是可以避免的)。所以这里我们有另几种方法,可以不需要用到额外的地址:2。利用RTI(SAILOR-HB首创)我们知道,RTI是“ReTurn from Int”即“从中断中返回”的意思。6502在执行到RTI指令的时候,会做以下工作:先从堆栈中弹出一个数据,送入标志寄存器P;然后再弹出两个数据,依次送给PC的低字节和高字节;最后转向PC所指向的地方继续运行。(汗,你不知道?那你就看下这个帖子http://wqx.4irc.com/bbs/viewthread.php?fpage=1&tid=240先;其实之前我也不知道^_^),这样我们就可以这样实现同样的功能:                LDA Value
                LDX #$00
Compare_Value:  CMP Value_List,X
                BEQ Found
                INX
                CPX #Count
                BCC Compare_Value
                BCS Illegal_Value
Found:      TXA
                ASL
                TAX
                LDA Addr_List+1,X
                PHA
                LDA Addr_List,X
                PHA
                PHP
                RTI

可以看出,在这个程序里,我们使用了两个PHA和一个PHP来模拟出了6502处理器遇到BRK指令后所做的各项工作。是不是比上面的方法好一些?有一点要注意,就是取地址的指令,原方法是先取低字节,这种方法则要先取高字节。

不过这种方法不常见,可能用过的人也不多吧(所以偶尔用一下让想修改你程序的人看不明白也不错,呵呵),那我们就再看一个很好懂的方法:

3.动态修改跳转地址

                LDA Value
                LDX #$00
Compare_Value:  CMP Value_List,X
                BEQ Found
                INX
                CPX #Count
                BCC Compare_Value
                BCS Illegal_Value
Found:       TXA
                ASL
                TAX
                LDA Addr_List,X
                STA Jump+1              //动态修改jmp的跳转地址
                LDA Addr_List+1,X
                STA Jump+2
Jump:       JMP $xxxx                                 

这种方法不需要多解释吧,NC2k及以上的GVmaker解释器都是用这个处理GVmaker虚拟指令的(NC1020的用的是第一种方法)。但也要注意一点,这段代码必须放在RAM中,否则,呵呵。。。

除了上面的方法还有其他的吗?没有了?真的没有了?呵呵,其实方法还是有的,比如:

4。利用堆栈

XU的《6502奥秘》上有介绍:当调用子程序时,系统自动将子程序 后一指令的地址 - 1 送堆栈。这样,我们有:

                LDA Value
                LDY #$00
Compare_Value:  CMP Value_List,Y

                BEQ Found
                INY
                CPY #Count
                BCC Compare_Value
                BCS Illegal_Value

Found:        TYA

                  ASL

                  TAY

                  JSR Jump


Jump:         TSX
                  INX
                  LDA Addr_List`,y(注意,这里是 Addr_List`,里面的数据为相应的跳转地址-1)

                  STA $0100,x
                  INX
                  LDA Addr_List`+1,y
                  STA $0100,x
                  RTS

呵呵,这种方法是不是有些BT?除非想把程序搞复杂,否则还是不要用为好^_^

[此贴子已经被作者于2005-1-23 16:40:30编辑过]

您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-24 11:38 , Processed in 0.013616 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表