[ASM] 42 Libasm 과제를 해보아요~(7) gdb


2026.07.04, 17:15


디버깅을 해보자

nasm 에서는 디버깅 툴로 무엇을 쓰나요?

NASM으로 작성한 어셈블리 코드 디버깅에는 보통 다음 도구들을 사용합니다.

  • GDB: 가장 표준적인 선택입니다. nasm -f elf64 -g -F dwarf 옵션으로 디버그 심볼을 포함해 어셈블해야 소스 레벨 디버깅이 가능합니다. layout asm, layout regs 명령으로 어셈블리 명령어와 레지스터를 동시에 보면서 si(step instruction) 단위로 추적하기 편합니다.
  • objdump: objdump -d 로 컴파일된 오브젝트 파일의 디스어셈블 결과를 확인해 실제 생성된 명령어를 검증할 때 씁니다.
  • ndisasm: NASM 패키지에 포함된 디스어셈블러로, 바이너리를 다시 어셈블리로 역변환해 확인할 때 유용합니다.
  • Valgrind: 세그폴트나 메모리 접근 오류(특히 문자열 함수 구현 시 버퍼 오버런) 잡을 때 필수적입니다.

libasm 프로젝트라면 특히 GDB에서 x/10xb $rdi 같은 메모리 덤프 명령과 레지스터 상태를 함께 보면서, System V AMD64 호출 규약대로 인자가 rdi, rsi, rdx 등에 제대로 들어가는지 확인하는 워크플로우가 실용적입니다.

GDB 키는방법부터 실제 디버깅에 필요한 것들 알려주세요

4:48 PM

GDB로 NASM 어셈블리 코드를 디버깅하는 데 필요한 핵심 사항을 정리해 드리겠습니다.

1. 준비: 디버그 심볼 포함 어셈블

bash

nasm -f elf64 -g -F dwarf ft_strcmp.s -o ft_strcmp.o
ld -g -o test test.o ft_strcmp.o
# 또는 C 테스트 하네스와 함께라면
gcc -g -no-pie -o test main.c ft_strcmp.o

-g 플래그 없으면 소스 라인 매칭이 안 되고 순수 어셈블리 명령어만 보입니다.

2. GDB 실행 및 레이아웃

bash

gdb ./test

GDB 진입 후:

  • layout asm — 어셈블리 명령어 창 표시
  • layout regs — 레지스터 상태 창 표시 (asm과 동시 사용 시 layout split 유용)
  • Ctrl+L — 화면 깨졌을 때 리프레시
  • Ctrl+X, A — TUI 모드 토글 (레이아웃 진입/해제)

3. 실행 제어 (키 바인딩 겸 명령어)

명령단축키용도
break ft_strcmpb ft_strcmp함수 진입점에 브레이크포인트
runr실행 시작
stepisi어셈블리 명령어 1개 단위 진행 (call 안으로 진입)
nextini어셈블리 명령어 1개 단위 진행 (call 건너뜀)
continuec다음 브레이크포인트까지 실행
Enter (빈 입력)직전 명령 반복 — si/ni 연타 대신 사용

4. 상태 확인 명령

  • info registers (i r) — 전체 레지스터 값 확인
  • print $rdi, print $rsi — 개별 레지스터 확인 (System V AMD64 호출 규약상 정수/포인터 인자 1,2번째)
  • x/10xb $rdi — rdi가 가리키는 메모리 10바이트를 16진수로 덤프
  • x/s $rdi — rdi를 문자열로 해석해 출력 (strlen/strcpy류 검증에 유용)
  • x/10i $rip — 현재 위치부터 10개 명령어 디스어셈블 출력
  • info frame — 현재 스택 프레임 정보 (rbp, 리턴 주소 등)

5. libasm 컨텍스트에서 실전 팁

  • ft_strcmp 검증 시: 진입 직후 print $rdi, print $rsi로 두 문자열 포인터가 제대로 들어왔는지 먼저 확인 → x/s $rdi, x/s $rsi로 실제 내용 대조 → si로 한 줄씩 진행하며 rax(비교 결과 반환값) 변화 추적.
  • Segfault 발생 시 bt(backtrace)로 어디서 죽었는지 먼저 확인 후, 위 레지스터/메모리 명령으로 원인 추적.
  • 조건부 브레이크포인트가 필요하면 break *0x<주소> if $rcx==0 형태로 루프 특정 시점만 잡을 수 있습니다.

확인 필요: 현재 ft_strcmp 구현체와 테스트 하네스 코드가 있다면, 실제 어떤 지점에서 막히는지 보고 구체적인 브레이크포인트 위치를 짚어드릴 수 있습니다. 코드 공유하시겠습니까?

ft_strcmp 구현에서 문자 비교 루프를 도는 중 불일치 지점(예: .break, .diff 같은 레이블)으로 한 번에 점프하고 싶으신 걸로 이해했습니다. si/ni로 한 명령씩 추적하는 대신 아래 방법을 쓰면 됩니다.

1. 레이블에 직접 브레이크포인트 걸기

gdb

break ft_strcmp
run
break *ft_strcmp+0x2a   # .break 레이블의 실제 주소
continue

심볼 정보가 살아있다면 주소 대신 레이블명으로도 걸립니다:

gdb

break .break

단, NASM 로컬 레이블(.break처럼 점으로 시작)은 GDB가 그대로 인식 못 할 수 있어 함수명.레이블명 형태가 필요할 수 있습니다:

gdb

break ft_strcmp.break

2. 조건부 브레이크포인트로 “불일치 나는 순간”만 잡기
루프 안에서 비교하는 시점(cmp 명령 다음 줄)에 브레이크를 걸고, 두 레지스터가 다를 때만 멈추게:

gdb

break *0x<cmp_다음_주소>
condition 1 $al != $bl    # 예: al, bl에 각 바이트를 로드하는 경우
continue

3. 루프를 통째로 건너뛰고 결과만 확인
불일치 지점 자체보다 최종 결과(rax)만 필요하면:

gdb

tbreak ft_strcmp
run
finish       # 함수 리턴까지 실행 후 반환값(rax) 표시

확인 필요: 정확한 레이블명(.break가 실제 코드에 있는 이름인지)과 현재 작성하신 ft_strcmp 어셈블리 코드를 보여주시면, 정확한 주소/조건으로 명령어를 짚어드릴 수 있습니다. 코드 공유 가능하신가요?

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다