2026.07.01, 08:17
과제를 해볼거예요. Claude를 켰어요.
이거 말도 안되거든요…
그치만 번역까지는 AI 써도 되지 않을까??
.
유튜브에 asm 기초 검색해서 영상 몇 개 봤거든요..
그런데 도저히 오늘 안에 끝낼 수가 없을 것 같아서, 클로드를 굴려봤어요.
Q. 내가 생소한 분야 (어셈블리 언어) 를 공부하려고 해. 학습보다는 과제 해결을 위해서인데, 어떻게 공부해야 할까?
A. NASM x86-64 Intel 문법, 42 libasm 과제 기준으로 안내드립니다.1. 학습 전략 — “패턴 먼저, 문법은 나중”
어셈블리는 명령어 양이 적습니다 (자주 쓰는 건 15~20개 정도). 처음부터 문법책을 정독하지 말고, strlen 하나를 완전히 이해 → 나머지 함수에 패턴 복제하는 방식이 과제 해결에는 가장 빠릅니다.
2. 반드시 알아야 할 최소 개념 (5개)
개념 내용 레지스터 rax, rdi, rsi, rdx, rcx, r8, r9 (64비트), 그 하위 32/16/8비트 별칭(eax, al 등) 호출 규약 (System V AMD64) 인자는 순서대로 rdi, rsi, rdx, rcx, r8, r9 / 리턴값은 rax 기본 명령어 mov, cmp, jmp, je/jne, inc/dec, add/sub, ret, push/pop 메모리 접근 [rdi],byte [rdi+rax]같은 포인터 역참조 문법빌드 흐름 .s→nasm -f elf64→.o→ar로.a정적 라이브러리화3. strlen에 그대로 적용
C 원형:
size_t strlen(const char *s)
- 인자
s→ rdi에 들어있음 (호출 규약상 1번째 인자)- 리턴값(길이) → rax에 넣어야 함
- 로직: rdi가 가리키는 메모리를 한 바이트씩 읽으며 null(0)이 나올 때까지 카운트 증가
이게 사실상 전체 과제 패턴입니다. strcpy, strcmp 등도 “인자가 어느 레지스터에 들어오는지 + 메모리를 어떻게 순회하는지”만 바뀌는 변주예요.
4. 추천 진행 순서
- 레지스터/호출규약 표를 옆에 띄워놓고 strlen 의사코드를 어셈블리 키워드로 1:1 직역
- nasm 설치 후
.s→.o빌드만 먼저 성공시키기 (코드 내용은 비어있어도 됨)- strlen 작성 → C 테스트 코드에서 링크해서 결과 비교 (
gcc test.c libasm.a -o test)- 막히면
objdump -d로 gcc가 생성한 strlen 어셈블리와 비교확인 필요
42 캠퍼스/버전마다 libasm subject의 허용 함수 목록(malloc, write 등)과 함수명 prefix 규칙(언더스코어 유무)이 다를 수 있어, 정확한 subject 원문을 같이 보면 더 정밀하게 도와드릴 수 있습니다.
그래그래.
잘 알았다, 너희들의 실력.
(내가) 시시해서 죽고 싶어졌다.

