처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.04.21 23

C의 strcpy는 사실 어떻게 만들어질까 - x86-64 문자열 명령어로 직접 구현해보기

Hacker News 원문 보기

strcpy 안을 들여다본 적 있나요?

C 언어 공부할 때 strcpy, strlen, strcmp 같은 함수는 그냥 쓰기만 하는 도구였잖아요. 헤더에 선언되어 있고, 쓰면 작동하는 블랙박스였죠. 그런데 이 함수들이 내부적으로 어떻게 구현되어 있을까 궁금해본 적 있으신가요? 단순히 C로 루프만 돌리는 걸까요, 아니면 뭔가 더 특별한 게 있을까요? 이번에 공유된 "Writing string.h functions using string instructions in asm x86-64"라는 글이 바로 이 질문에 답을 주는데요, x86-64 CPU에는 문자열 처리 전용 명령어가 따로 존재하고 그걸로 strcpy, strlen, strcmp 같은 걸 직접 만들어보는 내용이에요.

CPU 안에 숨어 있는 문자열 전용 명령어들

x86 계열 CPU에는 MOVSB, STOSB, LODSB, CMPSB, SCASB 같은 이름의 명령어들이 있어요. 여기서 "S"는 String의 S고, 맨 끝의 "B"는 Byte라는 뜻이에요(워드, 더블워드, 쿼드워드 버전도 각각 있고요). 이 명령어들의 공통점이 뭐냐면, RSI(source index)와 RDI(destination index) 레지스터를 소스와 목적지 주소로 자동으로 쓰고, 실행할 때마다 그 값을 1씩 증가(또는 방향 플래그에 따라 감소)시킨다는 점이에요. 일종의 반자동 포인터 산술이 CPU 레벨에 박혀 있는 거죠.

예를 들어 MOVSB는 "RSI가 가리키는 바이트를 RDI가 가리키는 곳으로 복사하고, 둘 다 1씩 증가"를 한 명령어로 해치워요. 여기에 REP 접두사를 붙이면 더 강력해져요. rep movsb는 "RCX 레지스터 값만큼 반복해라"라는 뜻이라서, 이 한 줄이면 N바이트 memcpy가 끝나거든요. C로 치면 for 루프로 dst++ = src++를 N번 도는 것과 같은 일을, CPU가 마이크로코드 레벨에서 최적화해서 실행하는 셈이에요.

strlen, strcmp를 한 줄로 만들기

strlen을 이 방식으로 만들려면 SCASB(Scan String Byte)를 써요. SCASB는 AL 레지스터 값과 RDI가 가리키는 바이트를 비교하고 RDI를 증가시키는 명령어거든요. 그러니까 AL에 0(널 종료 문자)을 넣고 repne scasb를 실행하면 "0이 나올 때까지 스캔해라"라는 뜻이 돼서 문자열 끝을 찾을 수 있어요. repne는 "같지 않은 동안 반복"이라는 의미예요. 실행이 끝난 뒤에 RDI와 시작 주소의 차이를 계산하면 그게 곧 문자열 길이가 되는 거죠.

strcmp도 비슷해요. CMPSB로 두 문자열을 바이트 단위로 비교하다가 다르면 멈추는 식이에요. 코드는 놀랍도록 짧아요. 하지만 여기서 중요한 반전이 있는데요, 요즘 컴파일러는 이런 string 명령어 대신 SSE/AVX 같은 SIMD 명령어로 한 번에 16바이트, 32바이트씩 처리하는 코드를 내보낸다는 점이에요. 실제 glibc의 strlen은 REP SCASB를 쓰지 않고 벡터화된 구현을 써요. 그래서 "교과서적인 구현"과 "실전 구현"이 꽤 달라요.

그래도 왜 다시 주목받을까

이런 저수준 이야기가 요즘 다시 이야기되는 이유는 재미있어요. 한쪽에서는 Rust, Go, TypeScript가 대세가 되면서 어셈블리를 볼 일이 거의 없어졌지만, 다른 한쪽에서는 LLM 추론 최적화, 고성능 컴퓨팅, 커널/하이퍼바이저 같은 영역에서 여전히 한 사이클이 아쉬운 상황이 많거든요. 특히 memcpy 성능은 지금도 활발히 연구되는 주제예요. 인텔은 Fast Short REP MOV라는 기능을 최신 CPU에 넣어서 REP MOVSB의 성능을 극적으로 끌어올렸고, 짧은 복사 구간에서는 오히려 이게 SIMD 기반 memcpy보다 빠를 수 있어요. 즉, "낡은 명령어 = 느리다"라는 선입견이 깨지고 있는 거죠.

한국 개발자에게 주는 시사점

현업에서 어셈블리를 직접 쓸 일은 거의 없지만, 성능 문제를 진지하게 파고드는 순간에는 이 정도의 이해가 결정적일 수 있어요. 예를 들어 프로파일러를 돌렸는데 memcpy에서 시간이 많이 빠진다면, 그게 정말 memcpy 자체의 문제인지, 캐시 미스 때문인지, 아니면 짧은 복사가 너무 많아서 함수 호출 오버헤드가 더 큰 건지 판단해야 하거든요. 이런 판단은 CPU가 바이트를 어떻게 움직이는지 감이 있어야 가능해요.

학습 루트로 추천하자면 Compiler Explorer(godbolt.org)에 간단한 C 코드를 넣고 어떤 어셈블리가 나오는지 관찰하는 것부터 시작해보세요. -O0-O3의 차이를 보는 것만으로도 공부가 되고, memcpy 호출이 어떻게 풀리는지, strlen이 어떤 벡터 명령어로 변하는지 보는 재미가 쏠쏠해요.

마무리

우리가 매일 쓰는 C 표준 함수 하나하나가 사실은 CPU 제조사들이 수십 년 동안 갈고 닦은 명령어의 얇은 래퍼라는 걸 알게 되면, 시스템을 바라보는 눈이 한 층 깊어지거든요. 여러분은 마지막으로 어셈블리를 들여다본 게 언제인가요? 실무에서 저수준 지식이 결정적이었던 순간이 있으셨다면 댓글로 공유해주세요.


🔗 출처: Hacker News

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

AI 도구, 직접 활용해보세요

AI 시대, 코딩으로 수익을 만드는 방법을 배울 수 있습니다.

AI 활용 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.