메모리에 데이터와 프로그램을 저장하고 CPU는 그것을 읽어서 연산만 수행하는 개념.
Fetch → Decode → Execute → Store :: 반드시 이 cycle은 머릿속에 넣어두자!
메모리로부터 정의된 instruction을 가져와서 수행하고, 다음 instruction을 가져와서 수행하고…
add r0, r1, r3
라는 명령줄이 있다고 가정하자.
add
같은 수행할 연산을 의미 r1, r3
같은 피연산자를 의미. register, memory 또는 외부에 있을 수 있다.r0
, 연산결과를 저장할 위치 지정Data movement
데이터를 source에서 destination으로 옮기거나 복사하는 것을 목표로 하는 operation이다.
Arithmetic and Logic (ALU)
Operands 사이에서 특정 연산을 수행하고 destination에 저장하는 것을 목표로 하는 operation이다.
Branch (or Control flow)
순차적인 흐름에서 벗어나서 다른 곳으로 분기할 때 사용하는 operation이다.
4-address instrunction
OPCode Res, Op1, Op2, NextInst
이다.Op1
과 Op2
사이에서 OPCode
연산을 수행한 뒤 결과를 Res
에 저장한다.Res
와 Op1
, Op2
는 모두 memory의 주소를 가리킨다.PC
register도 없다.NextInst
에 명시해줘야 한다.3-Address Instruction
PC
register가 있는 상황을 가정하면 위 instrunction에서 NextInst
가 불필요하다.OPCode Res, Op1, Op2
이다.PC
의 값을 바꾸는 명령어(branch
, jump
)를 사용한다.2-Address Instruction
일반형은 OPCode Op2, Op1
d이다.
연산 결과를 따로 저장하지 않고, operand 중 하나인 Op2
에 덮어쓴다.
하지만, A + B = C
를 C = C + A
, C = C + B
이렇게 두 번에 나눠서 진행해야하므로 같은 연산을 하더라도 3-address instruction보다 많은 instruction이 필요하다.
1-Address Instruction (Accumulator Machine)
CPU 내부에 ACC
(Accumulator) register가 포함된다. 연산 중간 결과가 이곳에 저장된다.
일반형은 OPCode Op1
이다.
Op1
과 ACC
사이의 OPCode
연산을 수행한 결과를 다시 ACC
에 덮어씌워 저장한다.
Accumulator에 접근하기 위한 명령어 (LDA
, STA
)가 필요하다.
같은 결과를 만들기위한 instruction의 개수가 더욱 늘어난다는 단점이 있다.
ACC
에 너무 자주 접근하기 때문에 접근하는 행위 자체가 하나의 bottleneck이 된다. CPU 성능을 올리기 병렬화나 파이프라이닝을 이용하는데, ACC
의 구조적 특징으로 인해 이 수혜를 받을 수 없다.
하나의 operand를 memory에서 가져와야 하기 때문에 여전히 memory traffic이 있다.
0-Address Instrunction (Stack Machine)
A * B - (A + C * B)
를 구현한다고 가정하면 다음과 같다.push A
→ push B
→ mul
push A
→ push C
→ push B
→ mul
→ add
→ sub
CPU 내부에 여러 개의 register를 둬서 저장공간을 확보하는 방법으로 요즘은 전부 이거 사용한다. Register와 memory 사이의 data를 이동시키는 명령어가 추가로 필요하다.
Operand 2개를 사용할 때, 하나는 register에 있고 다른 하나는 memory에 있으면 두 operand를 load 하는 데 소요되는 시간이 서로 달라서 같은 instruction을 수행해도 소요되는 시간이 달라질 여지가 있다. 이는 당장에는 문제가 되지 않지만, CPU를 최적화하는 여러 기법을 적용할 때 방해요소로 작용한다. 물론 이를 해결하는 수많은 방법이 연구돼 적용됐다.