MOS 6502
MOS 6502는 모스 테크놀로지사의 8비트 MPU이다. 모토로라의 6809계열의 CPU로 분류되며 명칭 또한 인텔 계열이 CPU(중앙 처리 장치)라는 단어를 사용한 데 반해, 모토로라 계열은 MPU(Main Processing Unit)라는 용어를 사용한다.
DIP-40에 있는 6502 칩. 4자리 날짜 코드는 1985년 45주차(11월) 생산을 의미함. | |
| 생산 | 1975년 |
|---|---|
| 주요 제조사 | |
| 최대 CPU 클럭 속도 | 1 MHz ~ 3 MHz |
| 명령어 집합 | MOS 6502 |
| 트랜지스터 | 3,510[1], 3,218[2] |
| 데이터 폭 | 8비트 |
| 주소 폭 | 16비트 |
| 이전 모델 |
|
| 후속 모델 | |
| 패키지 |
|
프로세서 레지스터 개수가 인텔 계열의 CPU에 비해 적으나, 제로 페이지라는 메모리 에리어 중 특수한 영역을 임시 기억공간으로 활용하여 프로세서 레지스터 부족분을 메운다. 입출력을 위한 주소 공간이 별도로 준비되어 있지 않기 때문에 메인 메모리의 일정 부분을 입출력으로 사용하는 메모리 맵 입출력 방식으로 동작한다.
명령어 집합
편집주소 모드
편집각 명령어는 주소 지정 모드에 따라 다른 수의 클럭 사이클이 필요하다:
- Implied/Accumulator: 2 사이클
- Immediate: 2 사이클
- Zero Page: 3 사이클
- Zero Page Indexed: 4 사이클
- Absolute: 4 사이클
- Absolute Indexed: 4-5 사이클 (페이지 경계 크로싱 시 +1)
- Indexed Indirect: 6 사이클
- Indirect Indexed: 5-6 사이클 (페이지 경계 크로싱 시 +1)
- 분기 명령어: 2-4 사이클 (분기하지 않으면 2, 분기하면 3, 페이지 경계 크로싱 시 4)
공식 명령어
편집데이터 전송 명령어 (Load/Store/Transfer)
편집- LDA (Load Accumulator): 메모리 값을 누산기(A)에 로드
- LDX (Load X): 메모리 값을 X 레지스터에 로드
- LDY (Load Y): 메모리 값을 Y 레지스터에 로드
- STA (Store Accumulator): 누산기(A) 값을 메모리에 저장
- STX (Store X): X 레지스터 값을 메모리에 저장
- STY (Store Y): Y 레지스터 값을 메모리에 저장
- TAX (Transfer A to X): 누산기 값을 X로 복사
- TAY (Transfer A to Y): 누산기 값을 Y로 복사
- TXA (Transfer X to A): X 값을 누산기로 복사
- TYA (Transfer Y to A): Y 값을 누산기로 복사
- TSX (Transfer SP to X): 스택 포인터 값을 X로 복사
- TXS (Transfer X to SP): X 값을 스택 포인터로 복사
산술 연산 명령어 (Arithmetic)
편집- ADC (Add with Carry): 캐리를 포함하여 메모리 값을 누산기에 더함
- SBC (Subtract with Carry): 캐리를 포함하여 메모리 값을 누산기에서 뺌
- INC (Increment): 메모리 값을 1 증가
- INX (Increment X): X 레지스터를 1 증가
- INY (Increment Y): Y 레지스터를 1 증가
- DEC (Decrement): 메모리 값을 1 감소
- DEX (Decrement X): X 레지스터를 1 감소
- DEY (Decrement Y): Y 레지스터를 1 감소
논리 연산 명령어 (Logical)
편집- AND (Logical AND): 메모리 값과 누산기의 비트 AND 연산
- ORA (Logical OR): 메모리 값과 누산기의 비트 OR 연산
- EOR (Exclusive OR): 메모리 값과 누산기의 비트 XOR 연산
- BIT (Bit Test): 메모리와 누산기의 AND 결과로 플래그 설정 (누산기는 변경 안 됨)
시프트/회전 명령어 (Shift/Rotate)
편집- ASL (Arithmetic Shift Left): 왼쪽으로 1비트 시프트, 최하위 비트에 0 삽입
- LSR (Logical Shift Right): 오른쪽으로 1비트 시프트, 최상위 비트에 0 삽입
- ROL (Rotate Left): 캐리를 포함하여 왼쪽으로 1비트 회전
- ROR (Rotate Right): 캐리를 포함하여 오른쪽으로 1비트 회전
비교 명령어 (Comparison)
편집- CMP (Compare): 누산기와 메모리 값을 비교 (A - M 연산으로 플래그 설정)
- CPX (Compare X): X 레지스터와 메모리 값을 비교
- CPY (Compare Y): Y 레지스터와 메모리 값을 비교
분기 명령어 (Branch)
편집모든 분기 명령어는 상대 주소 모드를 사용하며, 조건이 참일 때 -128~+127 범위로 점프한다.
- BCC (Branch if Carry Clear): 캐리 플래그가 0이면 분기
- BCS (Branch if Carry Set): 캐리 플래그가 1이면 분기
- BEQ (Branch if Equal): 제로 플래그가 1이면 분기 (결과가 0)
- BNE (Branch if Not Equal): 제로 플래그가 0이면 분기 (결과가 0이 아님)
- BMI (Branch if Minus): 네거티브 플래그가 1이면 분기 (결과가 음수)
- BPL (Branch if Plus): 네거티브 플래그가 0이면 분기 (결과가 양수)
- BVC (Branch if Overflow Clear): 오버플로 플래그가 0이면 분기
- BVS (Branch if Overflow Set): 오버플로 플래그가 1이면 분기
점프/서브루틴 명령어 (Jump/Subroutine)
편집- JMP (Jump): 지정된 주소로 무조건 점프
- JSR (Jump to Subroutine): 서브루틴 호출 (리턴 주소를 스택에 저장)
- RTS (Return from Subroutine): 서브루틴에서 복귀 (스택에서 주소 복원)
- RTI (Return from Interrupt): 인터럽트 처리 후 복귀 (상태와 주소 복원)
스택 명령어 (Stack)
편집- PHA (Push Accumulator): 누산기를 스택에 저장
- PHP (Push Processor Status): 프로세서 상태(P)를 스택에 저장
- PLA (Pull Accumulator): 스택에서 누산기로 복원
- PLP (Pull Processor Status): 스택에서 프로세서 상태 복원
상태 플래그 명령어 (Status Flag)
편집- CLC (Clear Carry): 캐리 플래그를 0으로 클리어
- SEC (Set Carry): 캐리 플래그를 1로 설정
- CLI (Clear Interrupt): 인터럽트 비활성화 플래그를 0으로 클리어 (인터럽트 허용)
- SEI (Set Interrupt): 인터럽트 비활성화 플래그를 1로 설정 (인터럽트 금지)
- CLV (Clear Overflow): 오버플로 플래그를 0으로 클리어
- CLD (Clear Decimal): BCD 모드 플래그를 0으로 클리어 (이진 모드)
- SED (Set Decimal): BCD 모드 플래그를 1로 설정 (BCD 모드)
기타 명령어 (Miscellaneous)
편집- NOP (No Operation): 아무 동작도 하지 않음 (2 사이클 소요)
- BRK (Break): 소프트웨어 인터럽트 발생 (디버깅용)
| 색상 | 주소 지정 모드 | 약어 | 설명 | 예시 |
|---|---|---|---|---|
| 연한 빨강 | Implied | impl | 명령어 자체에 피연산자가 내포됨 | CLC (캐리 플래그 클리어) |
| 노랑 | Accumulator | A | 누산기(A)를 피연산자로 사용 | ASL A (누산기 왼쪽 시프트) |
| 연한 초록 | Immediate | imm | 명령어 바로 다음 바이트가 값 | LDA #$42 (A에 $42 로드) |
| 연한 주황 | Zero Page | zpg | $0000-$00FF 범위의 주소 (1바이트) | LDA $80 (주소 $0080의 값 로드) |
| 주황 | Zero Page,X | zpg,X | Zero Page 주소에 X 레지스터 값 더함 | LDA $80,X ($0080+X 주소의 값) |
| 진한 주황 | Zero Page,Y | zpg,Y | Zero Page 주소에 Y 레지스터 값 더함 | LDX $80,Y ($0080+Y 주소의 값) |
| 연한 파랑 | Absolute | abs | 16비트 절대 주소 (2바이트) | LDA $1234 (주소 $1234의 값 로드) |
| 파랑 | Absolute,X | abs,X | 절대 주소에 X 레지스터 값 더함 | LDA $1234,X ($1234+X 주소의 값) |
| 파랑 | Absolute,Y | abs,Y | 절대 주소에 Y 레지스터 값 더함 | LDA $1234,Y ($1234+Y 주소의 값) |
| 하늘색 | Indexed Indirect | X,ind | (Zero Page + X) 주소에서 16비트 주소 읽음 | LDA ($80,X) (($80+X) 위치의 포인터가 가리키는 값) |
| 진한 하늘색 | Indirect Indexed | ind,Y | Zero Page 주소에서 16비트 주소 읽고 Y 더함 | LDA ($80),Y (($80) 포인터 + Y가 가리키는 값) |
| 보라 | Indirect | ind | 주소가 가리키는 곳에서 16비트 주소 읽음 (JMP만 사용) | JMP ($1234) ($1234 위치의 포인터로 점프) |
| 분홍 | Relative | rel | 현재 PC 기준 상대 오프셋 (-128~+127) | BNE $10 (0이 아니면 PC+$10으로 분기) |
| 회색 | — | — | 미정의/비공식 opcode | — |
| x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x | BRK impl |
ORA X,ind |
— | — | — | ORA zpg |
ASL zpg |
— | PHP impl |
ORA imm |
ASL A |
— | — | ORA abs |
ASL abs |
— |
| 1x | BPL rel |
ORA ind,Y |
— | — | — | ORA zpg,X |
ASL zpg,X |
— | CLC impl |
ORA abs,Y |
— | — | — | ORA abs,X |
ASL abs,X |
— |
| 2x | JSR abs |
AND X,ind |
— | — | BIT zpg |
AND zpg |
ROL zpg |
— | PLP impl |
AND imm |
ROL A |
— | BIT abs |
AND abs |
ROL abs |
— |
| 3x | BMI rel |
AND ind,Y |
— | — | — | AND zpg,X |
ROL zpg,X |
— | SEC impl |
AND abs,Y |
— | — | — | AND abs,X |
ROL abs,X |
— |
| 4x | RTI impl |
EOR X,ind |
— | — | — | EOR zpg |
LSR zpg |
— | PHA impl |
EOR imm |
LSR A |
— | JMP abs |
EOR abs |
LSR abs |
— |
| 5x | BVC rel |
EOR ind,Y |
— | — | — | EOR zpg,X |
LSR zpg,X |
— | CLI impl |
EOR abs,Y |
— | — | — | EOR abs,X |
LSR abs,X |
— |
| 6x | RTS impl |
ADC X,ind |
— | — | — | ADC zpg |
ROR zpg |
— | PLA impl |
ADC imm |
ROR A |
— | JMP ind |
ADC abs |
ROR abs |
— |
| 7x | BVS rel |
ADC ind,Y |
— | — | — | ADC zpg,X |
ROR zpg,X |
— | SEI impl |
ADC abs,Y |
— | — | — | ADC abs,X |
ROR abs,X |
— |
| 8x | — | STA X,ind |
— | — | STY zpg |
STA zpg |
STX zpg |
— | DEY impl |
— | TXA impl |
— | STY abs |
STA abs |
STX abs |
— |
| 9x | BCC rel |
STA ind,Y |
— | — | STY zpg,X |
STA zpg,X |
STX zpg,Y |
— | TYA impl |
STA abs,Y |
TXS impl |
— | — | STA abs,X |
— | — |
| Ax | LDY imm |
LDA X,ind |
LDX imm |
— | LDY zpg |
LDA zpg |
LDX zpg |
— | TAY impl |
LDA imm |
TAX impl |
— | LDY abs |
LDA abs |
LDX abs |
— |
| Bx | BCS rel |
LDA ind,Y |
— | — | LDY zpg,X |
LDA zpg,X |
LDX zpg,Y |
— | CLV impl |
LDA abs,Y |
TSX impl |
— | LDY abs,X |
LDA abs,X |
LDX abs,Y |
— |
| Cx | CPY imm |
CMP X,ind |
— | — | CPY zpg |
CMP zpg |
DEC zpg |
— | INY impl |
CMP imm |
DEX impl |
— | CPY abs |
CMP abs |
DEC abs |
— |
| Dx | BNE rel |
CMP ind,Y |
— | — | — | CMP zpg,X |
DEC zpg,X |
— | CLD impl |
CMP abs,Y |
— | — | — | CMP abs,X |
DEC abs,X |
— |
| Ex | CPX imm |
SBC X,ind |
— | — | CPX zpg |
SBC zpg |
INC zpg |
— | INX impl |
SBC imm |
NOP impl |
— | CPX abs |
SBC abs |
INC abs |
— |
| Fx | BEQ rel |
SBC ind,Y |
— | — | — | SBC zpg,X |
INC zpg,X |
— | SED impl |
SBC abs,Y |
— | — | — | SBC abs,X |
INC abs,X |
— |
비공식 명령어
편집다음 표는 NMOS 6502의 256개 opcode를 모두 포함한다. 진한 회색으로 표시된 명령어들은 MOS Technology가 공식적으로 문서화하지 않은 opcode이다. 이들은 NMOS 6502의 내부 논리 회로 특성으로 인해 작동하며, 일부는 유용한 기능을 제공한다. CMOS 버전인 65C02와 후속 프로세서인 WDC 65816에서는 대부분의 비공식 명령어가 작동하지 않으며, 공식 NOP로 대체되거나 새로운 명령어로 할당되었다.
주요 비공식 명령어:
- SLO (ASL + ORA): 메모리를 왼쪽 시프트하고 누산기와 OR 연산
- RLA (ROL + AND): 메모리를 왼쪽 회전하고 누산기와 AND 연산
- SRE (LSR + EOR): 메모리를 오른쪽 시프트하고 누산기와 XOR 연산
- RRA (ROR + ADC): 메모리를 오른쪽 회전하고 누산기에 더함
- SAX (STA + STX): A AND X의 결과를 메모리에 저장
- LAX (LDA + LDX): 메모리 값을 A와 X 모두에 로드
- DCP (DEC + CMP): 메모리를 감소시키고 누산기와 비교
- ISC (INC + SBC): 메모리를 증가시키고 누산기에서 뺌
- ANC (AND + ASL 캐리): 즉시값과 AND하고 결과의 비트 7을 캐리로
- ALR (AND + LSR): 즉시값과 AND하고 오른쪽 시프트
- ARR (AND + ROR): 즉시값과 AND하고 오른쪽 회전
- SBX (CMP + DEX): (A AND X) - 즉시값을 X에 저장
- SHA/SHX/SHY: 인덱스 레지스터와 주소 high byte의 AND 연산 (불안정)
- TAS: A AND X를 스택 포인터에 저장하고 메모리에도 기록 (불안정)
- LAS: 메모리와 스택 포인터의 AND를 A, X, SP에 저장
- JAM/KIL/HLT: CPU를 정지시킴 (리셋 필요)
- NOP (다양한 주소 모드): 공식 NOP와 동일하지만 다른 주소 모드 사용
| x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x | BRK impl |
ORA X,ind |
JAM | SLO X,ind |
NOP zpg |
ORA zpg |
ASL zpg |
SLO zpg |
PHP impl |
ORA imm |
ASL A |
ANC imm |
NOP abs |
ORA abs |
ASL abs |
SLO abs |
| 1x | BPL rel |
ORA ind,Y |
JAM | SLO ind,Y |
NOP zpg,X |
ORA zpg,X |
ASL zpg,X |
SLO zpg,X |
CLC impl |
ORA abs,Y |
NOP impl |
SLO abs,Y |
NOP abs,X |
ORA abs,X |
ASL abs,X |
SLO abs,X |
| 2x | JSR abs |
AND X,ind |
JAM | RLA X,ind |
BIT zpg |
AND zpg |
ROL zpg |
RLA zpg |
PLP impl |
AND imm |
ROL A |
ANC imm |
BIT abs |
AND abs |
ROL abs |
RLA abs |
| 3x | BMI rel |
AND ind,Y |
JAM | RLA ind,Y |
NOP zpg,X |
AND zpg,X |
ROL zpg,X |
RLA zpg,X |
SEC impl |
AND abs,Y |
NOP impl |
RLA abs,Y |
NOP abs,X |
AND abs,X |
ROL abs,X |
RLA abs,X |
| 4x | RTI impl |
EOR X,ind |
JAM | SRE X,ind |
NOP zpg |
EOR zpg |
LSR zpg |
SRE zpg |
PHA impl |
EOR imm |
LSR A |
ALR imm |
JMP abs |
EOR abs |
LSR abs |
SRE abs |
| 5x | BVC rel |
EOR ind,Y |
JAM | SRE ind,Y |
NOP zpg,X |
EOR zpg,X |
LSR zpg,X |
SRE zpg,X |
CLI impl |
EOR abs,Y |
NOP impl |
SRE abs,Y |
NOP abs,X |
EOR abs,X |
LSR abs,X |
SRE abs,X |
| 6x | RTS impl |
ADC X,ind |
JAM | RRA X,ind |
NOP zpg |
ADC zpg |
ROR zpg |
RRA zpg |
PLA impl |
ADC imm |
ROR A |
ARR imm |
JMP ind |
ADC abs |
ROR abs |
RRA abs |
| 7x | BVS rel |
ADC ind,Y |
JAM | RRA ind,Y |
NOP zpg,X |
ADC zpg,X |
ROR zpg,X |
RRA zpg,X |
SEI impl |
ADC abs,Y |
NOP impl |
RRA abs,Y |
NOP abs,X |
ADC abs,X |
ROR abs,X |
RRA abs,X |
| 8x | NOP imm |
STA X,ind |
NOP imm |
SAX X,ind |
STY zpg |
STA zpg |
STX zpg |
SAX zpg |
DEY impl |
NOP imm |
TXA impl |
ANE imm |
STY abs |
STA abs |
STX abs |
SAX abs |
| 9x | BCC rel |
STA ind,Y |
JAM | SHA ind,Y |
STY zpg,X |
STA zpg,X |
STX zpg,Y |
SAX zpg,Y |
TYA impl |
STA abs,Y |
TXS impl |
TAS abs,Y |
SHY abs,X |
STA abs,X |
SHX abs,Y |
SHA abs,Y |
| Ax | LDY imm |
LDA X,ind |
LDX imm |
LAX X,ind |
LDY zpg |
LDA zpg |
LDX zpg |
LAX zpg |
TAY impl |
LDA imm |
TAX impl |
LXA imm |
LDY abs |
LDA abs |
LDX abs |
LAX abs |
| Bx | BCS rel |
LDA ind,Y |
JAM | LAX ind,Y |
LDY zpg,X |
LDA zpg,X |
LDX zpg,Y |
LAX zpg,Y |
CLV impl |
LDA abs,Y |
TSX impl |
LAS abs,Y |
LDY abs,X |
LDA abs,X |
LDX abs,Y |
LAX abs,Y |
| Cx | CPY imm |
CMP X,ind |
NOP imm |
DCP X,ind |
CPY zpg |
CMP zpg |
DEC zpg |
DCP zpg |
INY impl |
CMP imm |
DEX impl |
SBX imm |
CPY abs |
CMP abs |
DEC abs |
DCP abs |
| Dx | BNE rel |
CMP ind,Y |
JAM | DCP ind,Y |
NOP zpg,X |
CMP zpg,X |
DEC zpg,X |
DCP zpg,X |
CLD impl |
CMP abs,Y |
NOP impl |
DCP abs,Y |
NOP abs,X |
CMP abs,X |
DEC abs,X |
DCP abs,X |
| Ex | CPX imm |
SBC X,ind |
NOP imm |
ISC X,ind |
CPX zpg |
SBC zpg |
INC zpg |
ISC zpg |
INX impl |
SBC imm |
NOP impl |
USBC imm |
CPX abs |
SBC abs |
INC abs |
ISC abs |
| Fx | BEQ rel |
SBC ind,Y |
JAM | ISC ind,Y |
NOP zpg,X |
SBC zpg,X |
INC zpg,X |
ISC zpg,X |
SED impl |
SBC abs,Y |
NOP impl |
ISC abs,Y |
NOP abs,X |
SBC abs,X |
INC abs,X |
ISC abs,X |
예제 코드
편집; TOLOWER:
;
; Convert a null-terminated character string to all lower case.
; Maximum string length is 255 characters, plus the null term-
; inator.
;
; Parameters:
;
; SRC - Source string address
; DST - Destination string address
;
ORG $0080
;
0080 00 04 SRC .WORD $0400 ;source string pointer ($40)
0082 00 05 DST .WORD $0500 ;destination string pointer ($42)
;
0600 ORG $0600 ;execution start address
;
0600 A0 00 TOLOWER LDY #$00 ;starting index
;
0602 B1 80 LOOP LDA (SRC),Y ;get from source string
0604 F0 11 BEQ DONE ;end of string
;
0606 C9 41 CMP #'A' ;if lower than UC alphabet...
0608 90 06 BCC SKIP ;copy unchanged
;
060A C9 5B CMP #'Z'+1 ;if greater than UC alphabet...
060C B0 02 BCS SKIP ;copy unchanged
;
060E 09 20 ORA #%00100000 ;convert to lower case
;
0610 91 82 SKIP STA (DST),Y ;store to destination string
0612 C8 INY ;bump index
0613 D0 ED BNE LOOP ;next character
;
; NOTE: If .Y wraps the destination string will be left in an undefined
; state. We set carry to indicate this to the calling function.
;
0615 38 SEC ;report string too long error &...
0616 60 RTS ;return to caller
;
0617 91 82 DONE STA (DST),Y ;terminate destination string
0618 18 CLC ;report conversion completed &...
0619 60 RTS ;return to caller
;
.END
각주
편집- ↑ “The MOS 6502 and the Best Layout Guy in the World”. swtch.com. 2011년 1월 3일. 2014년 9월 8일에 원본 문서에서 보존된 문서. 2014년 8월 9일에 확인함.
- ↑ “MOnSter6502 A complete, working discrete transistors (i.e. not integrated all on a single chip) replica of the classic MOS 6502 microprocessor”. monster6502.com. 2017. 2017년 5월 12일에 원본 문서에서 보존된 문서. 2017년 5월 1일에 확인함.