{"action":"opened","issue":{"url":"https://api.github.com/repos/dustpg/BlogFM/issues/10","repository_url":"https://api.github.com/repos/dustpg/BlogFM","labels_url":"https://api.github.com/repos/dustpg/BlogFM/issues/10/labels{/name}","comments_url":"https://api.github.com/repos/dustpg/BlogFM/issues/10/comments","events_url":"https://api.github.com/repos/dustpg/BlogFM/issues/10/events","html_url":"https://github.com/dustpg/BlogFM/issues/10","id":358350842,"node_id":"MDU6SXNzdWUzNTgzNTA4NDI=","number":10,"title":"Re: 从零开始的红白机模拟 - [06]基础指令","user":{"login":"dustpg","id":6801311,"node_id":"MDQ6VXNlcjY4MDEzMTE=","avatar_url":"https://avatars2.githubusercontent.com/u/6801311?v=4","gravatar_id":"","url":"https://api.github.com/users/dustpg","html_url":"https://github.com/dustpg","followers_url":"https://api.github.com/users/dustpg/followers","following_url":"https://api.github.com/users/dustpg/following{/other_user}","gists_url":"https://api.github.com/users/dustpg/gists{/gist_id}","starred_url":"https://api.github.com/users/dustpg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dustpg/subscriptions","organizations_url":"https://api.github.com/users/dustpg/orgs","repos_url":"https://api.github.com/users/dustpg/repos","events_url":"https://api.github.com/users/dustpg/events{/privacy}","received_events_url":"https://api.github.com/users/dustpg/received_events","type":"User","site_admin":false},"labels":[{"id":346860766,"node_id":"MDU6TGFiZWwzNDY4NjA3NjY=","url":"https://api.github.com/repos/dustpg/BlogFM/labels/C/C++","name":"C/C++","color":"e11d21","default":false},{"id":1048820002,"node_id":"MDU6TGFiZWwxMDQ4ODIwMDAy","url":"https://api.github.com/repos/dustpg/BlogFM/labels/FC/NES","name":"FC/NES","color":"d4c5f9","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-09-09T05:14:53Z","updated_at":"2018-09-09T05:14:53Z","closed_at":null,"author_association":"OWNER","body":"### STEP3: CPU 指令实现 - 基础指令\r\n这节就详细谈谈基础指令, 所谓'基础指令'只是自己随便命名的, 避免一节过长, 请勿对号入座.\r\n\r\n### 指令周期\r\n不同指令需要消耗不同的周期, 这很好理解. 不过就算相同的指令环境不同也会消耗不同周期:\r\n\r\n  - 页面边界交叉(Page Boundary Crossed)\r\n    - 页面边界交叉是指6502将内存划分为256个页面(8位机但是拥有16位地址空间). \r\n    - 当访问不同页面时, 需要额外的指令周期去读取. \r\n  - 跳转到不同页面(Branch Occurs Different Page)\r\n    - 意思和上面的差不多\r\n  - 这两个会在这一步的最后一节详细谈谈\r\n\r\n### LDA - Load \"A\"\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|----------|-----------|----|---------|----------|\r\n|  立即     | LDA #Oper    | A9 |    2    |    2     |\r\n|  零页     | LDA Oper     | A5 |    2    |    3     |\r\n|  零页,X   | LDA Oper,X   | B5 |    2    |    4     |\r\n|  绝对     | LDA Oper     | AD |    3    |    4     |\r\n|  绝对,X   | LDA Oper,X   | BD |    3    |    4*    |\r\n|  绝对,Y   | LDA Oper,Y   | B9 |    3    |    4*    |\r\n|  (间接,X) | LDA (Oper,X) | A1 |    2    |    6     |\r\n|  (间接),Y | LDA (Oper),Y | B1 |    2    |    5*    |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n由存储器取数送入累加器A, 影响FLAG: Z(ero),S(ign), 伪C代码:\r\n```c\r\nA = READ(address);\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### LDX - Load 'X'\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|--------------|----|---------|----------|\r\n|  立即     |   LDX #Oper    |  A2  |    2    |    2     |\r\n|  零页     |   LDX Oper     |  A6  |    2    |    3     |\r\n|  零页, Y  |   LDX Oper,Y   |  B6  |    2    |    4     |\r\n|  绝对     |   LDX Oper     |  AE  |    3    |    4     |\r\n|  绝对, Y  |   LDX Oper,Y   |  BE  |    3    |    4*    |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n由存储器取数送入变址寄存器X, 影响FLAG: Z(ero),S(ign), 伪C代码:\r\n```c\r\nX = READ(address);\r\nCHECK_ZSFLAG(X);\r\n```\r\n\r\n### LDY - Load 'Y'\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|--------------|----|---------|----------|\r\n|  立即   |   LDX #Oper   |    A2   |    2    |    2     |\r\n|  零页   |   LDX Oper    |    A6   |    2    |    3     |\r\n|  零页,Y |   LDX Oper,Y  |    B6   |    2    |    4     |\r\n|  绝对   |   LDX Oper    |    AE   |    3    |    4     |\r\n|  绝对,Y |   LDX Oper,Y  |    BE   |    3    |    4*    |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n由存储器取数送入变址寄存器Y, 影响FLAG: Z(ero),S(ign), 伪C代码:\r\n```c\r\nY = READ(address);\r\nCHECK_ZSFLAG(Y);\r\n```\r\n\r\n### STA - Store 'A'\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  零页   |   STA Oper       |    85   |    2    |    3     |\r\n|  零页,X |   STA Oper,X     |    95   |    2    |    4     |\r\n|  绝对   |   STA Oper       |    80   |    3    |    4     |\r\n|  绝对,X |   STA Oper,X     |    90   |    3    |    5     |\r\n|  绝对,Y |   STA Oper, Y    |    99   |    3    |    5     |\r\n| (间接,X)|   STA (Oper,X)   |    81   |    2    |    6     |\r\n| (间接),Y|   STA (Oper),Y   |    91   |    2    |    6     |\r\n\r\n将累加器A的数送入存储器, 影响FLAG:(无), 伪C代码:\r\n```c\r\nWRTIE(address, A);\r\n```\r\n\r\n### STX - Store 'X'\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  零页  |  STX Oper    |  86 |    2    |    3     |\r\n|  零页,Y|  STX Oper,Y  |  96 |    2    |    4     |\r\n|  绝对  |  STX Oper    |  8E |    3    |    4     |\r\n\r\n将变址寄存器X的数送入存储器, 影响FLAG:(无), 伪C代码:\r\n```c\r\nWRTIE(address, X);\r\n```\r\n### STY - Store 'Y'\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  零页  |   STY Oper     |  84  |   2   |    3     |\r\n| 零页,X |   STY Oper,X   |  94  |   2   |    4     |\r\n| 绝对 |   STY Oper       |  8C  |   3   |    4     |\r\n\r\n将变址寄存器Y的数送入存储器, 影响FLAG:(无), 伪C代码:\r\n```c\r\nWRTIE(address, Y);\r\n```\r\n\r\n### ADC - Add with Carry\r\n助记符号 A = A + M +C\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  立即    | ADC #Oper      |  69  |    2    |    2     |\r\n|  零页    | ADC Oper       |  65  |    2    |    3     |\r\n|  零页,X  | ADC Oper,X     |  75  |    2    |    4     |\r\n|  绝对    | ADC Oper       |  60  |    3    |    4     |\r\n|  绝对,X  | ADC Oper,X     |  70  |    3    |    4*    |\r\n|  绝对,Y  | ADC Oper,Y     |  79  |    3    |    4*    |\r\n| (间接,X) | ADC (Oper,X)   | 61  |    2    |    6     |\r\n| (间接),Y | ADC (Oper),Y   |  71  |    2    |    5*    |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n累加器,存储器,进位标志C相加,结果送累加器A.\r\n影响FLAG: S(ign), Z(ero), C(arry), (o)V(erflow), 伪C代码:\r\n```c\r\nsrc = READ(address);\r\nuint16_t result16 = A + src + (CF ? 1 : 0);\r\nCHECK_CFLAG(result16>>8);\r\nuint8_t result8 = result16;\r\nCHECK_VFLAG(!((A ^ src) & 0x80) && ((A ^ result8) & 0x80));\r\nA = result8;\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### SBC - Subtract with Carry\r\n助记符号  A = A - M - (1-C)\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  立即   | SBC #Oper     |  E9   |    2    |    2     |\r\n|  零页   | SBC Oper      |  E5   |    2    |    3     |\r\n|  零页,X | SBC Oper,X    |  F5   |    2    |    4     |\r\n|  绝对   | SBC Oper      |  ED   |    3    |    4     |\r\n|  绝对,X | SBC Oper,X    |  FD   |    3    |    4*    |\r\n|  绝对,Y | SBC Oper,Y    |  F9   |    3    |    4*    |\r\n| (间接,X)| SBC (Oper,X)  |  E1   |    2    |    6     |\r\n| (间接),Y| SBC (Oper),Y  |  F1   |    2    |    5     |\r\n\r\n从累加器减去存储器和进位标志C,结果送累加器A.\r\n影响FLAG: S(ign), Z(ero), C(arry), (o)V(erflow), 伪C代码:\r\n```c\r\nsrc = READ(address);\r\nuint16_t result16 = A - src - (CF ? 0 : 1);\r\nCHECK_CFLAG(!(result16>>8));\r\nuint8_t result8 = result16;\r\nCHECK_VFLAG(((A ^ result8) & 0x80) && ((A ^ src) & 0x80));\r\nA = result8;\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### INC - Increment memory\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|  \r\n|  零页   |   INC Oper    |   E6   |    2    |    5  |\r\n|  零页,X |   INC Oper,X  |   F6   |    2    |    6  |\r\n|  绝对   |   INC Oper    |   EE   |    3    |    6  |\r\n|  绝对,X |   INC Oper,X  |   FE   |    3    |    7  |\r\n\r\n存储器单元内容+1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```\r\ntmp = READ(address);\r\n++tmp;\r\nWRITE(address, tmp);\r\nCHECK_ZSFLAG(tmp);\r\n```\r\n\r\n### DEC - Decrement memory\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|  \r\n|  零页   |  DEC Oper   |  C6   |    2    |    5     |\r\n|  零页,X |  DEC Oper,X |  D6   |    2    |    6     |\r\n|  绝对   |  DEC Oper   |  CE   |    3    |    6     |\r\n|  绝对,X |  DEC Oper,X |  DE   |    3    |    7     |\r\n\r\n存储器单元内容-1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```\r\ntmp = READ(address);\r\n--tmp;\r\nWRITE(address, tmp);\r\nCHECK_ZSFLAG(tmp);\r\n```\r\n\r\n### AND - 'And' memory with A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即   |  AND #Oper   |   29   |    2    |    2     |\r\n|  零页   |  AND Oper    |   25   |    2    |    3     |\r\n|  零页,X |  AND Oper,X  |   35   |    2    |    4     |\r\n|  绝对   |  AND Oper    |   2D   |    3    |    4     |\r\n|  绝对,X |  AND Oper,X  |   3D   |    3    |    4*    |\r\n|  绝对,Y |  AND Oper,Y  |   39   |    3    |    4*    |\r\n| (间接,X)| AND (Oper,X) |   21   |    2    |    6     |\r\n| (间接),Y| AND (Oper),Y |   31   |    2    |    5     |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n存储器单元与累加器做与运算, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nA &= READ(address);\r\nCHECK_ZSFLAG(A);\r\n```\r\n### ORA - 'Or' memory with A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即   |  ORA #Oper   |  09  |   2   |   2    |\r\n|  零页   |  ORA Oper    |  05  |   2   |    3   |\r\n|  零页,X |  ORA Oper,X  |  15  |   2   |    4   |\r\n|  绝对   |  ORA Oper    |  0D  |   3   |    4   |\r\n|  绝对,X |  ORA Oper,X  |  10  |   3   |    4*  |\r\n|  绝对,Y |  ORA Oper,Y  |  19  |   3   |    4*  |\r\n| (间接,X)|  ORA (Oper,X)|  01  |   2   |    6   |\r\n| (间接),Y|  ORA (Oper),Y|  11  |   2   |    5   |\r\n\r\n\\* 在页面边界交叉时 +1s\r\n\r\n存储器单元与累加器做或运算, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nA |= READ(address);\r\nCHECK_ZSFLAG(A);\r\n```\r\n  \r\n### ERA - \"Exclusive-Or\" memory with A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即   |  EOR #Oper   |   49   |    2    |    2     |\r\n|  零页   |  EOR Oper    |   45   |    2    |    3     |\r\n|  零页,X |  EOR Oper,X  |   55   |    2    |    4     |\r\n|  绝对   |  EOR Oper    |   40   |    3    |    4     |\r\n|  绝对,X |  EOR Oper,X  |   50   |    3    |    4*    |\r\n|  绝对,Y |  EOR Oper,Y  |   59   |    3    |    4*    |\r\n| (间接,X)|  EOR (Oper,X)|   41   |    2    |    6     |\r\n| (间接),Y|  EOR (Oper),Y|   51   |    2    |    5*    |\r\n\r\n  \\* 在页面边界交叉时 +1s\r\n\r\n存储器单元与累加器做或运算, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nA ^= READ(address);\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n## INX - Increment X\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   INX    |    E8   |    1    |    2     |\r\n\r\n变址寄存器X内容+1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\n++X;\r\nCHECK_ZSFLAG(X);\r\n```\r\n\r\n### DEX - Decrement X\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |  DEX    |    CA   |    1    |    2    |\r\n\r\n变址寄存器X内容-1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\n--X;\r\nCHECK_ZSFLAG(X);\r\n```\r\n\r\n### INY - Increment Y\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   INY    |    C8   |    1    |    2     |\r\n\r\n变址寄存器Y内容+1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\n++Y;\r\nCHECK_ZSFLAG(Y);\r\n```\r\n\r\n### DEY - Decrement Y\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n |  隐含   |   DEY    |    88   |    1    |    2     |\r\n\r\n变址寄存器Y内容-1, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\n--Y;\r\nCHECK_ZSFLAG(Y);\r\n```\r\n\r\n### TAX - Transfer A to X\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含   |   TAX      |   AA  |   1   |   2    |\r\n\r\n将累加器A的内容送入变址寄存器X, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nX = A;\r\nCHECK_ZSFLAG(X);\r\n```\r\n\r\n### TXA - Transfer X to A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含   |   TXA      |    8A   |    1    |    2     |\r\n\r\n将累加器A的内容送入变址寄存器X, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nA = X;\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### TAY - Transfer A to Y\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含  |   TAY     |   A8  |   1    |    2     |\r\n\r\n将累加器A的内容送入变址寄存器Y, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nY = A;\r\nCHECK_ZSFLAG(Y);\r\n```\r\n\r\n### TYA - Transfer Y to A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含   |   TYA   |    98   |    1    |    2     |\r\n\r\n将变址寄存器Y的内容送入累加器A, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nA = Y;\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### TSX - Transfer SP to X\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含  |   TSX     |  BA  |   1    |    2     |\r\n\r\n将栈指针SP内容送入变址寄存器X, 影响FLAG:Z(ero),S(ign), 伪C代码:\r\n```c\r\nX = SP;\r\nCHECK_ZSFLAG(X);\r\n```\r\n### TXS - Transfer X to SP\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含  |   TXS    |   9A   |    1    |    2     |\r\n\r\n将变址寄存器X内容送入栈指针SP, 影响FLAG:**无**, 伪C代码:\r\n```c\r\nSP = X;\r\n```\r\n\r\n### CLC - Clear Carry \r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   CLC     |    18   |    1    |    2    |\r\n\r\n清除进位标志C,  影响FLAG: C(arry), 伪C代码:\r\n```c\r\nCF = 0;\r\n```\r\n### SEC - Set Carry\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   SEC     |   38   |    1    |    2    |\r\n\r\n设置进位标志C,  影响FLAG: C(arry), 伪C代码:\r\n```c\r\nCF = 1;\r\n```\r\n\r\n### CLD - Clear Decimal\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   CLD     |    D8   |    1    |    2     |\r\n\r\n清除十进制模式标志D,  影响FLAG: D(Decimal), 伪C代码:\r\n```c\r\nDF = 0;\r\n```\r\n\r\n### SED - Clear Decimal\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |   SED    |    F8   |    1    |    2     |\r\n\r\n设置十进制模式标志D,  影响FLAG: D(Decimal), 伪C代码:\r\n```c\r\nDF = 1\r\n```\r\n\r\n### CLV - Clear Overflow\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |    CLV     |    B8   |    1    |    2     |\r\n\r\n清除溢出标志V,  影响FLAG: (o)V(erflow), 伪C代码:\r\n```c\r\nVF = 0;\r\n```\r\n\r\n### CLI - Clear Interrupt-disable\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |    CLI   |    58   |    1    |    2     |\r\n\r\n清除中断禁止标志I,  影响FLAG: I(nterrupt-disable), 伪C代码:\r\n```c\r\nIF = 0;\r\n```\r\n\r\n### SEI - Set Interrupt-disable\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  隐含  |    SEI   |    78   |    1    |    2     |\r\n\r\n设置中断禁止标志I,  影响FLAG: I(nterrupt-disable), 伪C代码:\r\n```c\r\nIF = 1;\r\n```\r\n\r\n### CMP - Compare memory with A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即     |   CMP #Oper           |    C9   |    2    |    2     |\r\n|  零页     |   CMP Oper            |    C5   |    2    |    3     |\r\n|  零页,X   |   CMP Oper,X          |    D5   |    2    |    4     |\r\n|  绝对      |   CMP Oper            |    CD   |    3    |    4     |\r\n|  绝对,X    |   CMP Oper,X          |    DD   |    3    |    4*    |\r\n|  绝对,Y    |   CMP Oper,Y          |    D9   |    3    |    4*    |\r\n|  (Indirect,X)  |   CMP (Oper,X)        |    C1   |    2    |    6     |\r\n|  (Indirect),Y  |   CMP (Oper),Y        |    D1   |    2    |    5*    |\r\n\r\n比较储存器值与累加器A.\r\n影响FLAG: C(arry), S(ign), Z(ero). 伪C代码: \r\n```c\r\nuint16_t result16 = (uint16_t)A - (uint16_t)READ(address);\r\nCF = result16 < 0x100;\r\nCHECK_ZSFLAG((uint8_t)result16);\r\n```\r\n\r\n\r\n### CPX - Compare memory with X\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即     |   CPX #Oper           |    E0   |    2    |    2     |\r\n|  零页     |   CPX Oper            |    E4   |    2    |    3     |\r\n|  绝对      |   CPX Oper            |    EC   |    3    |    4     |\r\n\r\n比较储存器值与变址寄存器X.\r\n影响FLAG: C(arry), S(ign), Z(ero). 伪C代码: \r\n```c\r\nuint16_t result16 = (uint16_t)X - (uint16_t)READ(address);\r\nCF = result16 < 0x100;\r\nCHECK_ZSFLAG((uint8_t)result16);\r\n```\r\n\r\n### CPY - Compare memory with Y\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  立即     |   CPY #Oper           |    C0   |    2    |    2     |\r\n|  零页     |   CPY Oper            |    C4   |    2    |    3     |\r\n|  绝对      |   CPY Oper            |    CC   |    3    |    4     |\r\n\r\n比较储存器值与变址寄存器Y.\r\n影响FLAG: C(arry), S(ign), Z(ero). 伪C代码: \r\n```c\r\nuint16_t result16 = (uint16_t)Y - (uint16_t)READ(address);\r\nCF = result16 < 0x100;\r\nCHECK_ZSFLAG((uint8_t)result16);\r\n```\r\n\r\n### BIT - Bit test memory with A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  零页     |   BIT Oper            |    24   |    2    |    3     |\r\n|  绝对      |   BIT Oper            |    2C   |    3    |    4     |\r\n\r\n位测试\r\n - 若 A&M 结果 =0, 那么Z=1\r\n - 若 A&M 结果!=0, 那么Z=0\r\n - S = M的第7位 \r\n - V = M的第6位\r\n\r\n影响FLAG: (o)V(erflow), S(ign), Z(ero). 伪C代码: \r\n```c\r\ntmp = READ(address);\r\nVF = (tmp >> 6) & 1;\r\nSF = (tmp >> 7) & 1;\r\nZF = A & tmp ? 0 : 1;\r\n```\r\n\r\n### ASL - Arithmetic Shift Left\r\n助记符号: C <- |7|6|5|4|3|2|1|0| <- 0\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------| \r\n|  累加器A   |   ASL A               |    0A   |    1    |    2     |\r\n|  零页     |   ASL Oper            |    06   |    2    |    5     |\r\n|  零页,X   |   ASL Oper,X          |    16   |    2    |    6     |\r\n|  绝对      |   ASL Oper            |    0E   |    3    |    6     |\r\n|  绝对, X   |   ASL Oper,X          |    1E   |    3    |    7     |\r\n\r\n累加器A, 或者存储器单元算术按位左移一位. 最高位移动到C, 最低位0. 影响FLAG: S(ign) Z(ero) C(arry), 伪C代码:\r\n```c\r\n// ASL A:\r\nCHECK_CFLAG(A>>7);\r\nA <<= 1;\r\nCHECK_ZSFLAG(A);\r\n\r\n// 其他情况\r\ntmp = READ(address);\r\nCHECK_CFLAG(tmp>>7);\r\ntmp <<= 1;\r\nWRITE(address, tmp);\r\nCHECK_ZSFLAG(tmp);\r\n\r\n```\r\n\r\n### LSR - Logical Shift Right\r\n助记符号: 0 -> |7|6|5|4|3|2|1|0| -> C\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  累加器A   |   LSR A               |    4A   |    1    |    2     |\r\n|  零页     |   LSR Oper            |    46   |    2    |    5     |\r\n|  零页,X   |   LSR Oper,X          |    56   |    2    |    6     |\r\n|  绝对      |   LSR Oper            |    4E   |    3    |    6     |\r\n|  绝对,X    |   LSR Oper,X          |    5E   |    3    |    7     |\r\n\r\n累加器A, 或者存储器单元逻辑按位右移一位. 最低位回移进C, 最高位变0, 影响FLAG: S(ign) Z(ero) C(arry), 伪C代码:\r\n```c\r\n// LSR A:\r\nCHECK_CFLAG(A & 1);\r\nA >>= 1;\r\nCHECK_ZSFLAG(A);\r\n\r\n// 其他情况\r\ntmp = READ(address);\r\nCHECK_CFLAG(tmp & 1);\r\ntmp >>= 1;\r\nWRITE(address, tmp);\r\nCHECK_ZSFLAG(tmp);\r\n```\r\n\r\n### ROL - Rotate Left\r\n助记符号: ...|0| <- C <- |7|6|5|4|3|2|1|0| <- C <- |7|...\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  累加器A   |   ROL A               |    2A   |    1    |    2     |\r\n|  零页     |   ROL Oper            |    26   |    2    |    5     |\r\n|  零页,X   |   ROL Oper,X          |    36   |    2    |    6     |\r\n|  绝对      |   ROL Oper            |    2E   |    3    |    6     |\r\n|  绝对,X    |   ROL Oper,X          |    3E   |    3    |    7     |\r\n\r\n累加器A, 或者储存器内容 连同C位 按位循环左移一位, 影响FLAG: S(ign) Z(ero) C(arry), 伪C代码:\r\n```c\r\n// A_M 意思到了就行\r\nuint16_t src = A_M;\r\nsrc <<= 1;\r\nif (CF) src |= 0x1;\r\nCHECK_CFLAG(src > 0xff);\r\nA_M = src;\r\nCHECK_ZSFLAG(A_M);\r\n```\r\n\r\n### ROR - Rotate Right\r\n助记符号: ...|0| -> C -> |7|6|5|4|3|2|1|0| -> C -> |7|...\r\n\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  累加器A   |   ROR A               |    6A   |    1    |    2     |\r\n|  零页     |   ROR Oper            |    66   |    2    |    5     |\r\n|  零页,X   |   ROR Oper,X          |    76   |    2    |    6     |\r\n|  绝对      |   ROR Oper            |    6E   |    3    |    6     |\r\n|  绝对,X    |   ROR Oper,X          |    7E   |    3    |    7     |\r\n\r\n\r\n累加器A, 或者储存器内容 连同C位 按位循环左移一位, 影响FLAG: S(ign) Z(ero) C(arry), 伪C代码:\r\n```c\r\n// A_M 意思到了就行\r\nuint16_t src = A_M;\r\nif (CF) src |= 0x100;\r\nCF = src & 1;\r\nsrc >> 1;\r\nA_M = src;\r\nCHECK_ZSFLAG(A_M);\r\n```\r\n\r\n### PHA - Push A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含       |   PHA                 |    48   |    1    |    3     |\r\n\r\n累加器A压入栈顶(栈指针SP-1). 影响FLAG:(无), 伪C代码:\r\n```c\r\nPUSH(A);\r\n```\r\n\r\n### PLA - Pull(Pop) A\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含       |   PLA                 |    68   |    1    |    4     |\r\n\r\n\r\npush的反操作, 在6502汇编称为pull, 不过自己还是习惯称为pop.\r\n[6502_cn](http://nesdev.com/6502_cn.txt)这篇文档提到没有FLAG修改, 可能是笔误, 其他文档([比如这个](http://obelisk.me.uk/6502/reference.html))提到会影响S(ign) Z(ero) , 伪C代码:\r\n```c\r\nA = POP();\r\nCHECK_ZSFLAG(A);\r\n```\r\n\r\n### PHP - Push Processor-status \r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含       |   PHP                 |    08   |    1    |    3     |\r\n\r\n将状态FLAG压入栈顶, 影响FLAG:(无), 伪C代码:\r\n```c\r\nPUSH(P | FLAG_B | FLAG_R);\r\n```\r\n\r\n### PLP - Pull Processor-status\r\n| 寻址模式| 汇编格式| OP代码 |指令字节|指令周期|\r\n|--------|-----------|----|---------|----------|\r\n|  隐含       |   PLP                 |    28   |    1    |    4     |\r\n\r\nPHP逆操作, 影响FLAG: (是的), 伪C代码:\r\n```c\r\np = POP();\r\n// 无视BIT4 BIT5\r\nRF = 1;\r\nBF = 0;\r\n```\r\n\r\n### REF\r\n - [nesdev-archive](http://nesdev.com/archive.html)\r\n - [NES 文档2.00](http://nesdev.com/nestech_cn.txt)\r\n - [6502 微处理器](http://nesdev.com/6502_cn.txt)\r\n - [6502_cpu](http://nesdev.com/6502_cpu.txt)\r\n"}}
{"actor":{"display_login":"dustpg"}}