문자열 복사 함수

예: 문자열 복사 함수

C로 작성한 함수를 어셈블리로 작성해보자.

매개변수 dst, src 모두 포인터형(char*)이다

C에서는 포인터가 주소를 추상화해주지만, 6502 어셈블리에서는 이 포인터를 **제로페이지 2바이트(pdst, psrc)**로 직접 구현해야 한다. 즉 char* dstpdst(lo) + pdst+1(hi) 조합으로 16비트 주소를 표현한다.

주석으로 함수 시그니처를 보충하자.

<(pdst)>

인자로 들어온 (pdst)가 바뀐다는 의미이다.

  • 상세 설명에도 modifies: (pdst)를 명시했다.

제로 페이지를 이용해 인자를 전달하자.

함수니까 가장 먼저 rts를 작성하자.

문자열 1바이트를 복사하는 코드를 작성했다.

이 과정에서 A 레지스터, 프로세스 상태 레지스터가 모두 바뀌니 주석을 수정하자

  • <A, P, (pdst)>
  • modifies: A P (pdst)

하지만 이렇게 구현하면 안 된다.

문자열 복사 테스트 1

바이트 분리 시 자릿수(위치 정보)는 값이 아닌 저장 위치가 결정한다

copy 변수의 $1010<>로 분리하면 둘 다 $10이 된다. 값 자체에서는 상위/하위 구분이 사라진다.

lda #<copy    ; $10 (하위 바이트)
sta pdst      ; 주소+0에 저장 → ×1 계수
lda #>copy    ; $10 (상위 바이트)  
sta pdst+1    ; 주소+1에 저장 → ×256 계수

리틀 엔디안에서 **연속된 메모리 위치(pdst, pdst+1)**에 저장하는 행위 자체가 곱셈 계수(×1, ×256)를 부여하여 16비트 주소 $1010을 복원 가능하게 한다.

str=$1000은 바이트 분리가 더 직관적인 예시

$1010과 달리, $1000은 상위/하위 바이트가 다르므로 구분이 명확하다.

lda #<str    ; $00 (하위 바이트)
sta psrc     ; 주소+0에 저장 → ×1 계수   → $0000
lda #>str    ; $10 (상위 바이트)
sta psrc+1   ; 주소+1에 저장 → ×256 계수 → $1000

복원: $0000 + $1000 = $1000

반면 copy=$1010은 둘 다 $10이라 값만 보면 구분이 안 되지만, **저장 위치(psrc vs psrc+1)**가 자릿수를 결정하므로 동일하게 복원된다.

리틀 엔디안은 메모리 저장 규칙이지 표기 규칙이 아니다

소스코드에서 str=$1000처럼 주소를 쓸 때는 사람이 읽기 편한 순서(상위→하위)를 따른다. 리틀 엔디안이 적용되는 시점은 <, >로 바이트를 분리해서 실제 메모리에 배치할 때(pdst, pdst+1)부터다.

이제 jsr strcpy를 실행하면 함수 호출부로 점프한다.

lda psrc를 실행했다.

zeropage 주소 지정 모드

제로 페이지에 저장된 값 00을 A 레지스터로 로드한다.

이는 의도한 결과가 이니다.

원래의 의도는 psrc, psrc+1을 읽어 주소를 구하고 이 주소에 저장된 값인 H를 읽어오는 것이다.

문자열 복사 테스트 2

함수 내부에서 절대 간접 주소지정 모드를 사용했다.

컴파일 해보면 컴파일이 안 된다..

lda, sta의 주소지정 모드가 잘 못 됬다.

lda, sta 둘 다 절대 간접 주소지정 모드를 지원하지 않는다.

절대 간접 주소지정 모드 (a)는 jmp만 지원한다

ldasta는 절대 간접 모드를 지원하지 않는다. 따라서 포인터를 통해 메모리에 접근하려면 **제로페이지 간접 모드 (zp),y**를 사용해야 한다.

니모닉(a) 지원 여부
jmp6C
lda
sta

이 제약 때문에 포인터를 제로페이지에 저장하고 (zp),y로 우회하는 패턴이 필수적이다.