2012-02-09 2 views
0

asm을 많이 다루고 GDB에서 레지스터와 메모리를 살펴 보는 C 책을 읽었습니다. 정확히 동일한 소스를 컴파일 및 디스 어셈블 할 때 (실제로 책 CD와 함께 제공된 소스 파일을 사용하여) 어셈블리의 지시 사항이 책의 내용과 약간 다릅니다. 이 책은 intel flavored 어셈블리를 사용하고 gdb에 "set disassembly intel"을 넣으므로 그렇게하지 않습니다. 지시 사항의 순서가 다르며 일부는 모두 다르고 다른 몇 가지 단점이 있습니다.gdb의 이상한 결과

예컨대

이 책에 MOV 상기 EIP 레지스터의 지시가 : for 루프에서, 변수 I를 0으로 초기화 대응

(gdb) x/i $eip 
mov DWORD PTR[ebp-4], 0x0 

(I = 0, i가 < 10 난 ++

(gdb) x/i $eip 
mov DWORD PTR[esp+0x1c], 0x0 

통지는 다른 레지스를 참조 할 것 :이 참조) 실행)

그러나, 같은 장소에서 중단 점 내 GDB 콘솔에서 (주 휴식 설정 ter 모두 함께 - ebp 대신 esp esp의 값을 확인하면 0x1c 자체입니다. 하지만 0x1c 또는 esp + 0x1c에있는 항목을 검사하려고하면 그 주소를 볼 수 없다고 알려줍니다.

그래서 책이 계속 진행됨에 따라 나는 따라갈 수 없습니다. ebp, ebp-4 등의 흔적을 따라 가며 ebp 레지스터에서 아무 것도 일어나지 않는 것 같습니다.

이 책은 2008 년에 작성되었으므로 gcc 또는 gdb의 버전 변경으로 인해 변경 사항이 상당 부분 도입 될 것이라고 상상해보십시오 (또는 그랬습니까?) ... 일부 컴파일러 최적화 또는 기본적으로 다른 결과를 생성하는 스위치가있을 수 있습니다 ?

미리 감사드립니다.

편집 : Strange. 나는 각각의 제안을 시도했지만 아무 것도 효과가 없었다. 그런 다음 나는 rm a.out을했고 새로 컴파일되었고 이제는 잘 작동한다. (지침은 여전히 ​​책과 다르지만 책의 주소와 일치하는 주소를 조사 할 수있다. 내가 상응하는 패턴을 따라갈 수 있다면, 정확히 똑같은 크기 일 필요는 없습니다. 너무 간단 할 것입니다!) 여러분의 도움과 제안에 다시 한번 감사드립니다.

답변

0

이것은 모두 매우 구체적인 플랫폼 및 컴파일러가 될 것입니다. 네가 할 수있는 일이 많지 않을까 걱정된다.

+0

감사합니다. 이 책은 32 비트 인텔을 사용하고 있습니다. 둘 다 gcc로 컴파일하고 (버전을 확인하고 qeustion을 업데이트해야합니다), 리눅스를 실행해야합니다. 이 책은 우분투 (다시 버전을 확인해야합니다)를 기반으로하고 최신 아치 설치를 실행하고 있습니다. 동일한 아키텍처와 동일한 컴파일러 (gcc)를 사용한다고 가정한다면 동일한 기계 코드가 필요합니까? 어느 쪽이든, 나는 그 값이 내가 조사 할 수없는 주소로 초기화되고 이상하게도 $ esp 즉 스택 포인터에 의해 참조되고 있다는 것을 알게된다. – speakingcode

+1

아니야, 같은 이유가 될 이유가 없다. . '-O0' 또는'-march = i386'으로 재생할 수 있습니다. 그러나 그것이 완전히 다른 것은 놀라운 일이 아닙니다. –

1

이 문제를 일으킬 수있는 일은 백만 가지가 있습니다. 다른 아키텍쳐에서 코드를 컴파일했다면,이 점을 기대할 수 있습니다. (물론, 32 비트 대 64 비트를 의미하지도 않습니다. 문자 그대로 다른 CPU 아키텍처가 실행 순서를 변경할 수 있습니다) . 최적화로 프로그램을 컴파일하면 CPU 파이프 라인을 최대한 활용하도록 실행 순서가 변경됩니다. 이것은 어떤 NOOP 명령어를 추가하거나 완전히 다시 주문하는 것을 의미 할 수도 있습니다 (당연히). 더군다나 일부 CPU는 여러 가지 방법으로 수행 할 수 있습니다. 일반적으로 다른 방법보다 빠른 한 가지 방법이 있습니다 (인텔 LOOP 명령어가 마음에 듭니다. 현대 컴파일러는이 명령어를 페스트 때문에 피해야합니다). 하나의 레지스터가 다른 레지스터보다 효율적이면이를 사용합니다.

이야기의 도덕 : 학습 목적으로 작성자와 독자는 모두 최적화를 비활성화해야합니다. 추가 보너스 포인트 : 동일한 버전의 gcc와 동일한 플랫폼을 사용하십시오.

+0

통찰력에 감사드립니다. 어떻게 내가 궁금해 하던지, 어떻게 최적화를하지 않을 수 있습니까? 나는 정확한 메모리 주소와 명령어조차 아키텍처마다 다를 수 있다는 것을 이해한다. 그것은 컴파일러의 요점이지만, 나는 이것이 매우 다르다는 것에 놀랐다. 심지어 asm이 완전히 다른 프로그램 인 것처럼 보인다. 그저 main에있는 for 루프 만 따라야합니다.) 실제로 문제는 주소가 초기화되지 않았 음을 말하는 것입니다 (esp + 0x1c). 그렇지 않아야합니다. – speakingcode

+0

@rootlicker 'gcc -O0' (문자 O 다음에 숫자 0이옵니다) –

1

컴파일 된 코드가 -fomit-frame-pointers으로 컴파일 된 것처럼 보입니다.이 코드는 GCC-4.6에서 기본값이되었습니다.

명시적인 -fno-omit-frame-pointer으로 건물을 시험해보십시오. 나는 그 결과가 그 책에 훨씬 가까워 질 것으로 기대한다.