2015-01-18 3 views
0

제발, 설명해주세요. 내가 아는 한 모든 CPU에는 다른 프로그래밍 모델이 있습니다. XYZ 어셈블리 명령어를 수행 할 수있는 CPU가 있다고 가정 해 봅시다. 그런 다음 프로그램을 컴파일하고 XYZ 어셈블리 지침이없는 CPU가있는 제 친구에게 보냅니다. 이 사실에도 불구하고 나는 프로그램이 효과가있을 것이라고 생각한다. 일단 컴파일 된 프로그램은 일반적으로 하드웨어 아키텍처와 독립적입니다.모델 프로그래밍 변경. 어떻게 작동합니까?

+1

명령을 구현하지 않는 CPU에서 어떻게'XYZ'가 작동 할 것으로 예상합니까? – wallyk

+1

매우 일반적인 x86 명령어 세트를 사용합니다 (분명히 일부 추가 사항과 함께 확장되었지만 일부 공통적 인 것도 포함). AMD 프로세서에서 컴파일 한 프로그램 (이전 버전)을 Intel 프로세서 (같은 기간)로 옮기십시오. 컴파일러가 최적화 과정에서 AMD 특정 명령어를 사용했기 때문에 마지막으로 시도해 보았습니다. – lared

+2

작동하지 않습니다. 학교에서 배운 내용에도 불구하고 아무도 실제로 집회에서 프로그램을 작성하지 않습니다. 최소한 C를 사용하고 특정 플랫폼에 적합한 기계 코드를 생성하는 컴파일러를 사용하십시오. –

답변

3

물론 이진 파일은 컴파일 된 아키텍처의 컴퓨터에서만 실행될 수 있습니다. 예를 들어 x86에서 ARM 실행 파일을 실행할 수 없습니다. 대부분의 경우 프로그램 로더는 사용자가 시도하도록 허용하지 않습니다.

프로세서가 지원해야하는 기본 명령어 세트가 있기 때문에 x86-64와 같은 특정 아키텍처 용 소프트웨어의 바이너리 버전을 성공적으로 배포 할 수 있습니다. 인텔 CPU와 버디의 AMD CPU는 여전히 동일한 기본 명령 세트를 구현합니다. 기본적으로 GCC는이 범주에 해당하는 지침 만 표시합니다.

또한 GCC는 특정 명령어 세트 에 속하는보다 특수화 된 명령어를 방출 할 수 있습니다. 예를 들어, 벡터 수학을 수행하는 SSE 확장의 다양한 반복이 있습니다. 모든 CPU가 이러한 명령어를 구현하지는 않기 때문에 GCC에 사용하도록 허용해야한다는 사실을 명시 적으로 GCC에 알려야합니다. GCC의 -march-mtune 플래그를 사용하면이 작업을 수행 할 수 있습니다. -march=native은 컴퓨터에서 잘 작동하도록 프로그램을 컴파일하지만 다른 CPU가있는 다른 컴퓨터에서 동일한 이진 파일을 실행하려고하면 작동하지 않을 수 있습니다.

코드가 컴파일되면이 전략이 잘 작동하지만 하이브리드 방식을 구현할 수 있습니다. 여기에는 CPUID 명령어를 사용하여 현재 CPU에서 사용할 수있는 기능을 (런타임에) 결정합니다. 그런 다음이 정보를 기반으로 다른 명령어 세트 확장을 사용하는 다른 함수를 호출 할 수 있습니다. 이들은 일반적으로 어셈블리에서 수동으로 코딩되거나 문제의 아키텍처에 대해 built-ins을 사용하여 C로 코딩됩니다.

리눅스 커널은 런타임에 실제로이 작업을 수행하지만 종종 더 인상적입니다. x86에서 몇 예 :

  • SMP에서 시스템은 x86 LOCK 접두사 특정 지침에 요구되는 동시에 같은 변수를 수정하는 여러 개의 CPU를 방지합니다. 그러나 유니 프로세서 (UP) 시스템에서이 명령은 불필요하며 작업 속도가 느려집니다. SMP 용으로 컴파일 된 커널이 UP 시스템에서 실행 중임을 확인하면 실제로 NOP - LOCK 명령이 실행되어 쓸모 없게됩니다. 즉, 위에 "no-op"명령을 씁니다.

  • 스트링 명령어는 메모리 영역에서 작동하기 위해 접두어 REP을 지정할 수 있습니다. 예를 들어 REP STOSBmemset을 구현하는 데 사용할 수 있으며 은 memcpy 등으로 사용할 수 있습니다. 수년 동안 다양한 인텔 프로세서가 이러한 지침을 내부적으로 다르게 구현했습니다. 이 때문에 Linux 커널은 실행중인 CPU가 "양호한"구현인지 여부를 결정합니다 (다시 CPUID을 기반으로 함). 양호한 경우 REP ... 지침을 사용합니다. 그렇지 않은 경우, 대체 루틴이 사용됩니다.

  • paravirtualization으로 컴파일 된 커널은 권한있는 지침을 위해이 작업을 수행합니다.베어 메탈에서 실행되는 커널은 LGDT 명령어를 실행할 수 있으며 Xen에서 실행되는 커널은 하이퍼 바이저에 hypercall을 수행해야합니다.

  • 이러한 모든 기능은 flags : 행을 통해 /proc/cpuinfo에 노출됩니다. 리스트는 요즘 꽤 길다.