Kim Seon Deok

[컴퓨터 구조] 2-1. ARM 본문

컴퓨터 구조

[컴퓨터 구조] 2-1. ARM

seondeok 2022. 11. 10. 03:01





ISA(Instruction Set Architecture)
Instruction = 컴퓨터가 이해하는 명령어
Instruction set = 명령어 집합
프로세서가 다르면 ISA도 약간 다르다
PC의 x86 >> CISC
휴대폰의 ARM >> RISC
RISC(reduced instruction set) : 프로세서가 수행해야 하는 명령 중 간단한 형태 ex) 휴대폰 ARM
CISC(complex instruction set) : 프로세서가 수행해야 하는 명령 중 복잡한 형태 ex) intel PC. x86

RISC CISC
instruction 수 늘어남 instruction 수 줄어듦
한 instruction 당 필요로 하는 클럭 갯수 증가 & 클럭 길이 감소 한 instruction 당 필요로 하는 클럭 갯수 감소 & 클럭 길이 증가


'복잡한 명령을 처리한다' (CISC)= F/F에 저장한 것을 조합회로로 연산하고 다시 F/F에 저장하는데, 조합회로가 복잡해지면 한 클럭의 길이를 길게 끌고 가게됨.
따라서 RISC, CISC 의 특징을 파악하고 용도에 맞게 사용해야 한다.




The ARM Instruction Set
ARM은 MIPS와 유사하며 32비트의 instruction set이다.
ARM / MIPS instruction : 1개의 instruction은 32비트. RISC명령. 무조건 4바이트
X86 intruction : 1개의 instruction은 8비트~32비트까지 다양. 명령어가 복잡해지다 보니 개수가 많아지고 길이가 가변적
>> 복잡한 명령어를 잘게 잘게 쪼개 작은단위의 명령어로 만들어 여러 유닛에 전달
>> 나중에 다시 순서를 합치는 방식으로 변화
>> 더 이상 single processor로는 성능개선이 되지 않는 한계에 이르러 multicoreprocessor로 변화



Arithmetic operations
Design principle1 : 간단하기 위해선 규칙적인 것이 좋다.
단순하고 쉽게 구현해야 더 싼 비용에 고성능을 얻을 수 있다.
intel - 8086, 8088을 거쳐 현재까지 ibm PC를 이어오면서 CISC에서 출발해 한계를 느끼고 RISC까지 변화해오면서 기존의 소프트웨어와 호환성을 유지해오고 있다. 뛰어난 디자인으로 이전 CISC버전과 호환을 유지하며 마켓을 유지.
매킨토시 - 모토로라사가 만든 68000계열. 8비트 프로세서를 사용. CISC의 한계를 느끼고 인텔과 다르게 '파워맥'을 만들어 옛날 소프트웨어와 호환시키지 않았다. 이후 파워맥을 버리고 인텔 CPU를 선택

Design principle2 : 작은 것이 더 빠르다.




Register operand
arithmetic instructions는 레지스터 연산을 사용한다. ARM은 32비트의 레지스터 16개를 묶음으로 하며 0~15까지 각 레지스터에 번호를 붙였다. (레지스터개수가 많아지면 신호가 더 멀리까지 전달되어야 하므로 클럭 사이클이 길어지기 때문에 이를 16개로 제한). ARM은 빈번하게 액세스되는 데이터를 사용하고, 32비트(=4byte)의 데이터는 "word"로 정의해 32비트의 데이터를 한꺼번에 처리하도록 하였다.



Memory operand
- 프로세서는 소량의 데이터만을 레지스터에 저장할 수 있지만 컴퓨터 메모리는 수십억 개의 데이터를 저장할 수 있다. 배열이나 구조체 같은 자료구조는 메모리에 보관한다.
- ARM의 산술연산은 레지스터에서만 실행되므로 메모리와 레지스터 간에 데이터를 주고받는 data transfer instruction(데이터 전송 명령어)가 있어야 한다. 메모리에 기억된 데이터 워드에 접근하려면 명령어가 memory address(메모리 주소)를 지정해야 한다.
LOAD(적재) = 메모리에서 레지스터로 데이터를 복사해오는 데이터 전송 명령
STORE(저장) = 레지스터에서 메모리로 연산한 결과값을 보내는 명령
- 메모리는 바이트단위로 주소를 지정한다. 1 레지스터의 크기는 32비트이므로 한 word단위로 오가는 데이터 양 또한 32비트이다.
-워드의 시작주소는 항상 4의 배수이어야 한다.(alignment restriction)




<프로그램 수행>
1. main memory로 로딩
2.필요한 메모리 할당
3.데이터 메모리 레지스터로 copy
4.연산
5.결과값 다시 원래 메모리 주소번지로 갖다놓음



