ARM Thumb Mode 공부 미완성

2018. 6. 10. 07:540x03 Reversing Theory

728x90

부제 : "ARM에 2가지 모드가 있는 것을 기억해~ "


우선, ARM에서 사용되는 2가지 모드

1. ARM Mode

2. Thumb Mode 


ARM Mode는 32비트 RISC Machine이다.


Thumb라는 것은 흔히 알기로 '엄지 손가락'이며, 최고를 일컫는 제스처이다.


PC환경에서 최고를 좌우하는 것 중 하나는 메모리 사용의 효율성이다.


굳이, 이런 예시를 들어보는 이유는 이해하기 쉽게 하기 위해서 이다. ^.^


일단 간단하게 요약하자면, ARM의 Thumb모드는 메모리를 효율적으로 다룰 수 있다. 


이제부터 구체적으로 들어가 보겠다. 


지금은 ARM 프로세서에 대해 삽질 중입니다


1. ARM MODE : 32BIT Instruction Set Apply


2. Thumb MODE : 16BIT Instruction Set Apply


여담 : 프로세서 이름에 T가 들어간 제품만 Thumb를 지원한다.


질문 혹은 궁금증 : 어떻게 하나의 CPU에서 2가지의 Instruction을 지원할 수 있을까?


1. RISC머신과 CISC머신에 대해 알아야 한다.


- RISC 머신은 칩 설계에 있어 CISC 머신보다 간단하다.

- 간단하다는 것은 무언가 알게 모르게 부족한 부분이 있을 것인데, 그 부분은 컴파일러 최적화를

이용하여 개선한다. 

-> 컴파일러 최적화가 정확히 무엇인지 아직 가늠하지 못하였다.

- RISC는 복잡하지 않고 단순하기 때문에 CISC의 기능을 똑같이 구현하고자 할 때, 인스트럭션의 길이가 길어진다. 


2. ARM은 주로 어디에 사용되고 있는지 알아야 한다.


- 임베디드 시스템.

- 임베디드 시스템에서는 "메모리"가 주요 자원이다.


그런데, 1번에서 인스트럭션의 길이가 길어진다고 했다. 인스트럭션의 길이가 길어진다는 것은, 바이너리의 크기가 CISC보다 커진다는 의미와 상통한다. 

바이너리의 크기가 커지는 결함을 해결하기 위해 Thumb라는 모드를 도입한 것이다.


ARM의 명령으로 자주 쓰이는 것은 Arithmetic Operation, Branch, load/store 이다. 


ARM을 설계 할 때 상태 레지스터를 만들어두었는데 그것은 CPSR(Current Program Status Register)라고 불린다. CPSR에 플래그 비트를 하나 설정(5번 BIT)하여 비트 값에 따라 ARM/Thumb 유무를 판단할 수 있게 해두었다. 


#DEFINE CPSR[4] T_flag

IF T_flag == 1

Thumb()

ELSE

ARM()


하나의 CPU에 2개의 Instruction이 있다는 것은 하나의 나라에 2명의 주군이 있다고 생각하면 편할 것 같다. 만약, 하나의 나라에 2명의 주군이 있으면 나라는 상당히 복잡해 지기 때문이다. 


지금 ARM은 ARM Mode라는 왕과, Thumb Mode라는 왕이 공존하고 있기 때문에 상당히 복잡한 나라가 되어 있다. 


하지만, Thumb Mode왕은 엄청 힘이 강한 녀석은 아니라는 것이다. Thumb Mode는 별도의 프로세서를 거치는 것이 아니라 보조 하드웨어를 거쳐 변환되는 녀석이다. 하드웨어에서 작업이 이루어 지기 때문에 속도의 차이가 나지 않는다고 보고 있다. 


이야기 컨셉으로 써봤는데 정리하면 이렇다.

ARM Mode와 달리 "Thumb Mode는 보조 하드웨어를 거쳐 ARM Instruction이 되기 때문에 속도 저하가 딱히 일어나지 않는다."


또 하나 생각해보아야 하는게 있다.


한 박스에 그 박스보다 작은 공을 넣는 건 별 지장이 없지만, 그 박스보다 큰 공을 넣게 되면 박스가 찢어지게 된다. 


ARM Mode는 32비트 Instruction  , Thumb Mode는 16비트라고 했다. 


CPSR의 Flag Bit로 인해 ARM -> Thumb로 전환되게 되면 CPU는 32비트로 연산하던 것을 16비트에 알맞게 커스터마이징을 해줘야 한다. 그러다보면, 제약 사항이 생길 것이다.


그럼 이제 그 제약사항도 이해하러 가보자.


ARM User Mode는 16+1개의 레지스터를 사용한다고 한다.

Thumb Mode는 32비트에서 비트가 1/2 줄어든 16비트이니 레지스터 역시 1/2 줄여서 8+1개가 되었다고 한다.


제약사항만 있으면 슬플 것이다. 효율성도 있다고 한다. 


하나의 바이너리에서 ARM / Thumb의 변환이 자유롭다고 한다.

Current Program Status Register 덕분이지 않을까 한다.


대충 의사코드를 만들어보면 이렇지 않을까 싶다. 


IF Func1

Status_ARM()


ELSE IF Func2

Status_Thumb()


혹은 WIN32와 WIN64의 기능을 구분 짓듯이 전처리기를 이용하는 방법도 생각해볼 수 있다.


#ifdef _ARM


#ifdef _THUMB


Func1에 속할 수 있는 대표적인 녀석이 Exception이다.

프로그램이 오동작하여 원하지 않은 사소한 에러가 발생했을 때, 외부에게 도움을 요청하는 것을 Exception이라고 생각할 수 있다. 


ARM에서도 충분히 Exception은 일어날 수 있다.

Exception이 일어나면 reaction이 하드웨어적으로 발생하게 된다.


여담 : 프로그램이 이상이 생겼을 때 CPU에게 유동적으로 보고하는 체계인 Interrupt도 Exception에 포함된다.


여담 : Polling은 프로그램이 이상이 생겨도 CPU가 회진하는 시간이 정해져 있기 때문에 CPU가 자신(에러가 발생한 프로그램)에게 접근하지 않으면 CPU가 이상유무 파악을 못하는 체계.


이제 대충 ARM모드는 언제 쓰는지 알겠고.. Thumb 모드의 장점은 과연 무엇일까?


Thumb모드는 바이너리 이미지가 ARM Mode보다 감소한다. 

명령이 16비트이면, 16비트 메모리 인터페이스에서 1번 fetch하기 때문에 퍼포먼스 관점으로 ARM Mode보다 더 좋다.