2009-06-11 10 views
9

최근 어셈블리 수준에서 프로그램을 디버깅해야했습니다. 나는 많은 어셈블리어 경험이 없으므로 다른 민족 코드를 디버깅하기 전에 언어에 대한 느낌을 얻기 위해 간단한 C 프로그램을 작성하고 단일 단계로 진행할 것이라고 생각했습니다. 그러나, 나는 정말 (-ggdb -O0로 컴파일) 무엇을이 두 라인으로 만들어진 GCC하지 않습니다이 어셈블리는 어떻게 작동합니까?

MAX_SIZE 5로 #define에 의해 정의되고 난 0x8이에 저장되어있는 지역 변수 (이다
items[tail] = i; 
tail = (tail+1) % MAX_SIZE; 

(% ebp), 나는 짐작한다. GDB에 따르면,이된다 : 0x804963c 항목의 주소가

0x08048394 <queue+17>: mov 0x8049634,%edx 
0x0804839a <queue+23>: mov 0x8(%ebp),%eax 
0x0804839d <queue+26>: mov %eax,0x804963c(,%edx,4) 
0x080483a4 <queue+33>: mov 0x8049634,%eax 
0x080483a9 <queue+38>: lea 0x1(%eax),%ecx 
0x080483ac <queue+41>: movl $0x66666667,-0xc(%ebp) 
0x080483b3 <queue+48>: mov -0xc(%ebp),%eax 
0x080483b6 <queue+51>: imul %ecx 
0x080483b8 <queue+53>: sar %edx 
0x080483ba <queue+55>: mov %ecx,%eax 
0x080483bc <queue+57>: sar $0x1f,%eax 
0x080483bf <queue+60>: mov %edx,%ebx 
0x080483c1 <queue+62>: sub %eax,%ebx 
0x080483c3 <queue+64>: mov %ebx,-0x8(%ebp) 
0x080483c6 <queue+67>: mov -0x8(%ebp),%eax 
0x080483c9 <queue+70>: shl $0x2,%eax 
0x080483cc <queue+73>: add -0x8(%ebp),%eax 
0x080483cf <queue+76>: mov %ecx,%edx 
0x080483d1 <queue+78>: sub %eax,%edx 
0x080483d3 <queue+80>: mov %edx,-0x8(%ebp) 
0x080483d6 <queue+83>: mov -0x8(%ebp),%ebx 
0x080483d9 <queue+86>: mov %ebx,0x804963 

때문에, 난 코드 C의 첫 번째 줄의 작동 방식을 알 수있다. 또한, 0x8049634 꼬리의 주소입니다 그래서 큐 + 33 및 큐 + 38 % ecx = tail + 1 같음 같아요 ...하지만 난 후에 무슨 일이 일어나고 있는지 전혀 몰라. 누가 간단한 모듈로 이것을 복잡하게 만들 수 있다고 생각했을까요?

답변

14

더 비싼 분할 명령을 수행하지 않아도되는 방법입니다. 내가 처음 만났을 때 나는 또한 아주 곤란했다. 재미있는 점은이 트릭에 사용 된 마법 번호 (이 경우 0x66666667)를 검색하면이 트릭을 설명하는 결과가 나오는 경우가 많다는 것입니다. (나는 소스가 없기 때문에 내가해야만하는 유일한 구체적인 일이라고 믿는다.)

빠른 검색은 내게이 블로그 포스트를 주었다 : http://blog.dkbza.org/2007/09/reverse-engineering-compiler-produced.html 아래쪽에 유용한 링크가있다. 이 간계에 종이에 간접적 인 연결을 포함하여).

관련 문제