Register VS Memory
-레지스터는 메모리보다 접근시간이 짧고 처리량도 많으므로, 레지스터에 저장된 데이터를 사용하면 시간이 절약되고 사용하기도 간편하다.
-레지스터 접근은 메모리 접근보다 에너지도 적게든다.
따라서 고성능으로 에너지를 절약하려면 컴파일러가 레지스터를 효율적으로 사용해야 한다.
register spilling = 자주 사용하지 않는 변수를 메모리에 넣는 일
- 컴파일러는 로드된 레지스터를 매핑시키는 역할을 한다. 컴파일러가 가능한 레지스터를 효율적으로 배치시켜야 load, store 횟수가 줄어든다.
따라서 자주 사용되는 변수를 가능한 많이 레지스터에 넣고 나머지 변수는 메모리에 저장했다 필요할 때 꺼내 레지스터에 넣도록 해야 한다.

LDR r5, [r3, #32] ; reg r5 gets A[8]   // r3로부터 32비트 떨어진 위치에 1 word를 로딩해 r5에 넣음
ADD r1, r2, r5 ; g = h + A[8]   // r5 + r2를 r1으로 
STR r5, [r3, #48] ; stores h + A[8] into A[12]   //r3로부터 48비트 떨어진 위치(12 + 4*12)에 32비트 저장





Immediate operands
프로그램 연산에서 상수를 사용하는 경우는 생각보다 많다.
load 명령어를 사용하지 않고 피연산자 하나가 상수인 산술연산을 할 때 그 상수를 immediate operand라 한다.
-상수 피연산자 중 특히 0과 1은 매우 자주 사용되므로 immediate operands를 사용해 메모리에 매핑시키지 않는다면 매번 load할 필요가 사라지기 때문에 매번 메모리에서 상수를 가져오는 것보다 연산이 훨씬 빨라지고 에너지를 덜 소모하게 된다.
Design principle3: 자주 생기는 일을 빠르게 하라.



Representing instructions
ARM은 32비트 instruction을 사용한다. 컴퓨터 내부에서는 서로 다른 n개의 명령어를 각각의 비트로 대응시킨다. (n비트 >> 명령어 2^n가지)
ARM은 16개의 레지스터를 사용하므로 레지스터 하나를 지정하는 데 4비트가 필요하다. (n비트 >> 레지스터 2^n개)



ARM data processing Instructions(DP)

Cond F I Opcode S Rn Rd Operand2
4비트 2비트 1비트 4비트 1비트 4비트 4비트 12비트

Cond : condition
F : instruction format
I : immediate
Opcode : basic opreation of the instruction
S : Set condition code
Rn : The first register source operand
Rd : The destination of the instruction
Operand2 : the second source operand

ADD  r3 = r1 + r2 ; r1, r2는 Rn, r3은 rd
ADD  r3, r3 #4 ; r3 = r3 + 4 // r3은 immediate






**************************************************************************************************************************************
flag
Counter 0~100까지 돌림 > 레지스터에 100 저장하고 0이 될 때까지 1씩 뺌 > 연산결과가 0이 되면 zero flag를 1로 세팅
1. zero flag : 이전에 수행한 결과가 0이 되면 zero flag 1로 세팅
2. sign flag : 이전에 수행한 결과가 0이 되면 sign flag 1로 세팅
3. overflow flag : 이전에 수행한 결과에서 오버플로우 발생하면 overflow flag 1로 세팅
***************************************************************************************************************************************



ARM data transfer instructions(DT)
Data transfer : load, store

Cond F Opcode Rn Rd offset12
4비트 2비트 6비트 4비트 4비트 12비트

LDR  r5, [r3, #32]  ; Temporary reg r5 gets A[8]   //r3가 갖고 있는 주소로부터 32만큼 떨어진 위치에 1word만큼을 읽어와 r5로 가져옴





Conditional operations

CMP   reg1, reg2   // reg1, reg2를 빼서 비교
BEQ   L1      //뺄셈 결과가 0이면 L1으로 jump  (reg1 == reg2)
CMP   reg1, reg2
BNE   L1      // 뺄셈 결과가 0이 아니면 L1으로 jump  (reg1 != reg2)
B Exit ; go to exit  // 무조건 뛰어야 하는 경우


프로그램을 짜고 실행할 때 실행파일은 하드디스크에 있고 위치가 결정되지 않은 상태이다.
프로그램을 실행하면 메모리로 실행파일을 copy하는데 이 때 메모리상에 위치(=메모리 주소) 가 결정된다.


procedure calling
프로시저나 함수는 재사용이 가능하도록 프로그램을 구조화하는 방법이다. 프로시저는 컴파일러에 스택 공간을 관리하기 위해 컴파일러에 의해 사용되고, 프로그래머가 한 번에 한 부분씩 집중해서 처리할 수 있게 해준다.
1. 프로시저가 접근할 수 있는 곳에 인수를 넣는다
2. 프로시저로 제어를 넘긴다.(jump, branch)
3. 프로시저가 필요로 하는 메모리 자원을 획득한다.
4. 필요한 작업을 수행한다.
5. 호출한 프로그램이 접근할 수 있는 장소에 결과값을 넣는다.
6. 프로시저는 프로그램 내의 여러 곳에서 호출될 수 있으므로 원래 위치로 돌아온다.

어떤 high level language로 표현된 main문(caller)에서 또다른 함수(callee)를 호출했을 때, main문에 있던 로컬변수는 다른 위치에 copy되고 호출된 함수로 가면 호출된 함수의 로컬변수를 스택에 할당한다. 호출된 함수가 return되어 끝나면 다시 main문으로 돌아오면서 다른곳에 copy되었던 main문의 로컬변수를 다시 원래 위치로 되돌려주어야 한다.

PC(program counter) =프로그램 수행할 때 그 프로그램이 수행하는 위치를 담아 두는 레지스터.
BNE, BEQ, jump를 만나면 해당 번호로 바뀜)





procedure call instructions
- Branch and link : return address(복귀주소)를 링크레지스터(lr)에 저장하고 branch
링크는 프로시저 종료 후 올바른 주소로 되돌아올 수 있도록 호출한 곳과 프로시저 사이에 주소 또는 링크를 형성한다.
lr (링크 레지스터) : return address를 미리 저장해두는 레지스터
한 프로시저가 여러 곳에서 호출될 수 있기 때문에 return address는 꼭 필요하다.
- register spilling에 이상적인 자료구조는 스택이다.
스택에는 다음 프로시저가 스필할 레지스터를 저장할 장소나 레지스터의 옛날 값이 저장된 장소를 표시하기 위해 최근에 할당된 주소를 가리키는 포인터가 필요하다.

stack : 후입선출(last in first out) 큐로 구성된 자료구조
stack pointer(sp) : 가장 최근에 스택에 할당된 주소를 가리키는 값 . 메모리의 특정 주소번지를 가리키는 레지스터
push : sp 감소 pop : sp 증가

- 레지스터에 들어가지 못할 만큼 큰 배열이나 구조체 같은 local variable을 저장하는 데에도 스택이 사용되기 때문에 문제가 복잡해진다.
procedure frame(=activation record) : 프로시저의 저장된 레지스터와 local variable을 가지고 있는 스택 영역
어떤 프로시저가 일어날 때 생겼다가 프로시저가 종료되어 pop되면 사라진다.




Leaf procedure : 다른 프로시저를 호출하지 않는 프로시저

Non-leaf procedure : 다른 프로시저를 호출하는 프로시저


Heap
메모리에는 프로시저 내에서 정의된 자동변수 외에도 static 변수와 dynamic 변수를 위한 메모리 공간도 필요하다.
스택은 숫자가 큰 주소에서 시작해서 주소값이 작은쪽으로 자란다(activation record).
주소값이 0인 부분은 reserve되어있고 그 다음은 기계어 코드가 들어가는 text segment이다.
그 다음 변하지 않는 global data가 포함된 static data가 들어가고 그 다음에 dynamic data가 들어간다.
특히 dynamic data 중 linked list. malloc(힙에 공간을 할당한 후 공간을 가리키는 포인터를 결과값으로 보냄), free(포인터가 가리키는 힙공간을 반납)같은 자료구조는 늘어나기도 하고 줄어들기도 한다. 이러한 세그먼트를 전통적으로 힙이라 부르며, 전체적으로 스택과 힙이 서로 마주보면서 자라도록 할당하기 때문에 메모리의 효율적인 사용이 가능하다.



Translation and Startup
< C언어 번역계층 >
high level language는 assembler로 컴파일되고 다시 기계어 형태로 어셈블된다. 링커는 모듈들을 라이브러리 루틴과 합쳐 모든 외부 참조를 해결한다. 다음으로 프로세서가 실행할 수 있도록 로더가 기계어 코드를 적절한 메모리 위치에 넣는다.

1.컴파일러 : high level language를 어셈블리어로 변환
2. 어셈블러 : 기계어로 번역할 수 있는 기호화된 언어.
3. 링커 : (static link) object와 library를 한 덩어리로 붙임. (dynamic link) object와 library를 한 덩어리로 붙이지x. DLL로 분리
4. 로더 : 운영체제의 한 프로그램으로 헤더파일을 읽어 os에게 메모리를 할당하도록 함.









Comments