6.2. Hello, world!

6.2.1. Program layout

리눅스는 32비트 프로텍티드 모드에서 동작하며, 선형 메모리 모델(flat memory model)을 가진다. 그리고, 이진 실행파일에 ELF 포맷을 가진다.

프로그램은 여러분이 작성한 코드가 있는 .text 섹션과 (이 부분은 읽기 전용이다) 여러분의 초기화된(!) data 가 저장되어 있는 .data 섹션, 초기화되지 않은(!) 데이타가 저장되는 .bss 섹션 및 다른 표준적인 섹션들로 나뉜다. 크게 보면, .text 와 .data 의 두개의 섹션으로 나뉜다. (즉, 코드와 데이타) 그러나, 다른 섹션 없이 .text 섹션만으로도 프로그램이 가능하다. .text 섹션은 프로그램에 반드시 있어야 하는 섹션이다. (역자주 : 상상해보라! 코드 없는 프로그램 -- 말도 안된다.)

이제, 첫번째 프로그램을 작성해 보자 (역자주 : 역시나.. 헬로월드 프로그램이다 ㅡ.ㅡ)

6.2.2. NASM (hello.asm)

section     .data                           ;섹션 .data 를 선언한다.(여기부터
                                            ; .data 섹션이다.)

msg     db          "Hello, world!",0xa     ;출력할 사랑스런(!) 스트링이다.
len     equ         $ - msg                 ;친애하는(!) 문자열의 길이

section     .text                           ;여기부터 .text 섹션이다. 코드있음

                    ;ELF 링커나 로더에게 프로그램의 엔트리 포인트를 알려주어야
    global _start   ;한다. 로더 혹은 링커는 일반적으로 엔트리 포인트가 _start 
                    ;라고 가정하고 있다. 이 디폴트 설정을 바꿀려면,
                    ;ld -e foo 를 사용하라.

_start:

;stdout 에 우리의 사랑스런 문자열을 출력하자.

        mov     edx,len ;시스템 콜 4번(sys_write)은 세번째 인수로 출력할 메세지의
                        ;길이를 취한다.
        mov     ecx,msg ;시스템 콜 4번은 두번째 인수로 출력할 메세지가 담긴 메모리
                        ;주소를 취한다. 즉, 출력할 메세지로의 포인터를 취한다.
        mov     ebx,1   ;시스템 콜 4번은 첫번째 인수로 파일의 핸들(디스크립터)을 
                        ;취한다.
        mov     eax,4   ;eax 레지스터에 호출할 커널 시스템 콜의 번호를 넣어 준다.
                        ;이 경우에는 4번(sys_write) 이다.
        int     0x80    ;커널을 호출한다.

;출력이 끝났으면, exit 를 호출한다.

        mov     ebx,0   ;exit 코드로 0을 준다. (c 코드로는 exit(0);)
        mov     eax,1   ;시스템 콜 1번 (sys_exit)
        int     0x80	;커널을 호출한다.

6.2.3. GAS (hello.S)

.data                           # 섹션 .data 가 여기서부터 시작한다.

msg:
    .string	"Hello, world!\n"   # 우리의 사랑스런 문자열
    len = . - msg               # 친애하는 문자열의 길이

.text                           # 섹션 .text 가 여기서부터 시작한다.

                    # ELF 링커나 로더에게 프로그램의 엔트리 포인트를 알려주어야
    .global _start  # 한다. 로더 혹은 링커는 일반적으로 엔트리 포인트가 _start 
                    # 라고 가정하고 있다. 이 디폴트 설정을 바꿀려면,
                    # ld -e foo 를 사용하라.

_start:

# stdout 에 우리의 사랑스런 문자열을 출력하자.

    movl    $len,%edx   # 시스템 콜 4번(sys_write)은 세번째 인수로 출력할 
                        # 메세지의 길이를 취한다.
    movl    $msg,%ecx   # 시스템 콜 4번은 두번째 인수로 출력할 메세지가 
                        # 담긴 메모리 주소를 취한다. 즉, 출력할 메세지로의 
                        # 포인터를 취한다.
    movl    $1,%ebx     # 시스템 콜 4번은 첫번째 인수로 파일의 
                        # 핸들(디스크립터)을 취한다.
    movl    $4,%eax     # eax 레지스터에 호출할 커널 시스템 콜의 번호를 
                        # 넣어 준다. 이 경우에는 4번(sys_write) 이다. 
    int     $0x80       # 커널을 호출한다. 

# 출력이 끝났으면, exit 를 호출한다.

    movl    $0,%ebx     # exit 코드로 0을 준다. (c 코드로는 exit(0);)
    movl    $1,%eax     # 시스템 콜 1번 (sys_exit)
    int     $0x80       # 커널을 호출한다.