标签: 6502

CPU仿真并锁定到特定的时钟速度

如果你已经阅读了我的另一个问题,你就会知道我本周末花了6502 CPU模拟器作为编程练习.

CPU模拟器大部分是完整的,并且从我的有限测试看起来相当准确,但它运行速度非常快,我想把它降低到机器的实际时钟速度.

我目前的测试循环是这样的:

    // Just loop infinitely.
    while (1 == 1)
    {                
        CPU.ClockCyclesBeforeNext--;

        if (CPU.ClockCyclesBeforeNext <= 0)
        {
            // Find out how many clock cycles this instruction will take
            CPU.ClockCyclesBeforeNext = CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].CpuCycles;

            // Run the instruction
            CPU.ExecuteInstruction(CPU.Memory[CPU.PC]);

            // Debugging Info
            CPU.DumpDebug();
            Console.WriteLine(CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].ArgumentLength);

            // Move to next instruction
            CPU.PC += 1 + CPU.OpcodeMapper.Map[CPU.Memory[CPU.PC]].ArgumentLength;                                        
        }
    }
Run Code Online (Sandbox Code Playgroud)

如您所知,每个操作码需要一段特定的时间才能完成,所以在我倒计时CPU周期时,我不会运行下一条指令.这提供了操作码之间的适当时序,它只是整个事情快速运行.

目标CPU的速度是1.79mhz,但是我想要时钟问题的任何解决方案,即使我增加了复杂性,也要保持1.79mhz的速度,所以我不需要调整它.

有任何想法吗?

6502 emulation clockrates low-level

27
推荐指数
4
解决办法
1万
查看次数

6502 CPU仿真

这是周末,所以我通过写一个爱好项目来度过整周的编程.

我昨天编写了一个MOS 6502 CPU仿真器的框架,实现了寄存器,堆栈,内存和所有操作码.(链接到下面的来源)

我可以在我编写的调试器中手动运行一系列操作,但是我想加载一个NES rom并按指令指向程序计数器,我认为这是找到有缺陷的操作码的最快方法.

我写了一个快速的NES rom加载程序并将ROM库加载到CPU内存中.

问题是我不知道操作码是如何编码的.我知道操作码本身遵循每个操作码一个字节的模式,该模式唯一地标识操作码,

0 - BRK
1 - ORA (D,X)
2 - COP b
Run Code Online (Sandbox Code Playgroud)

等等

但是我不确定我应该在哪里找到操作码参数.是直接跟随的字节吗?在绝对记忆中,我想它可能不是一个字节而是一个短.

有人熟悉这个CPU的内存模型吗?

编辑:我意识到这可能是在黑暗中拍摄,但我希望有一些老学校的苹果和Commodore黑客潜伏在这里.

编辑:感谢大家的帮助.在我实施适当的更改以对齐每个操作后,CPU可以加载并运行Mario Brothers.除了循环等待Start之外它什么也没做,但它是一个好兆头:)

我上传了这个来源:

http://www.codeplex.com/Cpu6502/SourceControl/DirectoryView.aspx?SourcePath=&changeSetId=1810

如果有人想知道模拟器是如何工作的,那么它很容易理解.至少没有优化,但是再次,我在2.4ghz机器上模拟一个以2mhz运行的CPU :)

6502 machine-language emulation

18
推荐指数
1
解决办法
5785
查看次数

快速签名的16位除以7表示6502

我正在研究一个6502 cpu的汇编语言程序,我发现我需要一个快速尽可能快的七分程序,特别是一个可以获得16位分红的程序.

我熟悉这里发现的例程,但是对七分法例程进行了概括,发现它非常复杂,粗略地检查了一般算法(使用整数除法)

x/7~ =(x + x/8 + x/64 ...)/ 8

表示要处理16位范围,由于6502的单个累加器寄存器和6502上各个存储器位移的相对慢速,可能需要100多个周期才能完成.

我认为查找表可能会有所帮助,但在6502上,我当然只限于256字节或更少的查找表.为此,可以假设存在两个256字节的查找表xdiv7和xmod7,当使用无符号的单字节值作为表的索引时,可以快速获得字节除以7或模数的结果分别为7.但是,我不确定如何利用它们来查找完整16位范围的值.

与此同时,我还需要一个模7算法,尽管理想情况下,可以通过除法得到的解决方案也会产生mod7结果.如果需要额外的预计算表,只要所有表的总内存需求不超过约3k,我就可以添加这些表.

虽然我最终需要一个带符号的除法算法,但是一个无符号算法就足够了,因为我可以根据需要将它推广到一个有符号的例程.

任何帮助将不胜感激.

assembly 6502 division integer-division micro-optimization

13
推荐指数
2
解决办法
640
查看次数

对于8位系统上类似于lisp的语言的VM感兴趣

我正在寻找可以在8位微处理器上运行的推荐虚拟机并支持动态语言.我想要一个VM解决方案,因为我认为在代码密度,可移植性和拥有更小的解释器的能力方面的好处,为更大的程序留下更多空间.

我的目标是在6502微处理器之类的东西上运行一个完整的LOGO解释器,遵循"Apple II的LOGO"语法.

我已经看过对PyMite,Java"微版"的引用,当然现在可以使用20世纪70年代的UCSD p-System源代码.

欢迎提出建议.

lisp 6502 logo-lang vm-implementation

12
推荐指数
3
解决办法
1031
查看次数

了解指令如何翻译(计算机体系结构)

有点令人困惑的问题.但我真的在寻找学习一些低级编程.事情是,开发板像Arduino/Etc.真的隐藏了很多正在发生的事情.

