.LC0:
.string "Hello World!" ; .LC0 레이블에서 문자열 할당
main:
push rbp
mov rbp, rsp ; 스택프레임 생성
mov edi, OFFSET FLAT:.LC0 ; LC0의 문자열 주소가 저장됨
mov eax, 0 ; 반환 값 초기화
call printf ; print format 호출, 문자열 인수로 넘김
mov eax, 0 ; main 함수가 정상적으로 종료됨
pop rbp ; 스택프레임 종료
ret ; 종료
.LC0과 main은 레이블이라고 부른다.
- 레이블: 인스트럭션이나 데이터의 위치를 표시해줌
push rbp
mov rbp, rsp
를 수행하므로써 스택프레임을 생성시킨다.
- esi: 복사된 데이터의 주소를 저장
- edi: 복사된 데이터의 목적지 주소(최종 도착지점)의 주소를 저장
.LC0 레이블의 주소를 edi에 저장하므로써 printf를 호출할 때
"Hello World!" 라는 문자열을 출력할 수 있게 한다.
mov eax, 0
함수가 정상적으로 종료될 때, eax는 0으로 설정되는데,
그 전에 eax를 한 번 초기화 시켜줘야한다고 한다.
- 호출 규약 (Calling Convention) 준수: 대부분의 컴파일러는 함수 호출 시에 일정한 규약을 따릅니다. 이 규약 중 하나는 함수의 반환 값에 대한 레지스터의 초기화입니다. 많은 함수가 eax 레지스터를 반환 값의 저장에 사용합니다. 그러므로 호출 이전에 eax를 0으로 초기화하여 반환 값을 제어합니다.
- 문법적 요구: 어셈블리 코드에서는 레지스터 값을 명시적으로 설정해주어야 합니다. 따라서 함수 호출 이전에 eax를 0으로 설정하는 것은 이 규칙을 따르는 것입니다.
- 의도의 명시화: 코드의 가독성을 위해 반환 값이 명시적으로 초기화되었음을 나타냅니다. 프로그래머가 반환 값의 초기화를 의도적으로 설정하여 프로그램의 동작을 명확히 합니다.
ChatGPT에게 물어 봤더니 printf 호출 전에 이러한 규약이 있다고 한다.
스택프레임이 종료되면 스택에서 종료된 스택프레임을 제거한다.