| 해당 내용은 NES에 국한된 내용입니다. 해당 문서의 내용의 일부는 NES(패미컴) 외에서는 해당 내용이 적용되지 않을 수 있습니다. |
| ADC | AND | ASL | BCC | BCS | BEQ | BIT | BMI | BNE | BPL | BRK | BVC | BVS | CLC |
| CLD | CLI | CLV | CMP | CPX | CPY | DEC | DEX | DEY | EOR | INC | INX | INY | JMP |
| JSR | LDA | LDX | LDY | LSR | NOP | ORA | PHA | PHP | PLA | PLP | ROL | ROR | RTI |
| RTS | SBC | SEC | SED | SEI | STA | STX | STY | TAX | TAY | TSX | TXA | TXS | TYA |
종류별 공식 명령어
| 종류 | 명령어 | |||||||
|---|---|---|---|---|---|---|---|---|
| 접근 (Access) | LDA | STA | LDX | STX | LDY | STY | ||
| 전송 (Transfer) | TAX | TXA | TAY | TYA | ||||
| 산술 (Arithmetic) | ADC | SBC | INC | DEC | INX | DEX | INY | DEY |
| 시프트 (Shift) | ASL | LSR | ROL | ROR | ||||
| 비트연산 (Bitwise) | AND | ORA | EOR | BIT | ||||
| 비교 (Compare) | CMP | CPX | CPY | |||||
| 분기 (Branch) | BCC | BCS | BEQ | BNE | BPL | BMI | BVC | BVS |
| 점프 (Jump) | JMP | JSR | RTS | BRK | RTI | |||
| 스택 (Stack) | PHA | PLA | PHP | PLP | TXS | TSX | ||
| 플래그 (Flags) | CLC | SEC | CLI | SEI | CLD | SED | CLV | |
| 기타 (Other) | NOP | |||||||
공식 명령어
ADC - 캐리와 함께 더하기 (Add with Carry)
A = A + 메모리 + C
ADC는 캐리 플래그와 메모리 값을 어큐뮬레이터에 더합니다. 그 후 캐리 플래그는 비트 7에서 나오는 캐리 값으로 설정되어, 다음 바이트 덧셈으로 1을 넘겨줌으로써 1바이트보다 큰 값을 더할 수 있게 합니다. 이는 부호 없는 오버플로로 생각할 수도 있습니다. 첫 바이트를 더하기 전에 CLC로 캐리를 클리어하여 알려진 상태로 만들어, 1만큼의 오차를 피하는 것이 일반적입니다. 오버플로 플래그는 부호 있는 오버플로나 언더플로가 발생했는지를 나타냅니다. 이는 두 입력이 모두 양수인데 결과가 음수이거나, 두 입력이 모두 음수인데 결과가 양수인 경우에 발생합니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| C - 캐리 | 결과 > $FF | 결과가 $FF를 초과하여 오버플로(랩어라운드)되면, 부호 없는 오버플로가 발생한 것입니다. |
| Z - 제로 | 결과 == 0 | |
| V - 오버플로 | (결과 ^ A) & (결과 ^ 메모리) & $80 | 결과의 부호가 A와 메모리의 부호와 모두 다르면, 부호 있는 오버플로(또는 언더플로)가 발생한 것입니다. |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $69 | 2 | 2 |
| Zero Page | $65 | 2 | 3 |
| Zero Page,X | $75 | 2 | 4 |
| Absolute | $6D | 3 | 4 |
| Absolute,X | $7D | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $79 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $61 | 2 | 6 |
| (Indirect),Y | $71 | 2 | 5 (페이지 교차 시 6) |
AND - 비트 단위 AND (Bitwise AND)
A = A & 메모리
이 명령어는 메모리 값과 어큐뮬레이터를 비트 단위로 AND 연산합니다. 두 입력 비트가 모두 1이면 결과 비트는 1이 되고, 그렇지 않으면 0이 됩니다.
| A | 메모리 | 결과 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $29 | 2 | 2 |
| Zero Page | $25 | 2 | 3 |
| Zero Page,X | $35 | 2 | 4 |
| Absolute | $2D | 3 | 4 |
| Absolute,X | $3D | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $39 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $21 | 2 | 6 |
| (Indirect),Y | $31 | 2 | 5 (페이지 교차 시 6) |
ASL - 산술 왼쪽 시프트 (Arithmetic Shift Left)
값 = 값 << 1, 또는 시각적으로: C <- [76543210] <- 0
ASL은 메모리 값 또는 어큐뮬레이터의 모든 비트를 왼쪽으로 한 자리씩 시프트하여, 각 비트의 값을 다음 비트로 이동시킵니다. 비트 7은 캐리 플래그로 시프트되고, 0이 비트 0으로 시프트됩니다. 이는 부호 없는 값을 2로 곱하는 것과 같으며, 캐리는 오버플로를 나타냅니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 메모리에서 작동하는 주소 지정 모드는 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 값의 비트 7 |
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Accumulator | $0A | 1 | 2 |
| Zero Page | $06 | 2 | 5 |
| Zero Page,X | $16 | 2 | 6 |
| Absolute | $0E | 3 | 6 |
| Absolute,X | $1E | 3 | 7 |
BCC - 캐리가 클리어되면 분기 (Branch if Carry Clear)
PC = PC + 2 + 메모리 (부호 있음)
캐리 플래그가 클리어(0)이면, BCC는 상대 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 캐리가 설정되었을 때 BCS로 해당 JMP를 건너뛰어야 합니다.
캐리 플래그는 문맥에 따라 다른 의미를 가집니다. BCC는 비교 후에 레지스터가 메모리 값보다 작을 경우 분기하는 데 사용될 수 있으므로, 때때로 BLT(Branch if Less Than)라고도 불립니다. 또한 SBC 후에는 부호 없는 값이 언더플로되었을 경우, ADC 후에는 오버플로되지 '않았을' 경우 분기하는 데 사용될 수 있습니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $90 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BCS - 캐리가 설정되면 분기 (Branch if Carry Set)
PC = PC + 2 + 메모리 (부호 있음)
캐리 플래그가 설정(1)되면, BCS는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 캐리가 클리어되었을 때 BCC로 해당 JMP를 건너뛰어야 합니다.
캐리 플래그는 문맥에 따라 다른 의미를 가집니다. BCS는 비교 후에 레지스터가 메모리 값보다 크거나 같을 경우 분기하는 데 사용될 수 있으므로, 때때로 BGE(Branch if Greater Than or Equal)라고도 불립니다. 또한 ADC 후에는 부호 없는 값이 오버플로되었을 경우, SBC 후에는 언더플로되지 '않았을' 경우 분기하는 데 사용될 수 있습니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $B0 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BEQ - 같으면 분기 (Branch if Equal)
PC = PC + 2 + 메모리 (부호 있음)
제로 플래그가 설정(1)되면, BEQ는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 제로가 클리어되었을 때 BNE로 해당 JMP를 건너뛰어야 합니다.
비교 연산은 이 플래그를 사용하여 비교된 값들이 같은지 여부를 나타냅니다. A, X, 또는 Y를 변경하는 모든 명령어는 레지스터가 0이 되는지 여부에 따라 암묵적으로 제로 플래그를 설정하거나 클리어합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $F0 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BIT - 비트 테스트 (Bit Test)
A & 메모리
BIT는 플래그를 수정하지만, 메모리나 레지스터는 변경하지 않습니다. 제로 플래그는 어큐뮬레이터와 메모리 값의 AND 연산 결과에 따라 설정되며, 이는 효과적으로 비트마스크를 적용한 후 설정된 비트가 있는지 확인하는 것과 같습니다. 메모리 값의 비트 7과 6은 네거티브 및 오버플로 플래그로 직접 로드되어, 마스크를 A에 로드할 필요 없이 쉽게 확인할 수 있습니다.
BIT는 CPU 플래그만 변경하기 때문에, 때때로 CPU 레지스터를 덮어쓰지 않고 하드웨어 레지스터의 읽기 부작용을 트리거하거나, 3 사이클 NOP처럼 사이클을 낭비하는 데 사용됩니다. 고급 기술로, 피연산자에 1 또는 2바이트 명령어를 숨겨두고 직접 점프할 때만 실행되도록 하여 두 코드 경로를 인터리빙하는 데 가끔 사용됩니다. 그러나 피연산자의 명령어는 읽을 주소로 취급되므로, 하드웨어 레지스터를 읽을 경우 부작용을 일으킬 위험이 있습니다. 이 기술은 공간, 시간 또는 레지스터 사용에 대한 제약이 심할 때 유용할 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| V - 오버플로 | 메모리의 비트 6 |
| N - 네거티브 | 메모리의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero page | $24 | 2 | 3 |
| Absolute | $2C | 3 | 4 |
참조: AND
BMI - 음수이면 분기 (Branch if Minus)
PC = PC + 2 + 메모리 (부호 있음)
네거티브 플래그가 설정(1)되면, BMI는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 네거티브가 클리어되었을 때 BPL로 해당 JMP를 건너뛰어야 합니다.
A, X, 또는 Y를 변경하는 모든 명령어는 비트 7(부호 비트)에 따라 암묵적으로 네거티브 플래그를 설정하거나 클리어합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $30 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BNE - 같지 않으면 분기 (Branch if Not Equal)
PC = PC + 2 + 메모리 (부호 있음)
제로 플래그가 클리어(0)이면, BNE는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 네거티브가 설정되었을 때 BEQ로 해당 JMP를 건너뛰어야 합니다.
비교 연산은 이 플래그를 사용하여 비교된 값들이 같은지 여부를 나타냅니다. A, X, 또는 Y를 변경하는 모든 명령어는 레지스터가 0이 되는지 여부에 따라 암묵적으로 제로 플래그를 설정하거나 클리어합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $D0 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BPL - 양수이면 분기 (Branch if Plus)
PC = PC + 2 + 메모리 (부호 있음)
네거티브 플래그가 클리어(0)이면, BPL는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 네거티브가 설정되었을 때 BMI로 해당 JMP를 건너뛰어야 합니다.
A, X, 또는 Y를 변경하는 모든 명령어는 비트 7(부호 비트)에 따라 암묵적으로 네거티브 플래그를 설정하거나 클리어합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $10 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BRK - 중단 (소프트웨어 IRQ) (Break)
스택에 PC + 2를 푸시
스택에 NV11DIZC 플래그를 푸시
PC = ($FFFE)
BRK는 인터럽트 요청(IRQ)을 트리거합니다. IRQ는 보통 외부 하드웨어에 의해 트리거되며, BRK는 소프트웨어에서 이를 수행하는 유일한 방법입니다. 일반적인 IRQ처럼, 현재 프로그램 카운터와 프로세서 플래그를 스택에 푸시하고, 인터럽트 비활성화 플래그를 설정한 후, IRQ 핸들러로 점프합니다. 일반적인 IRQ와 달리, 스택에 푸시되는 플래그 바이트에 브레이크 플래그를 설정하고(PHP처럼), 인터럽트 비활성화 플래그가 설정되어 있어도 인터럽트를 트리거합니다. 특히, 스택에 푸시되는 반환 주소는 BRK 옵코드 다음 바이트를 건너뜁니다. 이러한 이유로, BRK는 종종 사용되지 않는 즉시 피연산자를 가진 2바이트 명령어로 간주됩니다.
불행히도, 6502 버그로 인해 BRK IRQ는 동시에 발생하는 NMI에 의해 무시될 수 있습니다. 이 경우, NMI 핸들러만 호출되고 IRQ 핸들러는 건너뜁니다. 그러나 스택에 푸시된 플래그 바이트에는 여전히 브레이크 플래그가 설정되어 있으므로, NMI 핸들러는 이 플래그를 확인하여 (느리지만) 이 상황이 발생했음을 감지할 수 있습니다.
BRK는 값 $00을 사용하기 때문에, 프로그래밍 가능한 ROM의 모든 바이트는 BRK 명령어로 덮어써서 실행을 IRQ 핸들러로 보낼 수 있습니다. 이는 일회성 프로그래밍 가능 ROM을 패치하는 데 유용합니다. BRK는 또한 시스템 콜 메커니즘으로 사용될 수 있으며, 사용되지 않는 바이트는 소프트웨어에서 인수로 사용될 수 있습니다 (접근하기는 불편하지만). NES 게임의 맥락에서, BRK는 종종 크래시 핸들러로 가장 유용합니다. 사용되지 않는 프로그램 공간을 $00으로 채우고 IRQ 핸들러가 디버깅 정보를 표시하거나 다른 방식으로 크래시를 깔끔하게 처리합니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| I - 인터럽트 비활성화 | 1 | 이전 플래그가 스택에 푸시된 후 1로 설정됩니다. 이 플래그 변경의 효과는 지연되지 '않습니다'. |
| B - 브레이크 | 1로 푸시됨 | 이 플래그는 CPU의 실제 상태가 아닌, 스택에 푸시된 플래그 바이트에만 존재합니다. |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 | 비고 |
|---|---|---|---|---|
| Implied | $00 | 1 | 7 | BRK는 1바이트만 사용하지만, 반환 주소는 다음 바이트를 건너뜁니다. |
| #Immediate | $00 | 2 | 7 | BRK가 다음 바이트를 건너뛰기 때문에, 종종 2바이트 명령어로 간주됩니다. |
BVC - 오버플로가 클리어되면 분기 (Branch if Overflow Clear)
PC = PC + 2 + 메모리 (부호 있음)
오버플로 플래그가 클리어(0)이면, BVC는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 오버플로가 설정되었을 때 BVS로 해당 JMP를 건너뛰어야 합니다.
제로, 네거티브, 심지어 캐리와 달리, 오버플로는 매우 적은 수의 명령어에 의해서만 수정됩니다. 주로 BIT 명령어와 함께 사용되며, 특히 하드웨어 레지스터를 폴링할 때 사용됩니다. 또한 ADC 및 SBC와 함께 부호 있는 오버플로에 사용되기도 합니다. 표준 6502 칩은 외부 장치가 핀을 사용하여 오버플로를 설정할 수 있게 하여 소프트웨어가 해당 이벤트를 폴링할 수 있도록 하지만, NES의 2A03에는 이 기능이 없습니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $50 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
BVS - 오버플로가 설정되면 분기 (Branch if Overflow Set)
PC = PC + 2 + 메모리 (부호 있음)
오버플로 플래그가 설정(1)되면, BVS는 분기 오프셋을 프로그램 카운터에 더하여 가까운 위치로 분기합니다. 오프셋은 부호가 있으며, 분기 명령어 '다음'의 첫 바이트를 기준으로 [-128, 127]의 범위를 가집니다. 이보다 멀리 분기하려면 JMP 명령어를 사용하고, 오버플로가 클리어되었을 때 BVC로 해당 JMP를 건너뛰어야 합니다.
제로, 네거티브, 심지어 캐리와 달리, 오버플로는 매우 적은 수의 명령어에 의해서만 수정됩니다. 주로 BIT 명령어와 함께 사용되며, 특히 하드웨어 레지스터를 폴링할 때 사용됩니다. 또한 ADC 및 SBC와 함께 부호 있는 오버플로에 사용되기도 합니다. 표준 6502 칩은 외부 장치가 핀을 사용하여 오버플로를 설정할 수 있게 하여 소프트웨어가 해당 이벤트를 폴링할 수 있도록 하지만, NES의 2A03 CPU에는 이 기능이 없습니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Relative | $70 | 2 | 2 (분기 시 3, 페이지 교차 시 4)* |
CLC - 캐리 클리어 (Clear Carry)
C = 0
CLC는 캐리 플래그를 클리어합니다. 특히, 이는 보통 ADC로 값의 하위 바이트를 더하기 전에 추가적인 1이 더해지는 것을 방지하기 위해 수행됩니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 0 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $18 | 1 | 2 |
참조: SEC
CLD - 데시멀 클리어 (Clear Decimal)
D = 0
CLD는 데시멀 플래그를 클리어합니다. 데시멀 플래그는 보통 BCD 모드의 활성화 여부를 제어하지만, 이 모드는 NES의 2A03 CPU에서는 사용할 수 없다. 그러나 플래그 자체는 여전히 작동하며 상태를 저장하는 데 사용될 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| D - 데시멀 | 0 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $D8 | 1 | 2 |
참조: SED
CLI - 인터럽트 비활성화 클리어 (Clear Interrupt Disable)
I = 0
CLI는 인터럽트 비활성화 플래그를 클리어하여, CPU가 하드웨어 IRQ를 처리할 수 있도록 합니다. 이 플래그 변경의 효과는 한 명령어 지연됩니다. 왜냐하면 플래그는 IRQ가 폴링된 후에 변경되어, 보류 중인 IRQ가 감지되고 서비스되기 전에 다음 명령어가 실행될 수 있도록 하기 때문입니다. 이 플래그는 NMI에는 영향을 미치지 않으며, NMI는 이름("non-maskable")에서 알 수 있듯이 CPU가 무시할 수 없습니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| I - 인터럽트 비활성화 | 0 | 이 플래그 변경의 효과는 1 명령어 지연됩니다. |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $58 | 1 | 2 |
참조: SEI
CLV - 오버플로 클리어 (Clear Overflow)
V = 0
CLV는 오버플로 플래그를 클리어합니다. 이에 해당하는 SEV 명령어는 없습니다. 대신, 오버플로 설정은 6502 CPU에서 외부 하드웨어에 의해 제어되는 핀으로 노출되어 있으며, NES의 2A03 CPU에는 전혀 노출되어 있지 않습니다.
| 플래그 | 새로운 값 |
|---|---|
| V - 오버플로 | 0 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $B8 | 1 | 2 |
CMP - A 비교 (Compare A)
A - 메모리
CMP는 A를 메모리 값과 비교하여, 플래그를 적절하게 설정하지만 어떤 레지스터도 수정하지 않습니다. 비교는 뺄셈으로 구현되며, 빌림(borrow)이 없으면 캐리를 설정하고, 결과가 0이면 제로를 설정하고, 결과가 음수이면 네거티브를 설정합니다. 그러나 캐리와 제로는 종종 부등식으로 기억하는 것이 가장 쉽습니다.
비교는 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | A >= 메모리 |
| Z - 제로 | A == 메모리 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $C9 | 2 | 2 |
| Zero Page | $C5 | 2 | 3 |
| Zero Page,X | $D5 | 2 | 4 |
| Absolute | $CD | 3 | 4 |
| Absolute,X | $DD | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $D9 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $C1 | 2 | 6 |
| (Indirect),Y | $D1 | 2 | 5 (페이지 교차 시 6) |
CPX - X 비교 (Compare X)
X - 메모리
CPX는 X를 메모리 값과 비교하여, 플래그를 적절하게 설정하지만 어떤 레지스터도 수정하지 않습니다. 비교는 뺄셈으로 구현되며, 빌림(borrow)이 없으면 캐리를 설정하고, 결과가 0이면 제로를 설정하고, 결과가 음수이면 네거티브를 설정합니다. 그러나 캐리와 제로는 종종 부등식으로 기억하는 것이 가장 쉽습니다.
비교는 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | X >= 메모리 |
| Z - 제로 | X == 메모리 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $E0 | 2 | 2 |
| Zero Page | $E4 | 2 | 3 |
| Absolute | $EC | 3 | 4 |
CPY - Y 비교 (Compare Y)
Y - 메모리
CPY는 Y를 메모리 값과 비교하여, 플래그를 적절하게 설정하지만 어떤 레지스터도 수정하지 않습니다. 비교는 뺄셈으로 구현되며, 빌림(borrow)이 없으면 캐리를 설정하고, 결과가 0이면 제로를 설정하고, 결과가 음수이면 네거티브를 설정합니다. 그러나 캐리와 제로는 종종 부등식으로 기억하는 것이 가장 쉽습니다.
비교는 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | Y >= 메모리 |
| Z - 제로 | Y == 메모리 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $C0 | 2 | 2 |
| Zero Page | $C4 | 2 | 3 |
| Absolute | $CC | 3 | 4 |
DEC - 메모리 감소 (Decrement Memory)
메모리 = 메모리 - 1
DEC는 메모리 위치에서 1을 뺍니다. 특히, 이 명령어의 어큐뮬레이터 버전은 없으며, 대신 ADC 또는 SBC를 사용해야 합니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
감소는 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero Page | $C6 | 2 | 5 |
| Zero Page,X | $D6 | 2 | 6 |
| Absolute | $CE | 3 | 6 |
| Absolute,X | $DE | 3 | 7 |
DEX - X 감소 (Decrement X)
X = X - 1
DEX는 X 레지스터에서 1을 뺍니다. 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $CA | 1 | 2 |
참조: INX
DEY - Y 감소 (Decrement Y)
Y = Y - 1
DEY는 Y 레지스터에서 1을 뺍니다. 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $88 | 1 | 2 |
참조: INY
EOR - 비트 단위 배타적 OR (Bitwise Exclusive OR)
A = A ^ 메모리
EOR은 메모리 값과 어큐뮬레이터를 비트 단위로 배타적 OR(exclusive-OR) 연산합니다. 입력 비트가 다르면 결과 비트는 1이 되고, 같으면 0이 됩니다. 이 연산은 XOR로도 알려져 있습니다.
6502에는 비트 단위 NOT 명령어가 없지만, 값 $FF와 함께 EOR을 사용하면 동일한 동작을 하여 다른 값의 모든 비트를 반전시킵니다. 사실, EOR은 비트마스크를 사용한 NOT으로 생각할 수 있습니다. 한 값의 모든 1 비트는 다른 값의 해당 비트를 반전시키는 효과를 가지며, 0 비트는 아무것도 하지 않습니다.
| A | 메모리 | 결과 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $49 | 2 | 2 |
| Zero Page | $45 | 2 | 3 |
| Zero Page,X | $55 | 2 | 4 |
| Absolute | $4D | 3 | 4 |
| Absolute,X | $5D | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $59 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $41 | 2 | 6 |
| (Indirect),Y | $51 | 2 | 5 (페이지 교차 시 6) |
INC - 메모리 증가 (Increment Memory)
메모리 = 메모리 + 1
INC는 메모리 위치에 1을 더합니다. 특히, 이 명령어의 어큐뮬레이터 버전은 없으며, 대신 ADC 또는 SBC를 사용해야 합니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
증가는 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero Page | $E6 | 2 | 5 |
| Zero Page,X | $F6 | 2 | 6 |
| Absolute | $EE | 3 | 6 |
| Absolute,X | $FE | 3 | 7 |
INX - X 증가 (Increment X)
X = X + 1
INX는 X 레지스터에 1을 더합니다. 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $E8 | 1 | 2 |
참조: DEX
INY - Y 증가 (Increment Y)
Y = Y + 1
INY는 Y 레지스터에 1을 더합니다. 캐리나 오버플로에 영향을 미치지 '않는다는' 점에 유의하십시오.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $C8 | 1 | 2 |
참조: DEY
JMP - 점프 (Jump)
PC = 메모리
JMP는 프로그램 카운터를 새로운 값으로 설정하여, 코드가 새로운 위치에서 실행되도록 합니다. 해당 위치에서 반환하려면, 대신 JSR을 사용해야 합니다.
간접 주소 지정 모드는 피연산자를 포인터로 사용하여, 지정된 주소에서 새로운 2바이트 프로그램 카운터 값을 가져옵니다. 불행히도, CPU 버그로 인해 이 2바이트 변수의 주소가 $FF로 끝나 페이지를 교차하게 되면, CPU는 두 번째 바이트를 읽을 때 페이지를 증가시키지 못해 잘못된 주소를 읽게 됩니다. 예를 들어, JMP ($03FF)는 $03FF와 $0400 대신 $0300을 읽습니다. 이 변수가 페이지를 교차하지 않도록 주의해야 합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Absolute | $4C | 3 | 3 |
| (Indirect) | $6C | 3 | 5 |
참조: JSR
JSR - 서브루틴으로 점프 (Jump to Subroutine)
스택에 PC + 2를 푸시
PC = 메모리
JSR은 현재 프로그램 카운터를 스택에 푸시한 다음, 프로그램 카운터를 새로운 값으로 설정합니다. 이를 통해 코드는 함수를 호출하고 RTS로 JSR 다음 명령어로 돌아올 수 있습니다.
특히, 스택의 반환 주소는 다음 명령어의 시작 지점이 아니라, 그보다 1바이트 앞을 가리킵니다. 이는 RTS가 다음 명령어를 가져오기 전에 프로그램 카운터를 증가시키기 때문입니다. 이는 인터럽트에 의해 푸시되고 RTI에 의해 사용되는 반환 주소와 다릅니다. 인터럽트의 반환 주소는 다음 명령어를 직접 가리킵니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Absolute | $20 | 3 | 6 |
LDA - A 로드 (Load A)
A = 메모리
LDA는 메모리 값을 어큐뮬레이터로 로드합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $A9 | 2 | 2 |
| Zero Page | $A5 | 2 | 3 |
| Zero Page,X | $B5 | 2 | 4 |
| Absolute | $AD | 3 | 4 |
| Absolute,X | $BD | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $B9 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $A1 | 2 | 6 |
| (Indirect),Y | $B1 | 2 | 5 (페이지 교차 시 6) |
참조: STA
LDX - X 로드 (Load X)
X = 메모리
LDX는 메모리 값을 X 레지스터로 로드합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $A2 | 2 | 2 |
| Zero Page | $A6 | 2 | 3 |
| Zero Page,Y | $B6 | 2 | 4 |
| Absolute | $AE | 3 | 4 |
| Absolute,Y | $BE | 3 | 4 (페이지 교차 시 5) |
참조: STX
LDY - Y 로드 (Load Y)
Y = 메모리
LDY는 메모리 값을 Y 레지스터로 로드합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $A0 | 2 | 2 |
| Zero Page | $A4 | 2 | 3 |
| Zero Page,X | $B4 | 2 | 4 |
| Absolute | $AC | 3 | 4 |
| Absolute,X | $BC | 3 | 4 (페이지 교차 시 5) |
참조: STY
LSR - 논리적 오른쪽 시프트 (Logical Shift Right)
값 = 값 >> 1, 또는 시각적으로: 0 -> [76543210] -> C
LSR은 메모리 값 또는 어큐뮬레이터의 모든 비트를 오른쪽으로 한 자리씩 시프트하여, 각 비트의 값을 다음 비트로 이동시킵니다. 0이 비트 7로 시프트되고, 비트 0은 캐리 플래그로 시프트됩니다. 이는 부호 없는 값을 2로 나누고 내림하는 것과 같으며, 나머지는 캐리에 저장됩니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 메모리에서 작동하는 주소 지정 모드는 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 값의 비트 0 |
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 0 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Accumulator | $4A | 1 | 2 |
| Zero Page | $46 | 2 | 5 |
| Zero Page,X | $56 | 2 | 6 |
| Absolute | $4E | 3 | 6 |
| Absolute,X | $5E | 3 | 7 |
NOP - 아무 작업 안 함 (No Operation)
NOP는 아무 효과가 없습니다. 단지 공간과 CPU 사이클을 낭비할 뿐입니다. 이 명령어는 원하는 시간만큼 지연시키기 위한 시간 코드 작성, 페이지 교차 여부를 보장하기 위한 패딩, 또는 바이너리에서 코드를 비활성화할 때 유용할 수 있습니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $EA | 1 | 2 |
ORA - 비트 단위 OR (Bitwise OR)
A = A | 메모리
ORA는 메모리 값과 어큐뮬레이터를 비트 단위로 포괄적 OR(inclusive-OR) 연산합니다. 입력 비트 중 하나라도 1이면 결과 비트는 1이 되고, 그렇지 않으면 0이 됩니다.
| A | 메모리 | 결과 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $09 | 2 | 2 |
| Zero Page | $05 | 2 | 3 |
| Zero Page,X | $15 | 2 | 4 |
| Absolute | $0D | 3 | 4 |
| Absolute,X | $1D | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $19 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $01 | 2 | 6 |
| (Indirect),Y | $11 | 2 | 5 (페이지 교차 시 6) |
PHA - A 푸시 (Push A)
($0100 + SP) = A
SP = SP - 1
PHA는 A의 값을 현재 스택 위치에 저장한 다음 스택 포인터를 감소시킵니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $48 | 1 | 3 |
참조: PLA
PHP - 프로세서 상태 푸시 (Push Processor Status)
($0100 + SP) = NV11DIZC
SP = SP - 1
PHP는 6개의 상태 플래그와 B 플래그를 포함하는 바이트를 스택에 저장한 다음 스택 포인터를 감소시킵니다. B 플래그와 추가 비트는 모두 1로 푸시됩니다. 비트 순서는 NV1BDIZC (높은 쪽에서 낮은 쪽으로)입니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| B - 브레이크 | 1로 푸시됨 | 이 플래그는 CPU의 실제 상태가 아닌, 스택에 푸시된 플래그 바이트에만 존재합니다. |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $08 | 1 | 3 |
참조: PLP
PLA - A 풀 (Pull A)
SP = SP + 1
A = ($0100 + SP)
PLA는 스택 포인터를 증가시킨 다음 해당 스택 위치의 값을 A로 로드합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $68 | 1 | 4 |
참조: PHA
PLP - 프로세서 상태 풀 (Pull Processor Status)
SP = SP + 1
NVxxDIZC = ($0100 + SP)
PLP는 스택 포인터를 증가시킨 다음 해당 스택 위치의 값을 6개의 상태 플래그로 로드합니다. 비트 순서는 NVxxDIZC (높은 쪽에서 낮은 쪽으로)입니다. B 플래그와 추가 비트는 무시됩니다. I 변경의 효과는 한 명령어 지연됩니다. 왜냐하면 플래그는 IRQ가 폴링된 후에 변경되어, CLI 및 SEI와 같이 다음 명령어에서 IRQ가 폴링될 때까지 효과가 지연되기 때문입니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| C - 캐리 | 결과의 비트 0 | |
| Z - 제로 | 결과의 비트 1 | |
| I - 인터럽트 비활성화 | 결과의 비트 2 | 이 플래그 변경의 효과는 1 명령어 지연됩니다. |
| D - 데시멀 | 결과의 비트 3 | |
| V - 오버플로 | 결과의 비트 6 | |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $28 | 1 | 4 |
참조: PHP
ROL - 왼쪽으로 회전 (Rotate Left)
값 = 캐리를 통해 값 << 1, 또는 시각적으로: C <- [76543210] <- C
ROL은 메모리 값 또는 어큐뮬레이터를 왼쪽으로 시프트하여, 각 비트의 값을 다음 비트로 이동시키고 캐리 플래그를 비트 7 위와 비트 0 아래에 모두 있는 것처럼 취급합니다. 구체적으로, 캐리의 값은 비트 0으로 시프트되고, 비트 7은 캐리로 시프트됩니다. 왼쪽으로 9번 회전하면 값과 캐리가 원래 상태로 돌아옵니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 메모리에서 작동하는 주소 지정 모드는 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 값의 비트 7 |
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Accumulator | $2A | 1 | 2 |
| Zero Page | $26 | 2 | 5 |
| Zero Page,X | $36 | 2 | 6 |
| Absolute | $2E | 3 | 6 |
| Absolute,X | $3E | 3 | 7 |
ROR - 오른쪽으로 회전 (Rotate Right)
값 = 캐리를 통해 값 >> 1, 또는 시각적으로: C -> [76543210] -> C
ROR은 메모리 값 또는 어큐뮬레이터를 오른쪽으로 시프트하여, 각 비트의 값을 다음 비트로 이동시키고 캐리 플래그를 비트 7 위와 비트 0 아래에 모두 있는 것처럼 취급합니다. 구체적으로, 캐리의 값은 비트 7로 시프트되고, 비트 0은 캐리로 시프트됩니다. 오른쪽으로 9번 회전하면 값과 캐리가 원래 상태로 돌아옵니다.
이것은 읽기-수정-쓰기(read-modify-write) 명령어입니다. 즉, 메모리에서 작동하는 주소 지정 모드는 수정된 값을 쓰기 전에 원래 값을 먼저 메모리에 다시 씁니다. 이 추가적인 쓰기는 하드웨어 레지스터를 대상으로 할 때 중요할 수 있습니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 값의 비트 0 |
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Accumulator | $6A | 1 | 2 |
| Zero Page | $66 | 2 | 5 |
| Zero Page,X | $76 | 2 | 6 |
| Absolute | $6E | 3 | 6 |
| Absolute,X | $7E | 3 | 7 |
RTI - 인터럽트에서 복귀 (Return from Interrupt)
스택에서 NVxxDIZC 플래그를 풀
스택에서 PC를 풀
RTI는 인터럽트 핸들러에서 복귀하며, 먼저 스택에서 6개의 상태 플래그를 풀(pull)한 다음 새로운 프로그램 카운터를 풀합니다. 플래그 풀링은 PLP처럼 동작하지만, 인터럽트 비활성화 플래그의 변경 사항이 1 명령어 지연되지 않고 즉시 적용된다는 점이 다릅니다. 이는 플래그가 명령어에 대한 IRQ가 폴링된 후가 아니라 전에 변경되기 때문입니다. PC 풀링은 RTS처럼 동작하지만, 반환 주소가 1바이트 전이 아닌 다음 명령어의 정확한 주소라는 점이 다릅니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| C - 캐리 | 풀링된 플래그의 비트 0 | |
| Z - 제로 | 풀링된 플래그의 비트 1 | |
| I - 인터럽트 비활성화 | 풀링된 플래그의 비트 2 | 이 플래그 변경의 효과는 지연되지 '않습니다'. |
| D - 데시멀 | 풀링된 플래그의 비트 3 | |
| V - 오버플로 | 풀링된 플래그의 비트 6 | |
| N - 네거티브 | 풀링된 플래그의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $40 | 1 | 6 |
RTS - 서브루틴에서 복귀 (Return from Subroutine)
스택에서 PC를 풀
PC = PC + 1
RTS는 스택에서 주소를 프로그램 카운터로 풀(pull)한 다음 프로그램 카운터를 증가시킵니다. 이는 보통 함수 끝에서 함수를 호출한 JSR 다음 명령어로 돌아가기 위해 사용됩니다. 그러나 RTS는 점프 테이블을 구현하는 데 사용되기도 합니다(Jump table 및 RTS Trick 참조).
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $60 | 1 | 6 |
SBC - 캐리와 함께 빼기 (Subtract with Carry)
A = A - 메모리 - ~C, 또는 동등하게: A = A + ~메모리 + C
SBC는 메모리 값과 캐리의 비트 단위 NOT을 어큐뮬레이터에서 뺍니다. 이는 메모리 값의 비트 단위 NOT을 ADC를 사용하여 더하는 방식으로 수행됩니다. 이 구현 세부 사항은 캐리의 역방향 특성을 설명합니다. SBC는 캐리가 설정되었을 때가 아니라 클리어되었을 때 1을 더 빼고, 언더플로가 발생하면 캐리가 클리어되고 그렇지 않으면 설정됩니다. ADC와 마찬가지로, 캐리는 한 뺄셈의 빌림(borrow)을 다음 뺄셈으로 넘겨주어 1바이트보다 큰 값의 뺄셈을 가능하게 합니다. 첫 바이트를 빼기 전에 SEC로 캐리를 설정하여 알려진 상태로 만들어, 1만큼의 오차를 피하는 것이 일반적입니다.
오버플로는 ADC와 동일하게 작동하지만, 메모리 값이 반전됩니다. 따라서 결과의 부호가 A의 부호와 다르고 메모리 값의 부호와 같으면 오버플로 또는 언더플로가 발생합니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| C - 캐리 | ~(결과 < $00) | 결과가 $00 미만으로 언더플로(랩어라운드)되면, 부호 없는 언더플로가 발생한 것입니다. |
| Z - 제로 | 결과 == 0 | |
| V - 오버플로 | (결과 ^ A) & (결과 ^ ~메모리) & $80 | 결과의 부호가 A의 부호와 다르고 메모리의 부호와 같으면, 부호 있는 오버플로(또는 언더플로)가 발생한 것입니다. |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| #Immediate | $E9 | 2 | 2 |
| Zero Page | $E5 | 2 | 3 |
| Zero Page,X | $F5 | 2 | 4 |
| Absolute | $ED | 3 | 4 |
| Absolute,X | $FD | 3 | 4 (페이지 교차 시 5) |
| Absolute,Y | $F9 | 3 | 4 (페이지 교차 시 5) |
| (Indirect,X) | $E1 | 2 | 6 |
| (Indirect),Y | $F1 | 2 | 5 (페이지 교차 시 6) |
SEC - 캐리 설정 (Set Carry)
C = 1
SEC는 캐리 플래그를 설정합니다. 특히, 이는 보통 SBC로 값의 하위 바이트를 빼기 전에 추가적인 1이 빼지는 것을 방지하기 위해 수행됩니다.
| 플래그 | 새로운 값 |
|---|---|
| C - 캐리 | 1 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $38 | 1 | 2 |
참조: CLC
SED - 데시멀 설정 (Set Decimal)
D = 1
SED는 데시멀 플래그를 설정합니다. 데시멀 플래그는 보통 BCD 모드가 활성화되는지를 제어한다. BCD 모드는 NES의 2A03 CPU에서는 사용할 수 없지만 플래그 자체는 여전히 작동하며 상태를 저장하는 데 사용될 수 있다.
| 플래그 | 새로운 값 |
|---|---|
| D - 데시멀 | 1 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $F8 | 1 | 2 |
참조: CLD
SEI - 인터럽트 비활성화 설정 (Set Interrupt Disable)
I = 1
SEI는 인터럽트 비활성화 플래그를 설정하여, CPU가 하드웨어 IRQ를 처리하지 못하게 합니다. 이 플래그 변경의 효과는 한 명령어 지연됩니다. 왜냐하면 플래그는 IRQ가 폴링된 후에 변경되어, 이전에 플래그가 0이었다면 이 명령어와 다음 명령어 사이에 IRQ가 서비스될 수 있기 때문입니다.
| 플래그 | 새로운 값 | 비고 |
|---|---|---|
| I - 인터럽트 비활성화 | 1 | 이 플래그 변경의 효과는 1 명령어 지연됩니다. |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $78 | 1 | 2 |
참조: CLI
STA - A 저장 (Store A)
메모리 = A
STA는 어큐뮬레이터 값을 메모리에 저장합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero Page | $85 | 2 | 3 |
| Zero Page,X | $95 | 2 | 4 |
| Absolute | $8D | 3 | 4 |
| Absolute,X | $9D | 3 | 5 |
| Absolute,Y | $99 | 3 | 5 |
| (Indirect,X) | $81 | 2 | 6 |
| (Indirect),Y | $91 | 2 | 6 |
참조: LDA
STX - X 저장 (Store X)
메모리 = X
STX는 X 레지스터 값을 메모리에 저장합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero Page | $86 | 2 | 3 |
| Zero Page,Y | $96 | 2 | 4 |
| Absolute | $8E | 3 | 4 |
참조: LDX
STY - Y 저장 (Store Y)
메모리 = Y
STY는 Y 레지스터 값을 메모리에 저장합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Zero Page | $84 | 2 | 3 |
| Zero Page,X | $94 | 2 | 4 |
| Absolute | $8C | 3 | 4 |
참조: LDY
TAX - A를 X로 전송 (Transfer A to X)
X = A
TAX는 어큐뮬레이터 값을 X 레지스터로 복사합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $AA | 1 | 2 |
TAY - A를 Y로 전송 (Transfer A to Y)
Y = A
TAY는 어큐뮬레이터 값을 Y 레지스터로 복사합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $A8 | 1 | 2 |
TSX - 스택 포인터를 X로 전송 (Transfer Stack Pointer to X)
X = SP
TSX는 스택 포인터 값을 X 레지스터로 복사합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $BA | 1 | 2 |
참조: TXS
TXA - X를 A로 전송 (Transfer X to A)
A = X
TXA는 X 레지스터 값을 어큐뮬레이터로 복사합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $8A | 1 | 2 |
TXS - X를 스택 포인터로 전송 (Transfer X to Stack Pointer)
SP = X
TXS는 X 레지스터 값을 스택 포인터로 복사합니다.
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $9A | 1 | 2 |
참조: TXS
TYA - Y를 A로 전송 (Transfer Y to A)
A = Y
TYA는 Y 레지스터 값을 어큐뮬레이터로 복사합니다.
| 플래그 | 새로운 값 |
|---|---|
| Z - 제로 | 결과 == 0 |
| N - 네거티브 | 결과의 비트 7 |
| 주소 지정 모드 | 옵코드 | 바이트 | 사이클 |
|---|---|---|---|
| Implied | $98 | 1 | 2 |
비고
상대 주소 지정 모드(Relative addressing)에 대해, https://www.nesdev.org/6502_cpu.txt 문서는 분기 명령어가 5개의 가능한 사이클을 갖는 것으로 나타내지만, 이 페이지에 언급된 2-4 사이클이 정확합니다.
1 PC R 옵코드 가져오기, PC 증가
2 PC R 피연산자 가져오기, PC 증가
3 PC R 다음 명령어의 옵코드 가져오기,
분기가 발생하면, 피연산자를 PCL에 더함.
그렇지 않으면 PC 증가.
4+ PC* R 다음 명령어의 옵코드 가져오기.
PCH 수정. 변경되지 않았다면 PC 증가.
5! PC R 다음 명령어의 옵코드 가져오기,
PC 증가.
이 노트들은 문서에서 사이클이 표현되는 방식을 명확히 하는 데 도움이 됩니다:
- 분기가 발생하지 않으면, 여기에 표시된 사이클 3은 실제로는 다음 명령어의 사이클 1입니다 (분기 명령어는 2 사이클 후에 종료됨).
- 분기가 발생하고 페이지 경계를 넘지 않으면, 여기에 표시된 사이클 4는 다음 명령어의 사이클 1입니다 (분기 명령어는 3 사이클 후에 종료됨).
- 페이지 경계가 교차되면, 여기에 표시된 사이클 5는 다음 명령어의 사이클 1입니다 (분기 명령어는 4 사이클 후에 종료됨).