C64汇编中如何向子程序传递内存地址参数?
方案1:零页指针传递(最优通用方案)
6502架构下最常用的双字节地址传递方式是使用零页双字节变量做参数,配合(ind),Y间接寻址实现,完全不需要依赖X寄存器做索引,也能兼容KERNAL调用场景:
传参实现
首先你的param要定义在零页区域(C64的$0000~$00FF区域,访问速度最快),调用子程序前写入字符串的高低字节地址:
; 调用示例:传递scr1地址 lda #<scr1 ; 取scr1地址的低字节 sta param lda #>scr1 ; 取scr1地址的高字节 sta param+1 jsr print_str ; 调用打印函数
可复用打印函数实现
函数入口先保存所有用到的寄存器,出口恢复,完全不影响外部寄存器状态,也不怕内部调用KERNAL例程修改寄存器:
print_str pha ; 备份A寄存器 txa pha ; 备份X寄存器 tya pha ; 备份Y寄存器 ldy #$00 copy_loop lda (param),y ; 间接寻址:读取param存的地址 + Y偏移的内容 beq print_done sta screen_start,y iny bne copy_loop print_done pla ; 恢复Y寄存器 tay pla ; 恢复X寄存器 tax pla ; 恢复A寄存器 rts
方案2:内联参数传递(更省调用代码)
如果希望调用代码更简洁,可以把参数直接写在jsr指令后面,函数自动从返回地址位置读取参数并调整返回地址,不需要手动操作零页变量:
调用示例
jsr print_str word scr1 ; 直接把字符串地址存在jsr指令后面
函数实现
print_str pha txa pha tya pha tsx ; 从栈中读取返回地址(jsr执行后压栈的是下一条指令地址,也就是参数的位置) lda $0101,x sta param lda $0102,x sta param+1 ; 读取2字节地址参数存入临时指针 ldy #0 lda (param),y sta tmp_ptr iny lda (param),y sta tmp_ptr+1 ; 调整返回地址,跳过2字节参数,避免返回后执行参数内容 clc lda param adc #2 sta $0101,x lda param+1 adc #0 sta $0102,x ; 打印逻辑和方案1一致 ldy #0 copy_loop lda (tmp_ptr),y beq done sta screen_start,y iny bne copy_loop done pla tay pla tax pla rts
常见问题解答
- 关于代码重复:6502汇编开发中完全不接受这种同质化代码重复,C64可用内存仅64KB,重复逻辑会快速占用宝贵的存储空间。可复用函数实现难度很低,只要掌握寄存器压栈恢复、零页指针两个核心技巧就能实现绝大多数通用函数。
- 关于寄存器占用:6502的栈有256字节空间,函数入口备份寄存器、出口恢复的开销极小,只要不是极端深度的嵌套调用完全够用,不需要担心寄存器冲突问题。
内容的提问来源于stack exchange,提问作者user2297996
相关产品推荐
相关产品推荐

