블로그

  • [ASM] 42 Libasm 과제를 해보아요~(1) Makefile


    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] 같은 포인터 역참조 문법
    빌드 흐름.snasm -f elf64.oar.a 정적 라이브러리화

    3. strlen에 그대로 적용

    C 원형: size_t strlen(const char *s)

    • 인자 srdi에 들어있음 (호출 규약상 1번째 인자)
    • 리턴값(길이) → rax에 넣어야 함
    • 로직: rdi가 가리키는 메모리를 한 바이트씩 읽으며 null(0)이 나올 때까지 카운트 증가

    이게 사실상 전체 과제 패턴입니다. strcpy, strcmp 등도 “인자가 어느 레지스터에 들어오는지 + 메모리를 어떻게 순회하는지”만 바뀌는 변주예요.

    4. 추천 진행 순서

    1. 레지스터/호출규약 표를 옆에 띄워놓고 strlen 의사코드를 어셈블리 키워드로 1:1 직역
    2. nasm 설치 후 .s.o 빌드만 먼저 성공시키기 (코드 내용은 비어있어도 됨)
    3. strlen 작성 → C 테스트 코드에서 링크해서 결과 비교 (gcc test.c libasm.a -o test)
    4. 막히면 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개 초소단위로 쪼갠 순서

    #할 일 (한 번에 한 줄만)쓰기 전에 스스로 확인할 것쓰고 나서
    1touch Makefilels로 파일 생겼는지만 확인
    2NAME = libasm.a 한 줄만이 변수, 나중에 어디서 다시 쓰일 것 같은지 한 단어로 예상make(에러 나도 정상, 의도된 것)
    3SRCS = ft_strlen.s (지금 있는 파일만).s 파일이 뭘 의미했는지 기억나는지
    4OBJS = $(SRCS:.s=.o)이 줄, 검색 없이 1분만 직접 추측해보기 (틀려도 됨)make -n 으로 OBJS가 뭘로 치환되는지 눈으로 확인
    5all: $(NAME)all이 왜 필요한지 (make 기본 타겟 개념)
    6$(NAME): $(OBJS)
    ar rcs $(NAME) $(OBJS)
    ar이 뭐 하는 명령인지 한 줄로 설명 가능한지make 실행 → 진짜 .a 파일 생기는지 확인
    7%.o: %.s
    nasm -f elf64 $< -o $@
    $<, $@가 각각 뭘 가리키는지 추측make -n으로 실제 nasm 명령이 어떻게 펼쳐지는지 확인
    8clean, fclean, re 추가이건 패턴이 거의 고정이라 그냥 작성해도 무방make re 끝까지 돌아가는지 확인

    규칙 두 가지만 지켜주세요:

    1. 한 줄(또는 한 블록) 쓰고 → 바로 make 또는 make -n 실행 → 결과 보고 다음 줄. AI한테 전체 Makefile 통째로 달라고 하지 않기.
    2. 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 등) 에러 메시지 차이를 관찰하면 암기보다 체감으로 남습니다.

  • [Arch Linux] 아치리눅스 세팅 일지


    듀얼 부팅은 귀찮거든요…

    제가 한 번 해보겠습니다.
    WSL에 Arch Linux 세팅하기.

    [1일차] 2026-05-18

    왜 하필 아치냐?

    그건 말이죠..
    멋있잖아.
    친구가 영업했어요 (예전에)

    저도 해볼래요. 최신 유행의 선도자
    I use Arch, BTW
    암튼 저 아치 씀 ㅋㅋ

    WSL 설치하기

    링크에 다 있지만서두..
    UEFI에서 가상화 키고,
    파워셸 관리자 권한으로 실행 후, “wsl –install”입력
    컴퓨터 재부팅
    https://wiki.archlinux.org/title/Install_Arch_Linux_on_WSL

    WSL에 아치 설치하기

    wsl --install archlinux

    아치 실행하기

    시작 메뉴에서 archlinux 실행
    또는 Windows shell에서 “wsl -d archlinux”

    Upgrading packages

    pacman -Syu

    https://wiki.archlinux.org/title/Pacman

    Installing specific packages

    GPT 추천 필수 패키지!!

    pacman -S base-devel git curl wget unzip

    fish shell 설치

    왜 zsh 안씀??

    왜냐묜…
    fish 써보고싶어용..

    sudo pacman -S fish

    [root@DESKTOP-123ABCD/m/c/U/yuna]# chsh -s $(which fish)
    Changing shell for root.
    chsh: Warning: "/usr/sbin/fish" is not listed in /etc/shells.
    Shell changed.
    [root@DESKTOP-123ABCD/m/c/U/yuna]# which fish
    /usr/sbin/fish

    이런 에러가 뜰 수 있는데,
    which fish 해서 나온 경로를 /etc/shells에 넣어주면 됩니다~ 짜짠~

    echo /usr/sbin/fish >> /etc/shells

    껐다 키면?
    짜자잔~
    예쁜(구라임) fish가 뜹니다!

    프롬프트 바꾸기

    근데 호스트이름 뜨는 게 좀 마음에 안들어요.. 고쳐볼게요~

    근데 굳이 hostname을 수정해야 할까요?
    프롬프트만 바꿔보아요.

    설정파일은 여기: ~/.config/fish/config.fish
    프롬프트는 이렇게 추천받았는데.. 싫은데요?????

    function fish_prompt
        set_color red
        echo -n "["(whoami)"@arch "(basename (pwd))"] "
        set_color normal
    end

    근데 큰 문제가 있었음..
    나 충격받음.. 진짜임…

    [root@DESKTOP-123ABCD/m/c/U/yuna]# vi /etc/wsl.conf
    -bash: vi: command not found
    [root@DESKTOP-123ABCD/m/c/U/yuna]# nano /etc/wsl.conf
    -bash: nano: command not found

    최소 설치라더니 진짜 최소잖아…
    이거 좀 많이 설레네요

    에디터 뭐라도 깔아주고, 이렇게 수정해볼게요.
    원본이랑 비슷하게 써볼래..

    if status is-interactive
    # Commands to run in interactive sessions can go here
    
    function fish_prompt
        set_color green
        echo -n (whoami)
        set_color normal
        echo -n "@arch "(basename (pwd))"# "
    end
    
    end

    결과

    neovim 설치

    왜 또 vim 아니고 neovim?

    그건 말이죠.. 고수들은 이거 쓰길래 나도 써보고싶엇서…

    pacman -S neovim

    근데 neovim으로 실행이 안되는거임;;

    nvim으로 실행하시면 됩니다~

    참고자료: NeoVim: Vim 사용자를 위한 현대적 에디터

    눈이 빠질 것 같아서 오늘은 여기까지..


    [2일차] 2026-05-19