programing

C 프로그래머의 관점에서 ARM 아키텍처 간의 차이?

powerit 2023. 11. 4. 13:22
반응형

C 프로그래머의 관점에서 ARM 아키텍처 간의 차이?

저는 ARM을 위한 프로그래밍을 꽤 처음 해 봅니다.ARMv4, ARMv5, ARMv6 등과 같은 여러 아키텍처가 있다는 것을 알게 되었습니다.이것들의 차이점은 무엇입니까?그들은 다른 지시사항이나 행동을 가지고 있습니까?

가장 중요한 것은 제가 ARMv6용 C 코드를 컴파일하면 ARMv5에서 실행이 되나요?ARMv6에서 실행되는 ARMv5 코드는 어떻습니까? 아니면 커널 어셈블리 코드를 작성하는 경우에만 차이를 걱정해야 합니까?

ARM 세계가 좀 지저분합니다.

C 프로그래머들에게 있어 모든 ARM 아키텍처는 플랫 어드레싱 프로그래밍 모델과 함께 일반 32비트를 제공합니다.C 소스 코드를 사용하는 한 엔디안성과 성능에 대한 차이만 보일 수 있습니다.대부분의 ARM 프로세서(심지어 오래된 모델)는 빅 엔디안과 리틀 엔디안을 모두 사용할 수 있습니다. 선택은 로직 보드와 운영 체제에 의해 이루어집니다.Good C 코드는 엔디안 뉴트럴(endian neutral): 플랫폼 엔디안 뉴트럴(endian neutrality)에 관계없이 정확하게 컴파일되고 작동합니다(엔디안 뉴트럴은 신뢰성과 유지보수성뿐만 아니라 성능에도 좋습니다: non-neutral 코드는 서로 다른 크기의 포인터를 통해 동일한 데이터에 접근하는 코드입니다.그리고 이것은 컴파일러가 코드를 최적화하기 위해 사용하는 엄격한 앨리어싱 규칙을 파괴합니다).

이진 호환성(즉, 한 번 컴파일된 코드 재사용)을 고려하면 상황은 상당히 다릅니다.


  • 여러 명령어 집합이 있습니다.
    1. 26비트 프로그램 카운터가 있는 원래의 ARM 명령어 세트(매우 오래된, 요즘에는 접할 가능성이 거의 없음)
    2. 32비트 프로그램 카운터가 있는 ARM 명령어 세트(흔히 "ARM 코드"라고 함)
    3. Thumb 명령어 세트(16비트 단순화 opcode)
    4. Thumb-2 명령 세트(확장 기능이 있는 Thumb)

주어진 프로세서는 여러 개의 명령어 세트를 구현할 수 있습니다.ARM 코드만 아는 최신 프로세서는 ARMv4 대표 제품인 StrongARM으로 이미 상당히 오래된 제품(15년)입니다.ARM7TDMI(ARMv4T 아키텍처)는 Cortex-M을 제외한 거의 모든 후속 ARM 시스템과 마찬가지로 ARM과 Thumb을 모두 알고 있습니다.ARM과 썸 코드는 규약이 바뀌는 곳에 적절한 접착제를 삽입하는 한 동일한 응용 프로그램 내에서 함께 혼합될 수 있습니다. 이를 썸 연동이라고 하며 C 컴파일러가 자동으로 처리할 수 있습니다.

Cortex-M0는 Thumb 명령만 알고 있습니다."정상적인" ARM 프로세서에서 운영 체제는 (인터럽트를 처리하기 위해) ARM 코드를 사용해야 하기 때문에, Cortex-M0는 OS에 대한 몇 가지 사항을 알고 있습니다.이는 응용프로그램 코드에 상관없습니다.

다른 Cortex-M은 Thumb-2만 알고 있습니다.Thumb-2는 적어도 조립 수준 이상으로 대부분 이전 버전과 호환됩니다.


  • 일부 아키텍처는 추가적인 명령을 추가합니다.

따라서, 만약 이것이 ARMv6를 위한 것임을 알려주는 컴파일러 스위치와 함께 일부 코드가 컴파일된다면, 컴파일러는 ARMv6에는 있지만 ARMv5에는 없는 몇 안 되는 명령어 중 하나를 사용할 수 있습니다.이것은 거의 모든 플랫폼에서 직면하는 일반적인 상황입니다. 예를 들어 PC에서 C 코드를 컴파일할 경우, GCC를 사용하여-march=core2플래그를 지정하면 결과적인 바이너리가 이전의 펜티엄 프로세서에서 실행되지 않을 수 있습니다.


  • 몇 가지 통화 규칙이 있습니다.