다 알려줬잖아.
근데 못하겠는거임….
해서 “그래서 이제 뭐함?”을 무한 반복하며 뭐라도 사부작거려봅니다.
.
패키지 설치
sudo apt update
sudo apt install -y nasm gcc make binutils
테스트 파일로 빌드 파이프라인 검증
test.s
section .text
global ft_strlen
ft_strlen:
xor rax, rax
.loop:
cmp byte [rdi + rax], 0
je .end
inc rax
jmp .loop
.end:
ret
test.c
#include <stdio.h>
unsigned long ft_strlen(const char *s);
int main(void)
{
printf("%lu\n", ft_strlen("hello"));
return 0;
}
빌드
nasm -f elf64 test.s -o test.o
gcc test.c test.o -o test
./test
짜잔~ 에러가 나요
gcc test.c test.o -o test
/usr/bin/ld: warning: test.o: missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
Q. 에러나요
A. 이건 에러가 아니라 **경고(warning)**라서, 실행 결과 자체(5출력)는 정상일 겁니다. 다만 NASM으로 작성한.o파일에는 기본적으로 “이 코드는 실행 가능한 스택이 필요 없다”는 메타데이터(.note.GNU-stack섹션)가 빠져 있어서 링커가 안전을 위해 경고를 띄우는 겁니다.원인
- C 컴파일러(gcc)는 자동으로
.note.GNU-stack섹션을 넣어주지만, NASM은 안 넣습니다.- 이게 없으면 링커가 “스택을 실행 가능(executable) 상태로 처리해도 되는 거냐?”를 보수적으로 가정 → 보안상 바람직하지 않은 설정으로 빌드될 수 있어 경고가 뜹니다.
해결 방법 (둘 중 하나)
방법 1:
.s파일 맨 아래에 한 줄 추가 (권장, 42 norm에서도 흔히 쓰는 방식)section .note.GNU-stack noalloc noexec nowrite
…
(후략)
그래서 이제 뭐함?
클로드: Makefile 작성할까요?
넹
클로드: 이거 먹어 (42줄짜리 Makefile)
.
해서 받아쓰기 하고 있었는데,
문득 이게 맞나 싶어진거에요…
Q. 나는 42의 libasm 과제를 진행중이야. ai가 읊어주는대로 따라 치기만 하는 것 같아서 이게 맞나 싶고, 그래서 그런지 한 문장 타이핑하고 잠깐 자리에서 일어나서 방황하고를 반복하는 중이야. 내가 작업을 계속할 수 있도록 작은 범위로 할일을 쪼개줘.
“한 문장 치고 방황”할 때, 멈추는 이유에 가장 가까운 건:
집중이 안됨 / 너무 ai 의존적인 것 같음 / 내 실력이 아닌 느낌
A. 그러면 할 일을 잘게 쪼개는 것보다, “한 줄 치고 즉시 결과 확인” 구조로 만드는 게 더 맞을 것 같아요. AI가 완성된 줄을 불러주는 대신, 한 줄 쓸 때마다make를 바로 돌려서 본인 눈으로 결과를 보는 식이면 “받아쓰기” 느낌이 줄어듭니다.Makefile을 8개 초소단위로 쪼갠 순서
# 할 일 (한 번에 한 줄만) 쓰기 전에 스스로 확인할 것 쓰고 나서 1 touch Makefile— ls로 파일 생겼는지만 확인2 NAME = libasm.a한 줄만이 변수, 나중에 어디서 다시 쓰일 것 같은지 한 단어로 예상 make(에러 나도 정상, 의도된 것)3 SRCS = ft_strlen.s(지금 있는 파일만).s파일이 뭘 의미했는지 기억나는지— 4 OBJS = $(SRCS:.s=.o)이 줄, 검색 없이 1분만 직접 추측해보기 (틀려도 됨) make -n으로 OBJS가 뭘로 치환되는지 눈으로 확인5 all: $(NAME)all이 왜 필요한지 (make 기본 타겟 개념)— 6 $(NAME): $(OBJS)ar rcs $(NAME) $(OBJS)ar이 뭐 하는 명령인지 한 줄로 설명 가능한지make실행 → 진짜.a파일 생기는지 확인7 %.o: %.snasm -f elf64 $< -o $@$<,$@가 각각 뭘 가리키는지 추측make -n으로 실제 nasm 명령이 어떻게 펼쳐지는지 확인8 clean,fclean,re추가이건 패턴이 거의 고정이라 그냥 작성해도 무방 make re끝까지 돌아가는지 확인규칙 두 가지만 지켜주세요:
- 한 줄(또는 한 블록) 쓰고 → 바로
make또는make -n실행 → 결과 보고 다음 줄. AI한테 전체 Makefile 통째로 달라고 하지 않기.- 4번, 7번처럼 “처음 보는 문법”이 나오면, AI한테 답부터 받지 말고 먼저 1분 추측 → 그다음 맞는지만 확인 요청. 이게 “받아쓰기”와 “이해”의 차이를 만드는 지점이에요.
그래그래 내가 대답해볼게?
2.
make 실행 시 all: $(NAME) -> $(NAME): 실행. 정적 라이브러리를 만듦
보충: 인자 없이make를 치면 파일 내 첫 번째 target(=all)이 기본 목표가 되고, 그게$(NAME)에 의존하므로 연쇄적으로 라이브러리 빌드 규칙이 실행됩니다.
질문: bonus가 첫번째 타겟이라면, 인자 없이make를 쳤을 때 bonus가 기본 목표인가?
확인:3. s 는 asm 확장자
보충: 결과적으로 맞지만, 엄밀히.s는 “assembly”의 약자가 아니라 “source“의 약자입니다. nasm은 보통.asm을 더 흔히 쓰지만.s도 어셈블리 소스 확장자로 통용됩니다.4.
OBJS = $(SRCS:.s=.o)OBJS 변수 선언. SRCS의 각 파일에서 .s를 .o로 치환한 것이 OBJS라는 뜻
보충: 정확한 이해입니다.
5. all이 왜 필요할까? 모르겠다.. 리링크 방지려나
보충: “리링크 방지”는 make의 타임스탬프 기반 의존성 추적 개념이고, all과는 무관합니다. all이 필요한 이유는 make의 기본 동작 규칙 때문입니다: make를 인자 없이 실행하면 Makefile에서 가장 먼저 나온 target을 자동으로 목표로 삼습니다. 그 첫 target을 관례적으로 all이라 이름 붙이는 것 뿐이며, NAME을 첫 줄에 바로 뒀다면 굳이 all 없어도 동작은 합니다. 다만 나중에 clean, fclean, re 등 여러 target이 늘어날 때 “빌드”라는 목적으로 명시적으로 표시하기 위한 관례(convention)입니다.
6. ar은 아카이빙. 정적 라이브러리 만드는 명령어. ar rcs… 는 새로 만들고, 모르겠음..
보충: ar 설명은 맞음. rcs는 각각 독립된 옵션 조합. r = 아카이브에 파일을 삽입(이미 있으면 교체), c = 아카이브를 새로 만들 때 경고 메시지 억제(create), s = 아카이브 안에 심볼 인덱스를 기록(ranlib과 동일 효과 – 이게 없으면 링커가 .a 안에서 심볼을 못 찾아 링크 에러가 날 수 있음).
7. $<는 첫번째, $@는 %부분. 확장자 제외 이름
보충:$<=첫 번째 전제조건(prerequisite), 즉 매칭된.s파일 — 이건 정답입니다. 하지만$@는 “%부분(확장자 제외 이름)”이 아니라 target 전체 이름입니다. 즉ft_strlen.o라면$@=ft_strlen.o(확장자 포함 전체). “확장자 제외 이름(stem)”을 가리키는 건$@가 아니라 **$***입니다.$<,$@,$*를 헷갈리신 겁니다.
보충:
4번:all= “make 기본 타겟” 개념으로 정정 필요. Makefile 첫 줄에 아무 target이나 두면 그게 기본 실행 대상이 된다는 걸touch파일 두 개짜리 장난감 Makefile로 직접 실험해보시길 권합니다 (target_a,target_b순서 바꿔가며make실행 → 뭐가 실행되는지 관찰).
4번 예제 코드.
target_a:
echo hi
target_b:
echo bye
현재 상태에서 타겟 없이 make만 실행 시 hi
target_a, target_b 순서를 바꿨을 때,
타겟 없이 make만 실행 시 bye 출력되는 것 확인
보충:
6번:$@vs$*구분이 실전 디버깅에서 자주 헷갈리는 포인트입니다.make -n으로 실제 명령이 어떻게 치환되는지 눈으로 다시 확인하시길 권합니다 — 특히$@자리에.o까지 포함된 전체 파일명이 찍히는지 확인하시면 헷갈림이 정리됩니다.
target_a, target_b 순서를 바꿨을 때,
타겟 없이 make만 실행 시 bye 출력되는 것 확인
보충:
5번: rcs 세 플래그를 각각 빼고make돌려보면서 (ar rc,ar rs,ar cs등) 에러 메시지 차이를 관찰하면 암기보다 체감으로 남습니다.

