Assembly 在TI-84 Plus CE上设置中断

Assembly 在TI-84 Plus CE上设置中断,assembly,interrupt,interrupt-handling,texas-instruments,z80,Assembly,Interrupt,Interrupt Handling,Texas Instruments,Z80,我正试图设置一个中断来捕捉按下ON按钮的动作 这是我目前的代码: SetInterrupt: di ; copy the 4 bytes from InterruptVectorTable to cursorImage ; (I chose cursorImage because it's on a 512-byte boundary, 0E30800h) ld hl, InterruptVectorTable ld de, cursorImage ld bc, 4

我正试图设置一个中断来捕捉按下ON按钮的动作

这是我目前的代码:

SetInterrupt:
 di
  ; copy the 4 bytes from InterruptVectorTable to cursorImage
  ; (I chose cursorImage because it's on a 512-byte boundary, 0E30800h)
 ld   hl, InterruptVectorTable
 ld   de, cursorImage
 ld   bc, 4
 ldir
  ; clone the same 4 bytes into the rest of the 256-byte interrupt vector table
 ld   hl, cursorImage
 ld   de, cursorImage + 4
 ld   bc, 252
 ldir
  ; load the address of the new interrupt vector in the i register
  ;  and set interrupt mode to 2
 ld   hl, cursorImage >> 8 & 0ffffh
 ld   i, hl
 im   2
 ei
 ret
FillScreen:
  ; fills the screen with black pixels
 ld a, 0
 ld hl, vRam
 ld bc, 320*240*2
 call _MemSet
 ret
InterruptVectorTable:
  ; try to call FillScreen whenever there's an interrupt
 .db 00, FillScreen & 0ffh, FillScreen >> 8 & 0ffh, FillScreen >> 16 & 0ffh
然而,这只是冻结了我的计算器(因为我不能使用任何键来停止程序)

我相信这个问题是可以中断的。我真的不明白这个表应该如何格式化。我在下面链接的ez80应用程序说明中说,“每个向量都是指向_vectptr段的4字节地址”,但ez80使用24位地址,因此我不确定如何构造每个向量

非常感谢您的帮助


我已阅读/试图阅读的参考资料:

  • [注:这是针对z80的 TI-84+CE运行ez80]

非常感谢您的帮助

因此,将此聊天作为答案发布,因为评论部分的长度限制和格式让我很恼火,而您上面的“问题”使这种“答案”有点合法

根据“设置中断”PDF文档,在第13页,地址的32位格式是清晰的,如果是地址0x123456,内存应包含字节
56 34 12 00
(不确定最后一个
00
是否可以是垃圾,或者必须是零,我想对于未来的兼容性,零更好,尽管我想eZ80F91将只使用24位,忽略最后8位)

因此,您原始问题中的定义很可能是错误的,
00
应该在3个字节之后,而不是前面

三个字节的
.dl
应该足够了,还可以通过
.db
添加额外的垃圾字节(以避免手动标签分解为字节)

我只熟悉经典的Z80,所以我不知道你的代码到底出了什么问题,但是一般的原则和东西可能值得一看:

  • 检查设备是否真的有eZ80F91(“-like”?还有谁在制造它的克隆?我猜它要么是Zilog的原创,要么不是,不可能是“-like”),因为任何其他eZ80变体只有8位
    I
    寄存器,需要不同的中断表设置和中断处理(可以尝试
    ld hl,0x1234
    ld i,hl
    ld hl,0
    ld hl,i
    并检查
    hl
    中的值是否返回到
    0x1234

  • 在代码初始化向量表时,检查调试器中生成的二进制文件或内存是否包含预期值

  • 检查设备描述(如果可用),触发哪种中断,以及何时触发,为什么您实际希望按钮“开”触发中断?(例如,ZX频谱-我熟悉的Z80机器-没有键盘中断,键盘必须通过代码进行轮询,唯一的中断是在显示光束的垂直回程开始时触发的,即PAL/SECAM ZX型号为~50Hz,而美国NTSC型号为~60Hz,导致游戏在美国ZX克隆上运行稍微快一点…IIRCTI计算器有定时器中断,比如100Hz,但我从未深入研究过,所以这可能是完全错误的信息)

  • 确保您处于“ADL”模式,而不是“Z80”兼容模式

  • 您的“FillScreen”例程正在尝试返回,但它似乎没有像序言/尾声那样的适当中断,因此无论它返回到哪里,它都会损坏寄存器的内容,并且不会通过
    reti
    返回

  • 您还可以从
    SetInterrupt
    例程返回到某个程序中……在安装中断的同时,正在运行什么

您可以先尝试“空”中断处理程序,如

FillScreen:
    ei        ; not sure if there's implicit DI - if yes, EI needed
    reti
要查看主线程中运行的代码是否正常(中断处理程序是否正常)。请注意,如果它是普通的计算器处理程序,并且它需要自己的中断处理程序,那么仅仅安装空中断将妨碍已经实现的功能……也许您永远不应该从代码中返回(主线程,如调用setInterrupt的地方)并执行自己的无限主循环)

如果要在中断中执行更多操作,必须在主线程中保留代码的寄存器值,例如,如果知道主线程不使用备用寄存器,则可以通过

interruptHandler:
    di        ; disable interrupts until done
    ; (especially if you know your interrupt may take longer to run)

    ; preserve current register values (by switching to alternate ones)
    ex   af,af
    exx
    ; do your stuff here (destroying alternate register values)
    ; which is OK, if your interrupt handler is the only code using them
    ...
    ; restore the register values back (by switching to original ones)
    exx
    ex   af,af
    ; return from interrupt
    ei
    reti
或者,如果知道堆栈上总是有足够的空间,可以使用
push/pop
来保留原始寄存器值

或者,如果堆栈空间可能过于紧张,但您有单独的内存块可用作中断处理程序堆栈,则可以先切换到该堆栈:

interruptHandler:
    di
    ; preserve current stack pointer (self-modify code)
    ld   (interruptHandler_SP+1),sp
    ld   sp,top_of_interrupt_stack
    ; preserve registers as needed (AF with flags being a MUST)
    push ...
    ; do your stuff here
    ...
    ; restore registers as needed
    pop ...
    ; restore stack pointer
interruptHandler_SP:
    ld   sp,0x123456     ; this will be overwritten at start of handler
    ; return from interrupt
    ei
    reti
仔细想想,您的中断处理程序显然不是中断处理程序,因此即使它正确运行一次,这也是您的设备中发生的最后一件正确的事情

此外,填充屏幕是一个有点不幸的选择(因为它需要很长时间才能完成,而且很难看到它两次)

作为一种快速测试,可以执行以下操作:

testInterrupt:
  di
  push   af
  ; increment first byte of video ram to make some visible "noise"
  ld     a,(vRam)
  inc    a
  ld     (vRam),a
  ; restore flags, enable interrupts, return back to main code
  pop    af
  ei
  reti
一般来说,中断处理程序应该非常快速和微小,清除vram之类的任务应该留给主代码完成,中断应该只设置一些全局标志,需要清除vram(在几个T周期内完成),然后主代码可以在循环中测试各种事件标志,并对“清除vram”作出反应通过清除vram进行标记。处理程序中不应有任何严重的“biz”逻辑,只将即将出现的状态/数据(如串行总线I/O上的数据)收集到一些标志/缓冲区中,并让中断之外的主代码以完整逻辑处理这些标志/缓冲区


也许你会考虑尝试一些经典的Z80,除非你真的很想要EZ80F91。经典的Z80有很多可用的材料,不同的机器和仿真器,因为它是非常流行的CPU(例如我是Z80的一个)专家。“由于ZX频谱计算机,我在1991年至1996年期间为它做了一些演示和游戏。.就是这样