Sjasm循环宏定义问题:DLOOP_TOP未替换实际值求助
实现类JavaScript风格的Z80 Sjasm宏循环语法
需求目标
希望通过Sjasm宏实现类似JavaScript的do-while/do-djnz循环语法,预期使用方式如下:
L_E52A: ld hl, $58A0 ld c, $12 _do inc hl ld b, $1E _do ld (hl), a inc hl _djnz inc hl dec c _while nz ret
当前问题代码
以下是尝试编写的宏代码,但无法正常运行,核心问题是DLOOP_TOP未被替换为实际的循环标签地址:
DLOOP_3 = 0 DLOOP_2 = 0 DLOOP_TOP = 0 MACRO DLOOP_PUSH arg DLOOP_3 = DLOOP_2 DLOOP_2 = DLOOP_TOP DLOOP_TOP = arg ENDM MACRO DLOOP_POP DLOOP_TOP = DLOOP_2 DLOOP_2 = DLOOP_3 DLOOP_3 = 0 ENDM MACRO _do DLOOP_PUSH $ DLOOP_TOP: ENDM MACRO _while flag jr flag, DLOOP_TOP DLOOP_POP ENDM MACRO _djnz djnz DLOOP_TOP DLOOP_POP ENDM
问题根源
- 符号与变量混淆:Sjasm中,跳转指令需要引用标签符号,而非变量存储的地址数值。你用
DLOOP_TOP = arg存储的是地址值,但DLOOP_TOP:定义的是一个固定标签名,两者没有关联,导致跳转时无法正确解析。 - 全局变量冲突:嵌套循环时,全局变量
DLOOP_TOP/DLOOP_2/DLOOP_3会被内层循环覆盖,外层循环的标签信息丢失,跳转逻辑混乱。
解决方案
利用唯一标签生成的思路,通过计数器为每个循环生成独立的标签名,避免嵌套冲突,同时让跳转指令能正确引用对应标签:
; 初始化循环计数器,用于生成唯一标签后缀 DLOOP_COUNT = 0 MACRO _do ; 递增计数器,确保每个循环有唯一标识 DLOOP_COUNT = DLOOP_COUNT + 1 ; 定义当前循环的顶部标签,格式为DLOOP_1、DLOOP_2... DLOOP_{DLOOP_COUNT}: ; 记录当前循环层级,供后续结束宏使用 DLOOP_CURRENT = DLOOP_COUNT ENDM MACRO _while flag ; 跳转到当前层级的循环顶部 jr flag, DLOOP_{DLOOP_CURRENT} ; 循环结束,递减计数器释放层级 DLOOP_COUNT = DLOOP_COUNT - 1 ENDM MACRO _djnz ; DJNZ跳转到当前层级的循环顶部 djnz DLOOP_{DLOOP_CURRENT} ; 循环结束,递减计数器释放层级 DLOOP_COUNT = DLOOP_COUNT - 1 ENDM
工作原理
- 每次调用
_do时,计数器DLOOP_COUNT递增,生成唯一的循环标签(如DLOOP_1、DLOOP_2),同时记录当前层级到DLOOP_CURRENT。 _while和_djnz通过DLOOP_CURRENT引用对应层级的标签,执行跳转逻辑。- 循环结束后递减计数器,确保嵌套循环的层级正确回溯。
展开效果示例
你的目标代码展开后会变成以下可正常汇编的Z80代码:
L_E52A: ld hl, $58A0 ld c, $12 ; 外层_do展开 DLOOP_1: DLOOP_CURRENT = 1 inc hl ld b, $1E ; 内层_do展开 DLOOP_COUNT = 2 DLOOP_2: DLOOP_CURRENT = 2 ld (hl), a inc hl ; 内层_djnz展开 djnz DLOOP_2 DLOOP_COUNT = 1 inc hl dec c ; 外层_while nz展开 jr nz, DLOOP_1 DLOOP_COUNT = 0 ret
内容的提问来源于stack exchange,提问作者Rui Costa
相关产品推荐
相关产品推荐