호출 규약은 함수가 매개변수와 반환 값을 교환하는 방법을 지정하는 규칙 집합입니다.프로세서는 레지스터만 알고 스택에 대한 개념은 없습니다.호출 규약은 어떤 레지스터 파라미터가 이동하는지, 그리고 그것들이 어떻게 인코딩되는지를 알려줍니다(예를 들어, 가 있는 경우).char매개 변수, 레지스터의 하위 8비트에 들어가지만 호출자가 상위 24비트를 삭제/서명해야 합니까, 아니면 그렇지 않습니까?)적층 구조 및 정렬에 대해 설명합니다.구조물 필드에 대한 정렬 조건 및 패딩을 정규화합니다.

ARM에는 ATPCS(구)와 AAPCS(신)라는 두 가지 주요 협약이 있습니다.부동 소수점 값의 주제에 대해서는 상당히 다릅니다.정수 매개변수의 경우 대부분 동일하지만 AAPCS는 더 엄격한 스택 정렬이 필요합니다.물론 명령어 세트와 썸 연동 여부에 따라 규칙이 달라집니다.

경우에 따라서는 ATPCS와 AAPCS 모두를 준수하는 일부 바이너리 코드를 가질 수 있지만 이는 신뢰할 수 없으며 불일치에 대한 경고도 없습니다.결론은 서로 다른 호출 규약을 사용하는 시스템 간에 진정한 이진 호환성을 가질 수 없다는 것입니다.


  • 보조 프로세서(옵션)가 있습니다.

ARM 아키텍처는 핵심 명령어 세트에 자체적인 명령어를 추가하는 옵션 요소로 확장할 수 있습니다.FPU는 그러한 선택적인 보조 프로세서입니다(실제로는 매우 드물게 볼 수 있습니다).또 다른 보조 프로세서는 NEON으로, 일부 최신 ARM 프로세서에서 볼 수 있는 SIMD 명령어 세트입니다.

보조 프로세서를 사용하는 코드는 운영 체제가 해당 opcode를 트랩하고 보조 프로세서를 소프트웨어로 에뮬레이트하지 않는 한 해당 보조 프로세서를 포함하지 않는 프로세서에서 실행되지 않습니다(이것은 ATPCS 호출 규약을 사용할 때 부동 소수점 인수에서 일어나는 일이며 속도가 느림).


정리하자면, C 코드가 있다면 다시 컴파일 해보세요.다른 아키텍처나 시스템용으로 컴파일된 코드를 재사용하려고 하지 마십시오.

윈텔 컴퓨터 대 인텔 맥 같은 ARM 대 ARM을 생각해 보세요.두 컴퓨터에 동일한 인텔 칩(패밀리)이 있더라도 C 코드의 일부가 한 번 컴파일되어 두 프로세서 모두에서 정상적으로 실행될 수 있다고 가정합니다.사용자의 프로그램이 어디에서 왜 달라지는지는 인텔 프로세서와는 아무런 관계가 없지만, 인텔 프로세서 주변의 칩과 마더보드, 그리고 이 경우에는 운영 체제와 모든 관계가 있습니다.

ARM 대 ARM의 경우 대부분의 차이점은 코어가 아니라 코어를 둘러싸고 있는 벤더 고유의 논리입니다. 따라서 로드된 질문입니다. C 코드가 표준 API 호출을 호출하는 일부 애플리케이션이라면 암 또는 인텔 또는 powerpc 등에서 컴파일해야 합니다.애플리케이션이 온 칩이나 온보드 주변기기와 대화를 시작하게 되면 프로세서 유형이 무엇이든 간에 하나의 보드, 하나의 칩이 달라지므로 결과적으로 해당 칩이나 마더보드에 대해 C 코드를 작성해야 합니다.ARMv6용 이진 파일을 컴파일하면 ARMv4에서 정의되지 않은 것으로 간주되는 명령이 있을 수 있으며, 예외가 발생합니다.ARMv4용으로 컴파일하면 ARMv6가 잘 실행됩니다.

기껏해야 이 애플리케이션 공간에 있다면 성능 차이만 보일 수 있습니다.그 중 몇 가지는 컴파일러 옵션에서 선택하는 것과 관련이 있습니다.그리고 때로는 코드를 도와줄 수도 있습니다.저는 가능한 한 분할과 부동 소수점을 피하는 것을 추천합니다.나는 곱셈을 좋아하지 않지만, 밀어내면 나눗셈 대신 곱셈을 할 것입니다.x86은 정렬되지 않은 액세스로 인해 손상되었습니다. 지금 정렬된 I/O로 시작하면 정렬된 액세스를 선호하는 다른 칩으로 이동하는 것을 방지할 수 있고, 다양한 운영 체제와 부트로더가 ARM을 반응하도록 구성하는 것을 방지할 수 있습니다. x86에서 익숙했던 것은 그 어느 것도 아닙니다.마찬가지로 이 습관을 유지하면 x86 코드가 훨씬 더 빨리 실행됩니다.

