【问题标题】:Indirect Y indexed addressing mode in MOS 6502MOS 6502 中的间接 Y 索引寻址模式
【发布时间】:2017-09-17 09:15:42
【问题描述】:

我正在查看来自here 的 MOS 6502 指令集的寻址模式。

indirect, Y-indexed的描述与其他来源有点不一致。

它说

OPC ($LL),Y 操作数是有效地址加Y带进位;有效地址是零页地址处的字

但是其他消息来源没有提到带有进位位的加法。喜欢here

计算有效地址的正确方法是什么?

【问题讨论】:

    标签: assembly 6502


    【解决方案1】:

    如有疑问,最好查看官方文档。
    MOS here 有一个引人入胜的原始数据表 还有 [1]

    INDIRECT INDEXED ADDRESSING - 在间接索引寻址(称为( Indirect) , Y)中,指令的第二个字节指向页面零中的内存位置。
    这个内存位置的内容被添加到Y 索引寄存器的内容中,结果是有效地址的低八位
    这个加法的进位被添加到下一页零的内容 内存位置,结果是有效地址的高八位。

    所以第二次加法是通过携带进行的。
    您可以将其视为Immediate(在little-endian 中)指向的16 位字与Y 寄存器零扩展为16 位的内容之间的16 位加法。

    例如,如果内存和Y

    All values in hex
    
    Address    00  01  02  03  04 ...
    Value      80  02  f3  00  03 ...
    
    Y = 90
    

    那么(0), Y就是

      low 8 bits:  80 + 90     = 10   (with carry = 1)
      high 8 bits: 02 + 00 + 1 = 03 
    

    提供0310 的有效地址。同样(3), Y

      low 8 bits:  00 + 90     = 90   (with carry = 0)
      high 8 bits: 03 + 00 + 0 = 03 
    

    这会产生一个值为0390 的有效地址。

    您可以看到,当考虑 16 位量时,0 处的字是 0280Y0090,它们的加法如预期的那样是 0310

    长描述只是对这些事实进行编码:a)Indirect 指向的 16 位字存储在小端 b)Y 是零扩展的 c)加法是 16 位的。

    在 C 中,它应该是这样的

    uint16_t effective_addr(uint8_t indirect)
    {
       //Take the INDIRECT immediate and make a pointer to a 16-bit LE word out of it
       //In C int-to-ptr is implementation define, we assume an identity map here
       uint16_t* page_zero_ptr = (uint16_t*)indirect;
    
       //The Y register is 8-bit, we consider it a 16-bit one instead
       //Assume y is of unsigned type 
       uint16_t  y_zero_ext = y;
    
       //Do a 16-bit addition, this is equivalent to two 8-bit additions with carry
       return *page_zero_ptr + y;
    }
    

    【讨论】:

    • 这消除了混乱。我认为进位指的是指令之前进位位的状态。就像我们在“带进位相加”中所指的那样。如果我现在清楚了,这意味着Y被添加到带有进位的地址中?也感谢你的 C 实现和官方文档的链接。我将在以后提及这一点。我还在问题中编辑 64 位汇编等效项。你能确认这是否正确吗?
    • @Ajay,通常最好将后续问题作为新问题发布,因为主要编辑会使未来的读者感到困惑。该实现对我来说看起来不正确,但我不知道您想如何使用它。间接索引地址 (IAM) 模式采用 8 位立即地址和隐式 Y 寄存器,您的输入似乎不同。除此之外,您正在用rbx + \reg 指向的两个字节制作一个 big-endian 字并读取它(没有添加?)。这似乎不是 IAM 所做的。此外,这可以通过越来越多的惯用 x86-64 指令来实现。
    • 很抱歉编辑了后续问题。我会把它回滚。
    • @Olaf 这样做的原因是因为 6502 在每个时钟周期 上进行读取或写入以简化逻辑。因此,它必须在执行加法的第二部分时进行读取或写入,因此它不妨在加法的低位部分之后读取地址,这样如果没有进位,它可以节省一个周期。这是一个article on 6502 timing and bus access,它很好地解释了它。请注意,数据来自 Visual 6502,它是真实 6502 的晶体管级仿真。
    • 对于 6502 变体在 5 个周期内支持“lda ($0),y”,当 $00-$01 保持 $FF FF 并且 Y==1 时,它需要能够处理 7-在采样第四个字节和生成第五个地址之间的时间范围内的宽进位链。 65C02 执行的虚拟周期与 6502 有所不同,在跨页加载的情况下,我认为它会进行虚拟取指,取指指令后面的字节,而不是从错误地址取指,但实际上并没有足够的时间让它在跨页场景中生成正确的地址,无需等待一个周期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-02
    • 2018-05-31
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多