전체 코드
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov rbp, rsp ; 디버깅 편의 위한 스택 프레임 저장
; a 배열 출력 (1바이트씩)
xor ecx, ecx
LABEL_PRINT_A:
PRINT_HEX 1, [a+ecx]
NEWLINE
inc ecx
cmp ecx, 5
jne LABEL_PRINT_A
NEWLINE
; b 배열 출력 (2바이트씩)
xor ecx, ecx
LABEL_PRINT_B:
PRINT_HEX 2, [b+ecx*2]
NEWLINE
inc ecx
cmp ecx, 5
jne LABEL_PRINT_B
xor rax, rax
ret
section .data
a db 0x01, 0x02, 0x03, 0x04, 0x05
b times 5 dw 1
section .bss
num resb 10
📌 배열이란?
- 같은 타입의 데이터를 연속해서 저장하는 자료구조
- 각 원소(Element)는 연속된 메모리 주소에 배치된다.
- 각 원소의 위치는 인덱스(Index)로 접근한다.
- 어셈블리에서는 주소 + 오프셋으로 배열 요소를 직접 접근해야 한다.
📌 배열 선언 방식
| 섹션 | 선언 방법 | 의미 |
|---|
.data | a db 1,2,3 | 초기화된 배열 (데이터 존재) |
.bss | num resb 10 | 초기화되지 않은 배열 (0으로 채움) |
📌 배열 메모리 구조
section .data
a db 1, 2, 3, 4, 5 ; 1바이트씩 5개 (총 5바이트)
b times 5 dw 1 ; 2바이트씩 5개 (총 10바이트)
| 주소 | 값 (a 배열) |
|---|
| a+0 | 1 |
| a+1 | 2 |
| a+2 | 3 |
| a+3 | 4 |
| a+4 | 5 |
| 주소 | 값 (b 배열) |
|---|
| b+0 | 0x0001 |
| b+2 | 0x0001 |
| b+4 | 0x0001 |
| b+6 | 0x0001 |
| b+8 | 0x0001 |
📂 전체 예제 코드 분석 (완성본)
%include "io64.inc"
section .text
global CMAIN
CMAIN:
mov rbp, rsp ; 디버깅 용 스택 프레임 설정
rbp 설정으로 디버거에서 스택 추적 용이하게 함
🧵 a 배열 모든 데이터 출력 (1바이트씩)
xor ecx, ecx ; index 초기화 (ecx = 0)
- 배열 인덱스 역할을 할
ecx를 0으로 초기화
LABEL_PRINT_A:
PRINT_HEX 1, [a+ecx] ; a 배열의 ecx번째 값 출력
NEWLINE
inc ecx ; 인덱스 증가
cmp ecx, 5 ; 5번째 요소까지 출력했는지 확인
jne LABEL_PRINT_A ; 아직이면 계속 출력
| 인덱스(ecx) | 주소(a+ecx) | 값 |
|---|
| 0 | a+0 | 0x01 |
| 1 | a+1 | 0x02 |
| 2 | a+2 | 0x03 |
| 3 | a+3 | 0x04 |
| 4 | a+4 | 0x05 |
🧵 b 배열 모든 데이터 출력 (2바이트씩)
NEWLINE ; a 배열 출력 끝났으니 줄바꿈
xor ecx, ecx ; index 초기화
LABEL_PRINT_B:
PRINT_HEX 2, [b+ecx*2] ; b 배열의 ecx번째 요소 (2바이트) 출력
NEWLINE
inc ecx ; 인덱스 증가
cmp ecx, 5 ; 5개 출력했는지 확인
jne LABEL_PRINT_B ; 아니면 계속 출력
b 배열은 각 요소가 2바이트 크기(dw) 이므로 ecx*2로 주소 계산
- 리틀 엔디안 방식으로 저장됨
- 실제 메모리 (b 배열)는 다음과 같이 저장
주소 값
b+0 0x0001
b+2 0x0001
b+4 0x0001
b+6 0x0001
b+8 0x0001
📂 데이터 섹션 (.data)
section .data
a db 0x01, 0x02, 0x03, 0x04, 0x05 ; 1바이트씩 5개
b times 5 dw 1 ; 2바이트짜리 1을 5번 초기화 (총 10바이트)
📂 초기화되지 않은 메모리 섹션 (.bss)
section .bss
num resb 10 ; 10바이트 공간 확보 (초기화X, 모두 0)
📂 종료 처리
xor rax, rax ; 반환 값 0 (정상 종료 의미)
ret ; main 종료
💡 메모리 주소 계산법 정리
| 배열 타입 | 주소 계산 |
|---|
db (1바이트) | [배열이름 + 인덱스] |
dw (2바이트) | [배열이름 + 인덱스*2] |
dd (4바이트) | [배열이름 + 인덱스*4] |
📌 리틀 엔디안 복습
- x86-64는 리틀 엔디안 방식
- 다바이트 이상의 데이터는 하위 바이트부터 먼저 저장
- 예)
dw 0x1234 저장 시 → 메모리엔 34 12 순서로 저장
🏆 배열 출력 전체 흐름 요약
| 단계 | 설명 |
|---|
| 1 | 인덱스 초기화 |
| 2 | 요소 데이터 읽기 |
| 3 | 데이터 출력 |
| 4 | 인덱스 증가 |
| 5 | 끝까지 반복 |