y0u_bat

[SSA] 시스템 스터디 1주차 정리(어셈블리) 본문

System

[SSA] 시스템 스터디 1주차 정리(어셈블리)

유뱃 2015. 10. 6. 01:43

system call == api

interrput descriptor table (IDT)

0 - timer

8 - filoppy

128 - System Service Descriptor Table (약자로 SSDT)


ex) write 함수를 쓰고 싶다 하면,  ssdt[4]() 이렇게 하면 write();가 완성된다.

저기 있는 숫자는 syscall number 이다.


syscall이란  - 시스템에 미리 만들어 놓은 함수를 이용하여 처리하는 것을 말한다. 호출은 인터럽터를 사용하며 리눅스는 IDT의 128번째인(int $0x80) 인터럽터를 사용한다. 


우분투32비트 기준으로 /usr/include/asm/unistd_32.h 에서 syscall number를 볼수있다.


범용 레지스터

eax(ax,ah,al) :곱셈과 나눗셈 연산에서 자동으로 사용된다.

ebx(bx,bh,bl) : 베이스 레지스터. 특정 주소를 지정하는데 쓰인다.

ecx(cx,ch,cl) : 수를 센다. ex) 반목문에서 카운터역할

edx(dx,dht,dl) :데이터 레지스터, 입출력 연산에 반드시 간접 주소 지정에 사용된다.

esi(si) : 읽기 인덱스, 문자열 전송이나 비교에서 사용된다.

edi(di) : 쓰기 인덱스

ebp(bp) : 베이스 포인터, 스택의 데이터에 접근하기 위해 사용한다.

esp(sp) : 스택 포인터, 현재까지 사용된 스택의 위치를 저장하며 스택의 가장 꼭대기를 가르킨다.

eip : 다음 실행할 명령어의 주소를 가르킨다.

EFALGS : cpu의 동작제어나 연산의 결과를 반영한다.


보통 함수를 만들때,

eax는 syscall number로 쓰이고, ebx는 1번째 인자, ecx는 2번째 인자, 

edx는 3번째인자,esi는 4번째인자, edi는 5번째 인자, ebp는 6번째 인자로 쓰인다.


write함수를 어셈으로 나타내면


이렇게 된다.


실제로 코딩 해보았습니다.



어셈에서는 레지스터앞에 %를 붙이고 상수앞에 $표시를 붙인다.

여기서 맨위에 .globl <symbol>은 다른 어셈블러들과 호환성을 위해서 쓰인다. 

(해당 심볼을 외부참조를 가능하게 만듬)




저렇게 코딩해서 컴파일하고 실행하면 정상적으로 출력은 되나, 세그먼트 폴트가 뜨는것을 볼 수 있다.


그이유는 스택을 만들어주지도 않고(?) 정리해주지도 않았기때문이다.




이렇게 프롤로그(push %ebp;mov %esp,%ebp) 에필로그(leave;ret)을 써주면 세그먼트 폴트가 사라지는것을 볼 수 있다.



strlen 함수 구현 

구현방법 - 문자열은 null로 끝나는데 해당문자열이 null이 될때까지 카운트해서 길이를 구한다.




puts함수 구현

구현방법 - 해당문자열을 strlen함수로 길이를 구해온다음, write로 출력하는식으로 구현 해주면 된다. puts는 자동으로 \n도 출력해주기 때문에 \n도 뒤에 출력 해줘야 된다.



strchr 함수 구현 

구현방법 - 해당문자열(첫번째 인자)를 한글자씩 짤라서 검색할 문자열(두번째 인자)이랑 같을때까지 반복돌리면서 만약에 같으면 검색한 글자의 포인터주소를 리턴, 만약에 없으면 -1을 리턴한다



gets 함수 구현

구현방법 - read로 임시버퍼(ebp-0x1000)에 입력받은후 strchr를 이용해 \n을 널(0x0)으로 처리한뒤 strcpy로 원래입력할곳에 복사한다. 




strcpy 함수 구현

구현 방법 - 첫번째 인자와 두번째인자를 다 한글자씩 끊어서  첫번째인자=두번째인자  이런식으로 반복 -> 2번째인자가 널이면 첫번째 인자에 널을 넣고 리턴







ps. 스터디 하면서 하나하나 자세히 짚고 넘어간것이 정말 좋았습니다. 공부하다 보니까 어셈블리어가 엄청 재미있게 느껴지네요!!ㅋ

Comments