기초 어셈블리 프로그래밍 질문입니다.
글쓴이: HDNua / 작성시간: 월, 2013/04/08 - 5:00오후
안녕하세요. 요즘 리버스 엔지니어링을 공부하고자
강병탁 저자님의 '리버스 엔지니어링 바이블'을 읽고 있습니다.
저자님은 모르는 게 나올 때마다 찾아보면서 공부해도 된다고 하셨지만,
기본적으로 배운 적이 없는 언어이다보니 익숙해지기가 여간 쉽지 않습니다.
어셈블리 강좌와 같은 키워드로 검색해도... 많이 있을법한데 어째선지
마음에 드는 강좌가 있지는 않네요.
C를 공부할 때는 Hello, world!라는 멋진 프로그램으로 테스트를 해볼 수 있으니
이 언어가 어떻게 사용하는 언어이겠다는 게 눈에 들어는 오는 데 반해,
이 어셈블리라는 녀석은 아예 main과 같은 진입점을 정의하는 것도 잘 모르겠습니다.
게다가 찾아보니 MASM, NASM이라 하여 어셈블리도 종류가 나뉜 것 같더군요.
일단 Visual Studio가 가장 편하기에 MASM을 배우려고 합니다.
여튼 드리려는 질문은 진입점 뭐 그런 문제가 아니라 아래와 같습니다.
int sum1(int f, int l) { int s = 0; while (f <= l) s += f++; return s; } int main() { sum1(1, 3); return 0; }
C의 __asm 키워드를 이용하여 어셈블리를 작성해볼 수 있으므로, 먼저 위와 같이
첫 번째 인자부터 두 번째 인자까지의 총 합을 구하는 프로그램을 C로 작성하였습니다.
아래는 이를, 제가 나름대로 이해한 어셈블리로 재작성한 프로그램입니다.
__declspec(naked) int sum2(int f, int l) { __asm{ push ebp mov ebp, esp push eax // int s = 0; sub esp, 4 mov dword ptr ss:[esp-0x4], 0 // while (f <= l) loop_check: mov eax, dword ptr ss:[ebp+0x8] cmp eax, dword ptr ss:[esp+0xc] jg loop_end // s += f++; mov eax, dword ptr ss:[esp-0x4] add eax, dword ptr ss:[esp+0x8] mov dword ptr ss:[esp-0x4], eax mov eax, dword ptr ss:[esp+0x8] add eax, 1 mov dword ptr ss:[esp+0x8], eax jmp loop_check loop_end: // return s; mov eax, dword ptr ss:[esp-0x4] pop eax mov esp, ebp pop ebp } } int main() { sum2(1, 3); __asm{ sub esp, 8 } return 0; }
F10 버튼을 눌러 인터프리터로 들어가 차근차근 살펴보는데,
중간중간 eax, f, l의 값을 디버거로 보고 있자면, 생각한 것과 다르게 나옵니다.
일단 f가 3이 되고 l이 0이 되는 문제부터 시작하여
s += f++; 구문을 위한 덧셈에서는 eax에 주솟값을 더하는 것처럼 보이더군요.
맨땅에 헤딩하는 식으로 배우려니... 도전이기도 하면서 어렵기도 합니다. KLDP 분들의 가르침을 구합니다.
감사합니다.
Forums:
흠..
EAX 레지스터가 나오는걸 보니 인텔아키텍쳐 베이스로 보시는듯하네요.
인텔 어셈블리의 경우 기존 도큐먼트도 많고, 구하실수 있는 저서로는 MASM 6.X 책중 달팽이 그림있는 책을 한번 보시고 나신이후
해당 코드를 보시면 어셈블리코드가 이해되실듯 합니다.
NASM과 MASM의 차이는 미묘한 문법과 오퍼랜드의 위치차이 정도 일뿐 기본적인 명령어 자체는 동일합니다.
(당연한것이 기계어 이므로 매핑되는 기계어가 같기 때문이지요. )
건투를 빕니다~!
---------------------------------------------------------------
Opensource에 기여하는 것이 꿈입니다.
내가 만든 코드를 모두가 사용할 때 까지~
답변 감사합니다.
열심히 참고하여 공부하겠습니다. ㅎㅎ
저는 이렇게 생각했습니다.
push eax와 pop eax는
push eax와 pop eax는 필요없고요
dword ptr ss:[ebp+0x8]은 f로 축약해도 컴파일돼요
add eax, 1는 inc eax로
add eax, 1는 inc eax로 바꿔도 돼요
답변 감사합니다.
dword ptr ss:[ebp+0x8]을 그냥 f로 사용할 수도 있군요. 참고하겠습니다.
위 댓글도 님이 작성하셨을 것 같아 하나에 답니다.
저는 이렇게 생각했습니다.
뱀꼬리를 달아봤어요
// int s = 0;
sub esp, 4 ; 난 에스야, esp 어린인집에 다니는 4살 어린이야
mov dword ptr ss:[esp-0x4], 0 ; 동네 형들이 가끔 날 방구쟁이라고 놀려
// while (f <= l)
loop_check:
mov eax, dword ptr ss:[ebp+0x8] ; 난 에스 형 에프야, ebp 초등학교 8학년이야
cmp eax, dword ptr ss:[esp+0xc] ; 난 동네 쌈장 엘이야, ebp 초등학교 12학년이야, 에프, 나랑 키재기하자
jg loop_end ; 나보다 크면 저쪽 샛길로 가도 좋아. 하지만 작으면...
// s += f++;
mov eax, dword ptr ss:[esp-0x4] ; 에스 키를 재와서
add eax, dword ptr ss:[esp+0x8] ; 에프 키에 더하고
mov dword ptr ss:[esp-0x4], eax ; 에프 키는 동생 에스가 잠시 기억해둬 (내가 머리가 좀 나빠서...)
mov eax, dword ptr ss:[esp+0x8] ; 에프 키에 동생 키를 하나씩 더할게
add eax, 1 ; 하나,...(에스, 잘 기억하고 있지 ?)
mov dword ptr ss:[esp+0x8], eax ; 다 더해지면 그걸 에프 키로 해줄게
jmp loop_check ; 왜 싫어 ? 싫으면 말고...
loop_end:
// return s;
mov eax, dword ptr ss:[esp-0x4] ; 동생 에스는 뭘 기억하라했지 ?
pop eax ; 잘 떠올려봐
자답입니다.
위 코드에 대한 것은 아니지만, 어셈블리를 처음 시작할 때 도움이 될 수 있을 것 같습니다.
http://blog.naver.com/rbfwmqwntm/30165613835
솔직히.. 답변 달아주셨는데 죄송하게도 위 익명 분의 설명은 잘 이해가 되지 않았습니다.
저는 이렇게 생각했습니다.
댓글 달기