cpu의 고유 능력중 하나
첫번째로 나온 복잡 명령어 집합 컴퓨터(CISC)
x86 구조도 복잡 명령어 집합에 기초를 두고 있다.
x86 프로세서 생산 제조업체 (인텔, AMD)
현대 컴퓨터는 기본적으로 폰 노이만구조이다.
핵심
'저장 개념에서 프로그램과 프로그램이 사용하는 데이터에 어떤 차이도 없어야하며, 모두 컴퓨터의 저장 장치 안에 저장될 수 있어야 한다.'
메모리에 더 많은 프로그램 적재하려면 기계명령어를 매우 세밀하게 설계해서 차지하는 저장공간을 줄여야함.
-> 복잡명령어 집합의 필요성
복잡 명령어 집합이 나올 당시에 cpu 명령어 집합은 직접연결(hardwired) 방식이었다.
명령어 인출, 해독, 실행 등 각 단계가 특정 조합 회로로 직접 제어됨.
-> 명령어 실행에는 효율적, but 유연성 떨어짐(새로 추가시 디버깅어려움, 복잡해짐)
공통적으로 사용되는 연산에 해당하는 명령어들을 마이크로코드로 만들어 소프트웨어가 하드웨어를 대체할수 있도록 함. 하드웨어 수정하지 않고 이 마이크로코드(소프트웨어) 수정을 통해 작업하도록 하면 설계복잡도가 낮아짐
이 방식의 문제점)
프로그래머가 어셈블리어로 프로그램 더 쉽게 작성가능해졌고 저장공간도 줄어듬
여기서 복잡한 문제는 마이크로코드로 단순화할 수 있었다.
하지만 버그수정이 어렵다는 단점이 있고, 마이크로코드 설계하려면 트랜지스터가 매우 많이 필요함.
복잡명령어집합(x86) 나오고, 마이크로코드로 메모리공간 줄임. 하지만 가변길이의 명령어라서 트랜지스터 많이씀. 클럭주파수 높이기 힘들고 파이프라인에 제약이있음
그래서 축소명령어 집합이 나왔는데 얘는 마이크로코드 필요없고 더 간단하고 동일한 길이의 명령어로 되어있어서 파이프라인구조를 사용했을 때 효율이 좋아서 작게만들 수 있고, 레지스터 기반 연산을 하고, 클럭주파수도 더 높게 쓸수 있음.
그래서 cisc 시대가 왔다가 risc 개발자들(amd, intel) 이 risc를 cisc처럼 사용할 수 있도록 개발함.
-> 복잡명령어 집합을 축소명령어 집합으로 간단하게 변환(마이크로 명령어를 사용해서)
그리고 하이퍼스레딩 (=하드웨어 스레드)개발. = 하나의 cpu코어로 여러개의 스레드를 사용할 수 있도록 함.(운영체제 입장에서는 코어하나당 하나의 스레드로 쓰는것처럼 보이게하는 환각기술)
이 기술들을 장착해서 risc는 cisc랑 경쟁이 가능해졌음
하지만 여전히 메모리 접근에서는 컴파일러 최적화에서 축소명령어 집합이 더 좋음(load,store만 으로 접근 가능해서)
그렇게 둘이 경쟁하다가 결국 risc에서 cisc의 장점들을 흡수해서 더 발전시켜가지고 cisc를 이겨버림(ex인텔의 x86)
그래서 cisc는 임베디드, 저전력 영역이 되어버렸음 (risc win)
애플은 x86 쓰다가 지들이 자체 개발해서 m1칩으로 바꿈 (근데 얘는 축소명령어집합의 arm 기반임) 그래서 다시 데스크톱시장에서 쫌 쓰이는 느낌
x86 vs arm 느낌인듯
레지스터 쓰는 이유 = 속도빨라서
프로세스 -> 코드의 데이터 메모리에 적재 -> 코드실행
인데 이떄 메모리 데이터를 cpu가 쓸 레지스터로 옮겨야한다
레지스터, 메모리 둘다 정보저장용인데 레지스터가 빠르고 비쌈. 그래서 메모리에 정보 저장해놓고 cpu가 쓸때만 레지스터로 땡겨서 쓰는거다
스택 상단에 스택 하단을 가리키는 스택포인터 있음. 이걸로 함수 호출 스택 추적 가능.
이런 함수들이 실행될 때 로컬변수,매개변수 등 저장된 메모리공간 = 스택프레임
이게 모인게 스택영역
프로그램 카운터 = PC 라고 부른다
x86에서는 명령어 포인터 = IC 라고 부름
어떻게 불리는지가 중요한게 아니라 동작이 중요하다
명령어가 엄청 많은데 cpu가 어떤걸 실행해야 하는지 어떻게 알수있지?
-> 첫번째로 실행될 명령어 주소가 PC레지스터에 저장되어서 여기서 가져와서 실행한다.
순차적으로 실행되다가 분기점프, 함수호출 반환 등이 일어나면 그에 따라 실행함
x86 에서는 FLAGS레지스터
ARM 에서는 응용프로그램 상태 레지스터 라고함
어떤 상태 저장?
-> 산술 연산시에 carry, overflow 생길 수 있는데 이런 정보가 저장됨
대부분 프로그램이 유저모드에서 실행된다. 커널모드에서는 제한없이 뭐든 실행가능.
지금 유저모드인지 커널모드인지 어케 알지?
-> 상태레지스터 값을 보면 됨(어떤상태인지 표시하는 비트가 따로 있음)
cpu는 이 값을 바꾸어서 유저모드 <-> 커널모드 전환한다.
레지스터에 저장된 모든 정보를 상황정보라고 한다.
얘는 뭐하는애지?
-> 프로그램 일시중지, 다시 재개 등 할 때 필요함
왜 저장해야하나?
-> cpu는 원래 순차적으로 실행하지만 함수를 만나서 다른함수로 점프할 때가 많다.
그러면 이 때 cpu가 커널코드를 실행해야될 수 있는데 그때 커널모드로 전환해야됨
cpu가 인터럽트 발생시 바로 처리하러 가야되기 때문에 현재 프로그램 중지 필요
->함수 호출마다 스택프레임 생성
-> 사용자상태스택, 커널상태스택 따로 있는데 운영체제 도움 필요할 떄 시스템호출 해야됨
이 때 유저 -> 커널 전환해서 유저모드 스레드에 대응하는 커널모드 스택 찾은 후 커널 코드 실행해서 시스템호출 요청을 처리함
-> 인터럽트 발생시 cpu실행 중지되고 특정 인터럽트 처리 함수로 점프해야됨
인터럽트 처리 함수의 실행시간 스택은 어디에 있을까?
1. 인터럽트 처리함수에 자체 실행시간스택 없으면 커널모드 스택이용해서 처리
2. 인터럽트 처리함수에 자체적으로 isr스택이라는 실행 시간 스택이 있는 경우에는 이걸 사용하는데 유저 -> 커널모드로 전환해서 하듯이 처리
스레드 A에서 스레드B로 전환하려고 할 때
1. 주소공간 전환 필요(서로다른 프로세스에 있을 수 있기때문에)
2. cpu를 스레드 a에서 스레드b로 전환. 이 때 스레드a의 상황정보 저장하고 스레드b의 상황정보 복원필요