我花了一些时间学习计算机体系结构,逻辑/门/顺序逻辑/等等.(我甚至去了解与半导体和电子相关的物理学,只是为了知道到底发生了什么,就像以及如何使用CMOS晶体管等制造盖茨.

但那就是它结束的地方......我希望能够理解一个指令(如Hex /或汇编/等等代码)是如何通过一台简单的计算机(我用过的很多书)直接从盖茨到计算机....没有真正的介于两者之间).甚至是简单的东西.....将值存储在寄存器或存储器位置(并且可能打印到像素?或某些东西).

我认为最有趣的事情可能是最终编写模拟器.我有使用高级语言的经验,但我听说像6502这样的东西可能是一个好的开始,因为你使用了很多汇编,并且指令集不是太大.

有谁知道任何可能有帮助的资源/想法/书籍?我已经阅读了"计算系统的元素",虽然......这是一本很好的书,我真的不觉得它真的发生了什么,看到它发生了.这可能更像是一个Electronics.stackexchange问​​题,如果是这样,我道歉.

embedded assembly 6502 emulation computer-architecture

12
推荐指数
3
解决办法
2280
查看次数

6502轻量级压缩算法

我正在Commodore PET(为了好玩)的双盒式磁带录像机上实现虚拟内存,我正在写作.如果您有兴趣,我到目前为止在http://github.com/chitselb/pettil.

我打算使用PET的原生192字节盒式数据文件格式.哦,是的,一切只有32K的RAM .我已经在语言中嵌入了Woz优秀且非常节省内存的Sweet-16解释器.

Forth块(通常)为1024字节.为块ID添加两个字节会使可用的虚拟地址空间达到64 meg,这比磁带上的容量更大.将存在"播放"牌组(设备1)和"记录"牌组(设备2),并且FLUSH将涉及将整个虚拟存储器从一个驱动器复制到另一个驱动器.为什么要在风车上倾斜?因为当天早些时候,盒式磁带是大多数PET用户所拥有的,包括在内.

大多数数据将是Forth代码的屏幕,在此实现中将是1000字节的文本和24字节的换行表,因为我也在利用PET ROM屏幕编辑器.我正在寻找的是任何可能(可能)为此目的击败简单的运行长度编码的建议,但没有像Lempel-Ziv这样复杂的东西的CPU和内存开销.除了"忘记它"之外的所有建议都表示赞赏.

compression assembly 6502 forth

11
推荐指数
1
解决办法
1196
查看次数

等待$ D012的更改(C64汇编程序)

我在仿真C64机器上玩asm时遇到了一些问题.

我想要做的是检查键盘上的键"N"是否被按下,然后程序应该等待更改显示在地址$ D012上.现在我不明白的是我如何"等待"改变出现?任何人都可以告诉我它的全部意义吗?

检查键盘上的N按钮是否按下很简单 - 只需使用子程序FFE4(输入)和FFD2(输出).

我真的不想要为我做任何事情,但如果我能得到关于D012如何工作以及如何"等待"改变的快速信息,我将非常感激.

提前致谢!

assembly c64 6502

10
推荐指数
1
解决办法
2039
查看次数

在汇编中编写while循环

我正在尝试用6502处理器在汇编中编写while循环,我无法弄清楚如何编写十六进制代码.我已经看过使用简写编写的示例,其中有一个标签,表示循环应该从哪里开始和结束但是我没有看到任何实际的十六进制代码.

我认为有用的两个代码是:

  1. 比较内存中的字节与X reg(速记:CPX,十六进制:EC).如果相等,则将Z标志设置为零
  2. 如果Z标志= 0,则分支X字节(简写:BNE,十六进制:D0)

assembly hex loops 6502 while-loop

9
推荐指数
1
解决办法
1万
查看次数

6502仿真实现ADC和SBC的正确方法

我一直在为MOS 6502设计仿真器,但我似乎无法让ADC和SBC正常工作.我正在使用在模拟内存中加载到0x4000 的AllSuiteA程序测试我的模拟器,而对于test09,我当前的ADC和SBC实现只是没有得到正确的标志.我已经尝试过无数次更改算法,但每次,进位标志和溢出标志都足够重要,并导致测试分支/不分支.

我的两个功能都基于此.

内存[0x10000]是累加器.它存储在存储器范围之外,因此我可以使用单独的寻址开关语句.

这是我对这些功能的一种实现:

case "ADC":
    var t = memory[0x10000] + memory[address] + getFlag(flag_carry);
    (memory[0x10000] & 0x80) != (t & 0x80) ? setFlag(flag_overflow) : clearFlag(flag_overflow);
    signCalc(memory[0x10000]);
    zeroCalc(t);

    t > 255 ? setFlag(flag_carry) : clearFlag(flag_carry);

    memory[0x10000] = t & 0xFF;
break;

case "SBC":
    var t = memory[0x10000] - memory[address] - (!getFlag(flag_carry));
    (t > 127 || t < -128) ? setFlag(flag_overflow) : clearFlag(flag_overflow);

    t >= 0 ? setFlag(flag_carry) : clearFlag(flag_carry);
    signCalc(t);
    zeroCalc(t);

    memory[0x10000] = t & 0xFF;
break; …
Run Code Online (Sandbox Code Playgroud)

javascript 6502 emulation

9
推荐指数
2
解决办法
4040
查看次数

不使用x86的经典汇编语言文本?

我正在寻找能够详细解决汇编编程原理的文本,而不是使用x86作为目标架构.我没有找到这样的近期书籍,但我希望在20世纪70年代和80年代写出一些好的书,当时整个申请仍然是用汇编写的.使用的架构也应该是更清洁的设计之一,例如6502或VAX.

assembly 6502 vax

8
推荐指数
2
解决办法
1264
查看次数