ARM ARM 사본을 받으세요(구글: ARM Architectural Reference Manual, 여러 곳에서 무료로 다운로드할 수 있습니다. 현재 리비전이 무엇인지 모르겠습니다. revI나 다른 것이 있을지도 모릅니다.).ARM 명령어 세트를 찾아보면 대부분의 명령어가 모든 코어에서 지원되며, 일부 명령어는 분할 및 바이트 스왑 등 시간이 지남에 따라 추가되었습니다.중심부 사이에는 아무것도 두려워할 것이 없다는 것을 알게 될 것입니다.

시스템의 관점에서 생각해 보세요. 윈텔 대 인텔 맥.ARM은 칩을 만드는 것이 아니라 코어를 만들고 라이센스를 부여합니다.칩에 ARM을 사용하는 대부분의 공급업체들은 그들만의 특별한 소스를 가지고 있습니다.따라서 같은 프로세서가 중간에 있는 윈텔 대 맥과 같지만 프로세서가 만지고 사용해야 하는 모든 것에 있어서는 완전히 다릅니다.ARM 코어로 멈추지 않고, ARM은 주변기기, 부동 소수점 유닛, 캐시 등을 판매합니다.예를 들어 ARMv4가 동일한 경우에는 거의 없습니다.코드가 차이에 닿으면 그렇지 않으면 문제가 발생합니다.

ARM ARM 외에 칩의 암 부분에 대해서도 TRM(Technical Reference Manuals)이 있습니다.하지만 사용중인 부품에 대해 잘못된 TRM을 갖게 되면 두통을 유발할 수 있습니다.TRM에는 ARM ARM에 없는 레지스터 설명 등이 있을 수 있지만, 애플리케이션 공간에 거주하는 경우에는 ARM ARM이나 ARM이 필요하지 않을 가능성이 높습니다.ARM ARM은 교육적인 목적으로 사용할 수 있습니다.정렬되지 않은 액세스를 분할하거나 사용하지 않을 수 있는 이유 이해.

사용자 코드를 고수한다면 ARM 자체는 상당히 호환됩니다(물론 커널 코드는 다릅니다).호스트 OS 환경에서는 ARMv5(ARM926 프로세서)를 사용할 가능성이 높습니다.

큰 차이는 다음과 같습니다.

  1. 캐시 동작은 크게 다릅니다.일부 ARM에 대한 캐시는 가상으로 처리되기도 하므로 프로세스 전환이 어려워질 수 있습니다.
  2. FPU는 여러 가지 맛(VFP, NEON 등)이 있습니다.많은 소규모 프로세서에는 FPU조차 없습니다.
  3. 엄지손가락 모드가 확 바뀌었습니다.ARMv5 간의 썸 모드는 썸2(ARMv6+)로 휴대할 수 없거나 역호환이 가능하지 않습니다.

만약 그 차이가 정말로 당신에게 중요하다면, 당신은 ARM의 공개 문서에서 그것을 알아낼 수 있을 것입니다.

하지만 (C만큼 "높은" 정도만이라도) 상위 언어로 쓰는 것의 핵심은 그것에 대해 걱정하지 않는 것입니다.당신이 하는 일은 재컴파일 뿐입니다.커널 내에서도 어셈블리에 쓸 필요는 별로 없습니다. 어셈블리에 쓸 필요가 없는 경우(예: 최대 성능을 얻기 위해서가 아니라), 일반적으로 CPU의 선택권 이상(예: 메모리 매핑된 위치에 직접적으로 저장된 것)에 기인합니다.

일반적으로 아키텍처 간에 포팅할 때 확인해야 할 영역의 매우 빠르고 더러운 목록:

  • Endianness: 조합 사용, 데이터 유형 캐스팅, 비트 필드, 데이터 공유
  • 정렬: 정렬 요구사항 뿐만 아니라 가능한 비 정렬 액세스의 성능 특성
  • 기억 모델: 약한 것 vs 강한 것?
  • 멀티 코어: 코히런시는 어떻게 작동합니까?
  • 기타: 서명된 데이터 형식 vs 서명되지 않은 데이터 형식, 데이터 구조 패킹, 스택 사용량, 열거 데이터 형식...

언급URL : https://stackoverflow.com/questions/4381102/differences-between-arm-architectures-from-a-c-programmers-perspective

반응형