전체 코드
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov rbp, rsp ; for correct debugging (디버깅 편의성)
; 레지스터에 데이터 저장 (mov 예제)
mov eax, 0x1234 ; 32비트 레지스터 eax에 값 저장
mov rbx, 0x12345678 ; 64비트 레지스터 rbx에 값 저장
mov cl, 0xff ; 8비트 레지스터 cl에 값 저장 (최하위 1바이트만 사용)
; 부분 레지스터만 조작하는 예제
mov al, 0x00 ; rax 하위 1바이트만 변경 (나머지는 그대로)
; 레지스터 간 데이터 복사
mov rax, rdx ; rdx 값을 rax에 복사
xor rax, rax ; rax 레지스터를 0으로 초기화
ret
section .data
num db 0x00 ; 데이터 섹션에 1바이트 변수 정의
1️⃣ 레지스터란?
레지스터 정의
- CPU 내부에 존재하는 초고속 메모리
- 연산 과정에서 나오는 중간 결과값을 저장하는 임시 저장소.
- CPU가 바로 접근할 수 있어서 가장 빠른 메모리.
- 하드디스크, 메인 메모리보다 훨씬 빠르지만 용량이 매우 적다.
메모리 계층별 비교
| 저장 위치 | 속도 | 크기 |
|---|
| 레지스터 | 가장 빠름 | 매우 작음 |
| 메인 메모리(RAM) | 중간 | 크다 |
| 하드디스크 | 가장 느림 | 매우 큼 |
2️⃣ 레지스터 종류와 크기
데이터 크기 단위 정리
| 데이터 단위 | 크기 |
|---|
| bit | 0 또는 1 |
| byte | 8 bits |
| word | 2 bytes (16 bits) |
| dword (double-word) | 4 bytes (32 bits) |
| qword (quad-word) | 8 bytes (64 bits) |
범용 레지스터 (x86-64 기준)
| 레지스터 이름 | 크기 | 설명 |
|---|
| RAX | 64비트 | 가장 큰 단위 |
| EAX | 32비트 | 하위 32비트 |
| AX | 16비트 | 하위 16비트 |
| AH | 8비트 | 상위 8비트 (AX 내부) |
| AL | 8비트 | 하위 8비트 (AX 내부) |
📌 주의
- AL, AH 같은 부분 레지스터를 조작해도 전체 RAX에는 일부만 영향을 줌.
- 반대로 EAX에 값을 넣으면 상위 32비트는 자동으로 0으로 초기화됨.
3️⃣ 레지스터 사용 이유
왜 필요한가?
- CPU가 연산할 때 중간 결과를 저장할 초고속 저장소가 필요.
- RAM까지 왔다갔다 하면 너무 느리니까, 아예 CPU 내부에 빠른 저장 공간을 둠.
- 레지스터는 연산용 "작업대" 같은 존재.
5️⃣ 명령어 분석 (한 줄씩 설명)
1. %include "io64.inc"
- 외부 매크로 라이브러리 포함.
PRINT_STRING 같은 입출력 명령어를 쉽게 쓸 수 있게 해줌.
2. section .text
- 실행 코드가 저장되는 섹션 정의.
- CPU가 실제로 읽고 실행할 명령어들이 들어감.
3. global CMAIN
- 프로그램 진입점(
CMAIN)을 링커에게 알려줌.
- C의
main()과 같은 역할.
4. mov rbp, rsp
- 현재 스택 프레임 주소를 저장.
- 디버깅할 때 유용.
5. 레지스터 데이터 저장
mov eax, 0x1234
eax에 16진수 1234 저장.
- 32비트만 사용, 상위 32비트는 0으로 초기화.
mov rbx, 0x12345678
mov cl, 0xff
cl은 8비트 레지스터.
- 상위 레지스터 영향 없음 (rcx 전체는 안 바뀜).
6. 부분 레지스터 조작
mov al, 0x00
rax 하위 1바이트만 0으로 설정.
- 나머지 상위 비트는 유지.
7. 레지스터 간 데이터 이동
mov rax, rdx
rdx 값을 rax로 복사 (64비트 전체 복사).
8. 레지스터 초기화
xor rax, rax
9. 함수 종료
ret
6️⃣ 디버그 실습 포인트
디버그 방법
| 작업 | 단축키 |
|---|
| 빌드 및 실행 | F9 |
| 디버그 시작 | F5 |
| 다음 명령 실행 (Step Over) | F10 |
| 함수 안으로 들어가기 (Step Into) | F11 |
| 레지스터 창 보기 | Ctrl+R |
| 메모리 창 보기 | Ctrl+M |
디버그 시 주목할 점
- mov 실행 후 레지스터 값 변화 확인.
- al 조작 후 rax 전체 변화 확인.
- rax 전체 초기화 여부 확인.
7️⃣ 레지스터 크기와 부분 레지스터 관계 요약
| 크기 | 이름 |
|---|
| 64비트 | RAX |
| 32비트 | EAX (상위 32비트는 0으로 채움) |
| 16비트 | AX |
| 8비트 상위 | AH |
| 8비트 하위 | AL |
-
mov eax, 0x1234하면
eax = 0x00001234
rax = 0x0000000000001234 (상위 32비트 0 자동 설정)
-
mov al, 0x00하면
al만 0이 되고, 나머지는 유지.
- 결과:
rax = 0x0000000000001200
8️⃣ mov 명령어 패턴 정리
| 패턴 | 설명 |
|---|
| mov reg, 상수 | 상수를 레지스터에 저장 |
| mov reg1, reg2 | reg2 값 reg1에 복사 |
| mov [메모리], 레지스터 | 레지스터 값 메모리에 저장 |
| mov 레지스터, [메모리] | 메모리 값 레지스터로 읽기 |