我正在尝试理解6502汇编中的控制流。
假设我有以下代码:
ControlFlow:
lda mem
cmp #1
bne .sub_one
cmp #2
bne .sub_two
.sub_one:
; sub routine one goes here
jmp .done ; <-------------- without this jmp, .sub_two will execute
.sub_two:
; sub routine two goes here
.done:
rts就我个人而言,我更喜欢switch语句或其他一些控制流结构。上面的JMP也与我有关。似乎有一种更好的方法来处理多个情况,而不需要这种类型的意大利面条代码。
发布于 2013-01-19 17:29:14
实际上,没有更好的方法,但可能会有改进,比如将FlowControl作为子例程调用,然后返回RTS。
这是主要的流程。
jsr ControlFlow
; main routine continues here下面是子例程。
ControlFlow:
lda mem
cmp #1
bne .sub_one
cmp #2
bne .sub_two
cmp #3
bne .sub_three
; case else here
rts
.sub_one:
; sub routine one goes here
rts
.sub_two:
; sub routine two goes here
rts
.sub_three:
; sub routine three goes here
rts如果子例程太长,则需要使用前面提到的JMPs。
.jump_to_sub_one
jmp .sub_one
.jump_to_sub_two
jmp .sub_two
.jump_to_sub_three
jmp .sub_three
ControlFlow:
lda mem
cmp #1
bne .jump_to_sub_one
cmp #2
bne .jump_to_sub_two
cmp #3
bne .jump_to_sub_three
; case else here
rts
.sub_one:
; sub routine one goes here
rts
.sub_two:
; sub routine two goes here
rts
.sub_three:
; sub routine three goes here
rts这就是它是如何完成的,不幸的是,没有更好的方法。这适用于许多汇编语言,如果不是全部的话。
发布于 2013-01-20 17:20:39
如果案例的数量足够大,跳转表可能会很有用。在左边,有一个跳转到标签的模板(未测试),它将正确的地址推送到堆栈并返回。在右边有一个基于jsr的比较例程,它将在从每个子例程返回后在标签_out:处继续。进位逻辑在6502上反转,这意味着进位将被设置为if (Acc >= Imm)。
; goto label[n] vs. call label[n]
lda variable
cmp #MAX_PLUS_ONE
bcs _out
tax
lda table_hi, X
pha vs. sta jsrcmd+2
lda table_lo, X
pha vs. sta jsrcmd+1
rts vs. jsrcmd: jsr 1000 ; self modify
_out: 发布于 2013-08-18 22:27:06
6502提供以下控制程序流程,即修改PC寄存器。
(或RTS,如果将stack)
.P导致跳过重置向量<代码>H215<代码>F216就这样。如果你想要更复杂的东西,你需要使用上面的一个或多个来创建它。
实现switch语句的一种方法是首先创建一个指针表,指向switch语句中涉及的所有例程。根据例程的低位字节和高位字节对它们进行拆分:
switchtab_lo .db >routine1, >routine2, >routine3
switchtab_hi .db <routine1, <routine2, <routine3
(我永远记不住>表示低字节还是高字节,不同的汇编程序可能有不同的语法)
然后,假设您想要切换的值是.X格式的,并且vector是两个不从页面末尾开始的字节(为了避免JMP间接错误),并且您已经确保它是一个有效的值:
lda switchtab_lo,X
sta vector
lda switchtab_hi,X
sta vector+1
jmp (vector)每次需要切换时这样做都很乏味,但这就是为什么高级语言被发明出来的原因。
https://stackoverflow.com/questions/14411017
复制相似问题