2011-02-18 8 views
2

나는 임베디드 프로세서 (ARM)에서 실행되는 알고리즘의 두 가지 C 구현을 작성했습니다. 나는 코드 크기의 측면에서이 두 가지 구현을 비교하는 공정한 방법을 원하는, 그래서 실행 파일을 다운로드 할 때 나는 다음 그림 얻을 :코드 크기의 공정한 비교

Implementation One 

.text size 55098 bytes 
.data size 2048 bytes 

Implementation Two 

.text size 54598 bytes 
.data size 2048 bytes 

찾아야하는 것은 .text 세그먼트의 차이는 500 바이트이지만, 상대적를 용어는 많지 않습니다. 문제는이 수치가 독립 실행 형 모드, 즉 임베디드 프로세서의 운영 체제가없는 독립 실행 형 모드에서 호출 할 수 있도록 실행 파일을 감싸는 부트 코드도 포함한다는 것입니다.

누군가가 부풀린 추가 코드없이 실행 파일의 실제 코드 크기를 얻는 방법에 대한 아이디어가 있는지 궁금합니다.

많은 감사 앤드류

+0

자신의 전용 메모리 세그먼트에 부트 로더를 배치 네,이 문제를 해결해야합니까? 왜 그렇게하지 않는거야? – Lundin

답변

0

당신은 extra code의 일부 무엇을 정의해야한다. 이 추가 코드를 다른 컴파일 유닛에 작성했기를 바랍니다. 툴 체인에는 해당 컴파일 단위의 코드 크기를 탐지하는 도구가 있어야합니다.

가장 중요한 점은 코드 크기와 사용 가능한 메모리를 비교해야한다는 것입니다. 특정 메모리 영역에 코드를 맞출 필요가 없다면 코드 크기를 줄일 가치가 없습니다.

8
  1. C 컴파일러는 일반적으로 검사 할 수있는 어셈블리 소스 코드를 생성 할 수 있습니다.
  2. 또 다른 가능성은 링커에서지도 파일을 보는 것입니다. 개별 기능의 크기를 제공해야합니다.
  3. 디버거로 이진 코드를 볼 수 있습니다.

asm 출력 또는 맵 파일을 얻으려면 컴파일러 및/또는 링커에 적절한 옵션을 지정해야합니다. 이러한 옵션은 사용하는 툴 체인 (컴파일러, 링커)에 따라 다릅니다.

는 GCC에서 ASM 출력을 얻으려면 : 의 gcc -S -o hello_asm.s에서는 hello.c

2

분에 (표시됩니다 거의 확실히 MAP 파일을 생성 할 수 있습니다 (이미 그렇게 될 수 있습니다) 귀하의 링커 세부 사항) 모든 개별 데이터 및 코드 객체의 메모리 사용 세부 사항을 확실히 객체 모듈 수준까지, 일반적으로 개별 기능 및 데이터 객체 수준까지 낮추십시오.

1

결국 모든 코드가 다운로드되고 부트 로더 및 OS가 포함됩니다. 그런데 왜 당신은 그 측정에서 그들을 제외시키고 싶습니까?

코드를 가능한 한 간단하게 응용 프로그램과 컴파일하도록 제외하려는 간단한 코드를 알고 싶습니다 (예 : main(){}). 그런 다음 얻은 값을 다음 측정 값에서 뺄 수 있습니다.

+2

동의 - "왜 측정에서 제외하고 싶습니까?"는 반드시 수사적 질문이 아닙니다. 몇 가지 이유가있을 수 있습니다 (또는 왜 잘못 생각할 수도 있습니다!). 귀하의 질문에 대한 정답은 그것이 어떤 이유인지에 달려 있습니다. –

+1

대부분의 경우 완성 된 시스템은 많은 다른 작업을 수행해야하지만이 실험은 문제의 한 부분에 대한 두 가지 접근 방식의 코드 크기를 알아내는 것입니다. –

0

가능한 한 가지 방법은 빌드 도구로지도를 더 자세히 세밀하게 덤프하는 것입니다.

예를 들어 gnu 도구 세트를 사용하는 경우 .elf 파일에서 size 실행을 사용하고 그 안에있는 오브젝트 파일을 기반으로 분석을 수행 할 수 있습니다.

.elf 파일에 objdump을 사용하여 세부 맵을 얻을 수도 있습니다.

예제의 부트 코드가 두 개의 전체 구현 사이에서 일정하다고 가정하면이 도구를 사용하면 코드 공간 효율성이 더 우수한 코드를 더 잘 파악할 수 있습니다.

0

GNU 도구를 사용하는 경우 size 도구를 사용할 수 있습니다. 그것은 모든 객체 파일에 의해 각 섹션에서 사용 된 메모리 양을 알려줍니다. 귀하의 경우에는 측정하려는 코드가 자체 파일에 있는지 확인해야합니다.

text data  bss  dec  hex filename 
9767  4 5184 14955 3a6b cfi_flash.o 
1138  0  192 1330  532 cfi_mtd.o 
556  0  128  684  2ac mtdcore.o 
3897  0  8 3905  f41 mtdpart.o 
0

때때로 일부 구현 라이브러리 루틴을 필요로하기 때문에, 고립 구현의 크기를 파악하기 어려울 수 있습니다 다른 사람이 없다는 점에서 연결되는 :

다음은 출력의 예입니다. 루틴 # 1이 # 2보다 300 바이트 작지만 500 바이트 라이브러리 루틴 foo()가 필요하고 루틴 # 3이 # 4보다 300 바이트 작지만 동일한 루틴이 필요하면 격리 된 # 1이 효과적 일 것입니다 # 2보다 큰 200 (즉, 500-300) 바이트이고 # 3은 # 4보다 200 바이트 더 크지 만 # 1 + # 3은 # 2 + # 4보다 100 바이트 작을 것입니다 (라이브러리 루틴은 한 번만 필요함).

이러한 종류의 상황은 일부 라이브러리 루틴 대신 기능이 저하 된 (그리고 비용 절감 된) 대안을 생성하는 경우 자주 발생할 수 있습니다. 값 비싼 라이브러리 루틴의 필요성을 피할 수 있다면 더 간단한 버전을 작성하고 사용하는 것이 좋습니다. 반대로 비싼 루틴을 사용하여 코드가 끝나면 단순한 버전이 불필요하게됩니다.

0

아무 것도하지 않는 스텁 함수 만있는 "Implementation Null"을 작성할 수 있습니다. 그러면 비교할 때 사용할 기준 값을 얻을 수 있습니다.

(구현 하나의 크기 - 구현 널의 크기) 대 (실행 두의 크기 - 구현 널의 크기)