2012-11-09 3 views
0

프로젝트에서 나는 매직 넘버를 사용하고 있습니다. 나는 그것이 55 AA를 말한다 AA55 말을해야 결과 파일을 Hexdump에서는 때 이 매크로는, 그러나 하나의GCC#define 문 바이트가 잘못되었습니다.

#define BOOTSIGNATURE 0xAA55 

을 정의하는 데 사용됩니다.

GCC는 엔디안 니스를 혼합하고 있습니까? 이 프로젝트는 x86 프로세서 용입니다. AA 55는 그 특정한 순서대로되어 있어야합니다. 바이트를 교환 할 수는 있지만 GCC가 왜 이것을하는지 궁금합니다.

+0

x86이 리틀 엔디안이므로 GCC가 왜 이것이 원하는 동작이라고 생각하는지 알 수 있습니다. 그러나, 나를 위해, AA55 바이트의 문자열처럼, 그 특정 순서로 필요합니다. 필요한 행동을 어떻게 성취 할 수 있습니까? –

+0

단일 정수 대신 바이트의 문자열 (배열)로 정의 할 수 있습니다.나는 당신이 그것을 어떻게 사용하고 있는지 모르기 때문에 다른 수정 없이는 작동 할 지 모른다. '#define BOOTSIGNATURE ((char []) {0xAA, 0x55})'. 또한 아키텍처를 확인하고 순서를 전환하여 의견을 남겨 이유를 알 수 있습니다. – ughoavgfhw

+0

바이너리는 머신과 동일한 엔디안 방식으로 작성됩니다. 다시 읽어 들일 때 걱정할 필요가있는 경우 올바르게 읽습니다. – iabdalkader

답변

2

0xAA55int입니다. 따라서 컴퓨터의 엔디안 적용을받을 수 있습니다. 나는 char 배열로이를 저장하는 것입니다 :

const unsigned char BOOTSIGNATURE[] = {0xAA, 0x55}; 
+0

좋아요. 그래서 이것을 unsigned short int로 캐스팅한다면 구조체의 일부로 작동할까요? –

+1

예, 부호없는 short int로 변환 할 수 있습니다. 나머지 파일은 어떻게 다루고 있습니까? 리틀 엔디안인가? 어떤 경우이 비트는 빙산의 일각에 불과합니다. –

+0

아니, 문제 없습니다. 파일의 나머지 부분은 GCC 도메인에 있습니다 (GCC 스타일의 컴파일 된 C 코드로 작성하고 읽음). 부트 서명 (이름이 말하는대로;) BIOS에서 디스크 이미지의 처음 512 개가 유효한지 확인합니다 부팅하기. 이것이 바로 바이트 순서가 다른 곳이 아닌 그곳에서 중요한 이유입니다. 다른 섹터를 읽을 때 endianness 영향은 동일한 엔디안을 사용하여 읽혀 지므로 취소됩니다. 그러나 바이오스는 이러한 바이트가 특정 순서로 있어야합니다. –

2

처리기 매크로는 컴파일 된 오브젝트 파일에 표시되지 않습니다 - 그들은 전혀 컴파일러에 의해 볼 수없는 것입니다. 당신이 방금 #define을 가지고 있고 그것을 어디에서도 사용하지 않았다면 그것의 흔적은 없을 것입니다.

어딘가에서 코드에서 사용한 경우 명령 (예 : 레지스터 또는 메모리에 상수를로드)에서 상수로 표시 될 수 있습니다. 위를 컴파일하고 데이터 세그먼트를 보면

// Global variable definition 
#define BOOTSIGNATURE 0xAA55 
uint16_t my_global = BOOTSIGNATURE; 

, 그것은 다음과 같습니다 :

$ gcc -c test.c 
$ objdump -s test.o 
[...] 
Contents of section .data: 
0000 55aa0000        U... 
정적 데이터를 초기화하는 데 사용되는 경우, 데이터 세그먼트에서 상수로 표시 할

두 바이트는 리틀 엔디안 순서 55 AA으로 메모리에 저장됩니다 (선두 0000은 16 진수의 세그먼트 오프셋 임).

당신이 다음 명시 적으로 바이트 배열로 저장, 데이터의 엔디안을 제어하려면 :

uint8_t my_global[] = {0xAA, 0x55}; 

이 항상 지정된 순서에 바이트를 저장합니다.

+0

나는이 과정을 알고 있으며 분명히 어딘가에 사용했다. 이 바이트 배열을 short int로 변환 할 수 있습니까? –

-2

가장 간단한 해결책 : 16 진수 값의 정수 형식을 사용하면 해당 이진수가 동일한 마법 번호가됩니다! 이 경우 43605

+0

죄송합니다. 21930은 올바른 값이었습니다 –

+0

나는 그게 더 나아 졌는지 모르겠습니다. 그건 단지 0x55AA입니다. 여전히 동일한 엔디안 문제가 있습니다. –

+0

도 그 사실을 깨닫지 못했습니다. 그냥 값을 업데이 트하고 지금은 내 코드의 나머지 부분을 통해 아무것도 변경할 필요가 없습니다. –

0

이식 가능한 코드를 작성하려면 함수를 사용하여 주어진 바이트 순서를 강제 실행하십시오. 예를 들어 these functions을 사용하면 파일에서 필요한 순서에 따라 기본 호스트 바이트 순서의 16 비트 값을 빅 엔디안 또는 리틀 엔디안으로 변환 할 수 있습니다.

#define BOOTSIGNATURE 0xAA55 

struct bootheader { 
    uint16_t signature_be; 
} header; 

header.signature_be = htobe16(BOOTSIGNATURE); 

내가 아닌 호스트 바이트 순서 변수와 구성 요소에 _le_be 또는 접미어를 사용하는 것과 같이.

빅 엔디안이 필요하므로 htons()arpa/inet.h에서 사용할 수 있지만 그 방법에 대한 큰 팬은 아닙니다. 나는 그 이름이 htobe16처럼 명확하지 않다고 생각하지 않으며 리틀 엔디 언 바이트 순서로 /에서 변환하기위한 기능을 가지고 있지 않습니다.

관련 문제