Project/OStrial in AMAZON

#4 어셈블리_함수

NONE_31D 2019. 10. 16. 01:11

 

사실 어셈블리는 함수라는 것이 존재한다기보다는 레이블을 이용하여 함수를 구현해내는 것에 가깝다고 생각함. 

 

    printf:
        push eax

    printf_loop:
        or alal
        jz printf_end
        mov albyte [esi]
        mov byte [es:edi], al
        inc edi
        mov byte [es:edi], 0x09
        inc esi
        inc edi
        jmp printf_loop

    printf_end:
        pop eax
        ret

 

위 코드는 3번째 포스트에서 썼던, 문자열을 출력시키는 코드이다.

 

보통 함수라고 한다면, 저기 표시되어 있는 printf:, printf_loop: 등, 콜론이 달려 있는 부분이 함수 이름이고 함수를 호출하면 그 안에서 돌고 알아서 끝나지 않나 싶은데 아니다. 

 

어셈블리에서 printf: 처럼 콜론으로 표시되어 있는 부분은 레이블로서, 해당 주소를 명명하게 되는 것이다. 

간단하게 말하자면, 만약 앞에서 이런 식으로 코드를 쓰면

    jmp print_f

프로그램 실행 중 print_f라는 이름의 주소로 이동이 되는 것이지, 해당 함수로 이동을 하는 것이 아니다.

그러다보니 코드 실행도 신기하게 되는데 위 코드에서

printf: 1번

printf_loop: 2번

printf_end: 3번

이렇게 넘버링을 해보자. 만약 jmp printf를 진행하게 된다면,  실행 과정은 1번하고 끝나는 것이 아닌, 1번, 2번, 3번 순으로 쭉 실행된 후, printf_end: 아래의 ret구문을 만나 다시 돌아가게 된다.

ret 구문이 없다면, printf_end: 아래의 코드로 쭉 직진을 하게 될 것이다.

 

함수로 구현을 하기 위해서는 필수적으로 함수의 프롤로그와 에필로그를 구현해야 하고, 그게 아닌 단순히 어디로 이동하고 싶은것이라면 레이블만 사용하면 된다.

* 함수의 프롤로그, 에필로그: https://pseudo-comsci.tistory.com/25

 

가끔 레이블을 통해 어디로 이동하는 것이 아닌, 아예 프로그램을 끝내고 싶을 때가 있는데 그럴 때는 간단하게

    end:  

다음처럼 레이블 뒤에 아무것도 없는 레이블을 만들어주면 된다. (코드의 제일 마지막에 들어갈 수 밖에 없음. ) 조건문 등으로 프로그램을 끝내고 싶을 경우, jmp end 를 해주면 끝난다.