백준저지에서는 다양한 언어를 지원합니다. 그 중에서도 32bit Assembly 언어도 지원을 합니다. 32bit Assembly로 백준저지에서 간단한 문제를 풀어보도록 하겠습니다.


일단 로컬에서 Assebmly 코딩을 하기 위해서 어셈블 환경을 만들어 볼 것인데요, 일단 Ubuntu 16.04기준으로 하겠습니다.


nasm과 gcc를 설치해줍니다. 만약 호스트가 64bit 운영체제라면 32bit 컴파일을 위해서 gcc-multilib을 설치해줘야 합니다.


다음 명령어로 어셈블리를 ELF파일로 빌드할 수 있습니다.


nasm -f elf32 assembly.asm -o assembly.o gcc -m32 assembly.o -o assembly.out


어셈블러로 어셈블리 소스코드를 오브젝트 파일로 바꾼 뒤, 실행가능한 ELF 바이너리로 빌드하는 과정입니다.


https://www.acmicpc.net/problem/2557


백준 2557번 Hello World를 어셈블리 코드로 작성해보도록 하겠습니다.


printf 라이브러리 콜을 이용해서 작성한 코드입니다.


extern을 이용해서 사용할 함수 명을 가지고 오며, 함수의 인자를 스택에다가 push해서 호출하는 것을 확인할 수 있습니다. Calling convention에 따라서 Caller function에서 스택을 정리하는 모습(add esp, 4)도 보입니다.

 
extern printf
section .data
    msg : db "Hello World!", 0xa, 0
        
section .text
    global main
main:
    push msg
    call printf
    add esp, 4
ret



write 시스템 콜을 이용해서 작성한 코드입니다.

int명령어로 인터럽트를 발생해서 시스템 콜을 호출하며, 시스템 콜 인자를 지정된 레지스터에 넣어서 호출하는 것을 확인할 수 있습니다.

EAX에는 시스템 콜 번호(write의 시스템 콜 번호는 4입니다), EBX는 첫번째 인자(stdout=1), ECX는 write할 Address로 두번째 인자, EDX는 세번째 인자로 문자열의 길이가 들어가게 되었습니다.

 
M: db "Hello World!"
section .text
global main
main:
    mov edx, 12
    mov ecx, M
    mov ebx, 1
    mov eax, 4
    int 0x80
    ret


어셈블리로 ps 문제 등을 풀면 어셈블리 언어에 대한 이해도가 늘고 리버싱이 쉬워질 것 같습니다.

+ Recent posts