x86이 못생긴 이유는 무엇입니까? 다른 사람과 비교할 때 왜 열등하다고 간주됩니까? [닫은]


105

최근에 나는 몇 가지 SO 아카이브를 읽고 x86 아키텍처에 대한 진술을 발견했습니다.

그리고 같은 더 많은 댓글

검색을 시도했지만 이유를 찾지 못했습니다. 내가 익숙한 유일한 아키텍처이기 때문에 x86이 나쁘다고 생각하지 않습니다.

누군가가 x86을 다른 사람에 비해 못생긴 / 나쁜 / 열등하다고 생각하는 이유를 친절하게 줄 수 있습니까?


1
지금까지의 답변을 기반으로 S & A를 진행하고 있지만 CISC는 m68k 명령어 세트에 대한 문제가 아니라는 점에 유의할 것입니다. x86은 그대로이며 유지할 수 있습니다.
dmckee --- ex-moderator kitten

"S & A"란 무엇입니까? "CISC는 m68k 명령어 세트의 문제가 아닙니다." -왜 안돼?
claws

5
motorala 68000 시리즈 칩은 CISC 아키텍처가 높지만 균일하고 상당히 직교하며 매우 쉬운 명령어 세트를 가지고 있습니다. x86과 다른 이유는 무엇입니까? 모르겠어요. 그러나 칩의 복잡성과 명령어 세트 (즉, 어셈블리 프로그래머가 보는 인터페이스)의 복잡성 사이에는 큰 차이가 있습니다 .
dmckee --- ex-moderator kitten

4
매우 흥미로운 질문에 +1.
Turing Complete

1
CISC 및 RISC 설계의 원동력에 대한 좋은 논의와 함께 다양한 프로세서의 에너지 효율성에 대한 최근 연구가 여기에 있습니다. extremetech.com/extreme/…

답변:


93

이에 대한 몇 가지 가능한 이유 :

  1. x86은 비교적 오래된 ISA입니다 (원조는 결국 8086이었습니다).
  2. x86은 여러 번 크게 발전했지만 이전 바이너리와의 하위 호환성을 유지하려면 하드웨어가 필요합니다. 예를 들어 최신 x86 하드웨어에는 기본적으로 16 비트 코드를 실행하기위한 지원이 여전히 포함되어 있습니다. 또한 리얼 모드, 보호 모드, 가상 8086 모드 및 (amd64) 롱 모드와 같은 이전 코드가 동일한 프로세서에서 상호 작용할 수 있도록 여러 메모리 주소 지정 모델이 있습니다. 이것은 일부 사람들에게 혼란 스러울 수 있습니다.
  3. x86은 CISC 시스템입니다. 오랫동안 이것은 MIPS 또는 ARM과 같은 RISC 시스템보다 느리다는 것을 의미했습니다. 명령어에는 데이터 상호 의존성과 플래그가 있어 대부분의 명령어 수준 병렬 처리 형식을 구현하기 어렵 기 때문입니다. 최신 구현에서는 x86 명령어를 " micro-ops " 라고하는 RISC와 유사한 명령어로 변환하여 이러한 종류의 최적화를 하드웨어에서 구현할 수 있도록합니다.
  4. 어떤면에서 x86은 열등하지 않고 단지 다릅니다. 예를 들어 입력 / 출력은 대부분의 아키텍처에서 메모리 매핑으로 처리되지만 x86에서는 처리되지 않습니다. (주의 : 현대 x86 컴퓨터는 일반적으로 어떤 형태가 DMA의 ,하지만 지원 및 메모리 매핑을 통해 다른 하드웨어와 통신 ISA는 여전히 같은 I / O 지침을 가지고 INOUT)
  5. x86 ISA 에는 아키텍처 레지스터가 매우 적기 때문에 프로그램이 필요한 것보다 더 자주 메모리를 통해 왕복 할 수 있습니다. 이를 수행하는 데 필요한 추가 지침은 효율적인 저장 전달 이지만 유용한 작업에 사용될 수있는 실행 리소스를 사용합니다.지연 시간을 낮게 유지합니다. 레지스터 이름을 큰 물리적 레지스터 파일로 변경하는 최신 구현은 많은 명령을 계속 사용할 수 있지만 아키텍처 레지스터의 부족은 여전히 ​​32 비트 x86의 중요한 약점이었습니다. x86-64의 8 개에서 16 개 정수 및 벡터 레지스터로의 증가는 64 비트 코드에서 32 비트보다 더 빠른 (더 효율적인 레지스터 호출 ABI와 함께) 가장 큰 요소 중 하나이며 각 레지스터의 너비가 증가한 것이 아닙니다. 16 개에서 32 개 정수 레지스터로 추가 증가하면 일부는 도움이되지만 그다지 많지는 않습니다. (AVX512는 32 개의 벡터 레지스터로 증가합니다. 부동 소수점 코드는 대기 시간이 더 길고 종종 더 많은 상수가 필요하기 때문입니다.) ( 주석 참조 )
  6. x86은 많은 기능을 가진 복잡한 아키텍처이기 때문에 x86 어셈블리 코드는 복잡합니다. 일반적인 MIPS 기계에 대한 지침 목록은 한 장의 Letter 크기의 종이에 맞습니다. x86에 해당하는 목록은 여러 페이지를 채우고 지침은 더 많은 작업을 수행하므로 목록에서 제공 할 수있는 것보다 더 큰 설명이 필요한 경우가 많습니다. 예를 들어, MOVSB명령어 가 수행하는 작업을 설명하려면 비교적 큰 C 코드 블록이 필요합니다.

    if (DF==0) 
      *(byte*)DI++ = *(byte*)SI++; 
    else 
      *(byte*)DI-- = *(byte*)SI--;
    

    이는로드, 저장 및 두 개의 더하기 또는 빼기 (플래그 입력에 의해 제어 됨)를 수행하는 단일 명령어이며, 각각은 RISC 시스템에서 별도의 명령어입니다.

    MIPS (및 유사한 아키텍처)의 단순성이 반드시 이들을 우월하게 만드는 것은 아니지만 어셈블러 클래스에 대한 소개를 가르치려면 더 간단한 ISA 로 시작하는 것이 좋습니다 . 일부 어셈블리 클래스는 y86 이라는 매우 단순화 된 x86 서브 세트를 가르치는데 , 이는 실제 사용에 유용하지 않다는 점 (예 : 시프트 명령 없음)을 넘어 단순화되거나 일부는 기본 x86 명령 만 가르칩니다.

  7. x86은 가변 길이 opcode를 사용하여 명령어 구문 분석과 관련하여 하드웨어 복잡성을 추가합니다. 현대 시대에 CPU가 원시 계산보다 메모리 대역폭에 의해 점점 더 제한됨에 따라이 비용은 점점 작아지고 있지만 많은 "x86 bashing"기사와 태도는이 비용이 비교적 훨씬 더 큰 시대에서 비롯되었습니다.
    2016 업데이트 : Anandtech는 x64 및 AArch64 아래의 opcode 크기 에 대한 토론 을 게시했습니다 .

편집 : 이것은 x86을 bash 로되 어서 는 안됩니다 ! 파티. 나는 선택의 여지가 거의 없었지만 질문이 표현 된 방식을 감안할 때 약간의 강타를 할 수밖에 없었다. 그러나 (1)을 제외하고 이러한 모든 작업은 정당한 이유로 수행되었습니다 (댓글 참조). 인텔 디자이너는 어리석지 않습니다. 아키텍쳐로 몇 가지를 달성하고 싶었고, 이는 이러한 것들을 실현하기 위해 지불해야하는 세금 중 일부입니다.


17
트레이드 오프입니다. 바이너리 크기가 더 작을 수 있다는 점에서 강점이지만 이러한 명령어에 대한 파서를 구현하려면 매우 복잡한 하드웨어가 필요하다는 점에서 약점입니다. 대부분의 명령어는 어쨌든 동일한 크기입니다 .x86에서 가변 길이 opcode의 대부분의 이유는 기능을 추가하기로 결정하고 작업해야하는 비트 수에서 원하는 것을 나타낼 수 없다는 것을 발견했을 때입니다. . 대다수의 사람들은 하드웨어 복잡성이나 전력 소비만큼 이진 크기에 관심이 없습니다.
Billy ONeal 2010

8
@Joey Adams : x86의 가변 길이 명령어를 ARM의 Thumb 모드 ( en.wikipedia.org/wiki/ARM_architecture#Thumb ) 와 대조합니다 . Thumb 모드는 더 짧은 명령어가 일반 명령어에 직접 매핑되기 때문에 ARM에 대해 훨씬 더 작은 객체 코드를 생성합니다. 그러나 더 큰 명령어와 더 작은 명령어간에 1 : 1 매핑이 있기 때문에 구문 분석 하드웨어를 구현하기가 간단합니다. x86의 가변 길이 명령어는 처음에 그런 방식으로 설계되지 않았기 때문에 이러한 이점이 없습니다.
Billy ONeal 2010

7
(6) 모든 연산 코드가 모든 프로그램에서 사용되어야하는 것은 아니지만 젠장, SSE3가 필요할 때 사용하게되어 기쁩니다.
Chris K

4
@Chris Kaminski : 하드웨어에 어떤 영향을주지 않습니까? 물론, 현대의 풀 사이즈 컴퓨터에서는 아무도 신경 쓰지 않을 것입니다.하지만 제가 휴대폰 같은 것을 만드는 경우, 저는 거의 다른 것보다 전력 소비에 더 신경을 씁니다. 가변 길이 opcode는 실행 시간을 늘리지 않지만 디코드 하드웨어는 여전히 작동하는 데 전원이 필요합니다.
Billy ONeal 2010

5
x86 명령어 세트를 너무 추하게 만드는 것 중 하나입니다. 누산기인지 레지스터 파일 기반 아키텍처인지 결정할 수 없기 때문입니다. , 6 만 8 천 팬들의 말에 관계없이).
ninjalj 2011

25

내 마음 속에서 x86에 대한 주요 노크는 CISC 기원입니다. 명령어 세트에는 많은 암시 적 상호 의존성이 포함되어 있습니다. 이러한 상호 종속성은 칩에서 명령 재정렬과 같은 작업을 수행하기 어렵게합니다. 이러한 상호 종속성의 아티팩트와 의미는 각 명령에 대해 보존되어야하기 때문입니다.

예를 들어, 대부분의 x86 정수 더하기 및 빼기 명령어는 플래그 레지스터를 수정합니다. 더하기 또는 빼기를 수행 한 후 다음 작업은 종종 플래그 레지스터를 확인하여 오버플로, 부호 비트 등을 확인하는 것입니다. 그 후에 다른 더하기가 있으면 두 번째 더하기 실행을 시작하는 것이 안전한지 여부를 알기가 매우 어렵습니다. 첫 번째 추가의 결과가 알려지기 전에.

RISC 아키텍처에서 추가 명령어는 입력 피연산자와 출력 레지스터를 지정하며 연산에 대한 모든 것은 해당 레지스터 만 사용하여 발생합니다. 이렇게하면 모든 항목을 정렬하고 단일 파일을 실행하도록하는 블루밍 플래그 레지스터가 없기 때문에 서로 가까운 추가 작업을 훨씬 쉽게 분리 할 수 ​​있습니다.

MIPS 스타일의 RISC 설계 인 DEC Alpha AXP 칩은 사용 가능한 명령어에서 매우 스파르타 적이었지만 명령어 세트는 명령어 간 암시 적 레지스터 종속성을 피하기 위해 설계되었습니다. 하드웨어 정의 스택 레지스터가 없습니다. 하드웨어 정의 플래그 레지스터가 없습니다. 명령 포인터조차도 OS에 정의되어 있습니다. 호출자에게 돌아가려면 호출자가 반환 할 주소를 알려주는 방법을 알아 내야했습니다. 이것은 일반적으로 OS 호출 규칙에 의해 정의되었습니다. 하지만 x86에서는 칩 하드웨어에 의해 정의됩니다.

어쨌든, 3 ~ 4 세대에 걸친 Alpha AXP 칩 설계에서 하드웨어는 32 개의 int 레지스터와 32 개의 부동 레지스터로 구성된 스파르탄 명령어 세트의 문자 적 ​​구현에서 80 개의 내부 레지스터, 레지스터 이름 변경, 결과 전달 (이전 명령어의 결과가 값에 따라 나중 명령어로 전달되는 경우) 및 모든 종류의 거칠고 미친 성능 부스터. 그리고 이러한 모든 종소리와 휘파람으로 AXP 칩 다이는 그 당시의 비슷한 펜티엄 칩 다이보다 훨씬 작았으며 AXP는 훨씬 더 빨랐습니다.

x86 명령어 세트의 복잡성으로 인해 많은 종류의 실행 최적화가 불가능하지는 않더라도 엄청나게 많은 비용이 들기 때문에 x86 패밀리 트리에서 이러한 종류의 성능 급증이 크게 향상되지는 않습니다. 인텔의 천재성은 더 이상 하드웨어에서 x86 명령 세트를 구현하는 것을 포기하는 데있었습니다. 모든 최신 x86 칩은 실제로 x86 명령을 어느 정도 해석하여 원래 x86의 모든 의미를 보존하는 내부 마이크로 코드로 변환하는 RISC 코어입니다. 그러나 마이크로 코드에 대한 RISC 비 순차 및 기타 최적화를 약간 허용합니다.

저는 x86 어셈블러를 많이 작성했으며 CISC 루트의 편리함을 충분히 이해할 수 있습니다. 그러나 Alpha AXP 어셈블러를 작성하는 데 시간을 할애하기 전까지는 x86이 얼마나 복잡한 지 충분히 이해하지 못했습니다. 나는 AXP의 단순성과 균일성에 매료되었습니다. 그 차이는 엄청나고 심오합니다.


6
m68k를 설명 할 수있을 때까지 CISC 자체 에 대한 비난을 듣지 않을 것 입니다.
dmckee --- ex-moderator kitten

2
나는 m68k에 익숙하지 않아서 비평 할 수 없다.
dthorpe 2010

4
나는이 대답이 반대표를 던질만큼 나쁘지 않다고 생각하지만, 전체 "RISC는 CISC보다 작고 빠르다"라는 주장이 현대에 실제로 관련이 없다고 생각합니다. 물론 AXP는 당분간 훨씬 빨라 졌을 수 있지만 문제는 최신 RISC와 최신 CISC가 성능면에서 거의 동일하다는 것입니다. 내 대답에서 말했듯이 x86 디코딩에 대한 약간의 전력 패널티는 휴대 전화와 같은 것에 x86을 사용하지 않는 이유이지만 풀 사이즈 데스크톱 또는 노트북에서는 거의 논쟁이 아닙니다.
Billy ONeal

4
@Billy : 크기는 단순히 코드 크기 나 명령어 크기 이상입니다. 인텔은 모든 특수 명령 (후드 아래의 RISC 마이크로 코드 코어 여부)에 대한 하드웨어 로직을 구현하기 위해 칩 표면적에 상당한 벌금을 지불합니다. 다이의 크기는 제조 비용에 직접적인 영향을 미치므로 최신 시스템 설계에서는 여전히 유효한 문제입니다.
dthorpe

1
@dthorpe : 나는 당신이 쓴 모든 것이 아니라면 대부분의 의견에 동의하지 않습니다. 실행하는 것이 안전하다고 경우 이제까지 8086 년부터, 당신은 걱정하지 않았다 add다른 후 add. 규칙은 분명합니다. 명령 재정렬을 처리 할 필요도 없습니다. 90 년대 중반의 펜티엄 프로 이후로 CPU는 당신을 위해 그렇게합니다. 당신이 언급하고있는 것은 20 년 전에 문제가되었을 지 모르지만, 요즘 x86 아키텍처에 반대 할 이유가 없습니다.
Nathan Fellman 2013 년

21

x86 아키텍처는 8008 마이크로 프로세서 및 친척의 설계에서 시작되었습니다. 이 CPU는 메모리가 느린시기에 설계되었으며 CPU 다이에서 할 수 있다면 훨씬 더 빠릅니다. 그러나 CPU 다이 공간도 비쌌습니다. 이 두 가지 이유는 특별한 목적을 갖는 경향이있는 적은 수의 레지스터와 모든 종류의 문제와 제한이있는 복잡한 명령어 세트가있는 이유입니다.

같은 시대의 다른 프로세서 (예 : 6502 제품군)도 비슷한 제한과 단점이 있습니다. 흥미롭게도 8008 시리즈와 6502 시리즈는 모두 임베디드 컨트롤러로 설계되었습니다. 그 당시에도 임베디드 컨트롤러는 어셈블러로 프로그래밍 될 것으로 예상되었으며 여러면에서 컴파일러 작성자가 아닌 어셈블리 프로그래머에게 적합했습니다. (컴파일러 작성을 수용 할 때 어떤 일이 발생하는지 VAX 칩을보십시오.) 설계자는 이들이 범용 컴퓨팅 플랫폼이 될 것이라고 기대하지 않았습니다. 이것이 바로 POWER 아키텍처의 전임자와 같은 것입니다. 물론 가정용 컴퓨터 혁명은 그것을 바꾸어 놓았습니다.


4
문제에 대한 역사적 배경이있는 것으로 보이는 사람의 유일한 답변은 +1입니다.
Billy ONeal

3
기억은 항상 느 렸습니다. 1982 년에 Z80과 CP / M으로 시작했을 때보 다 (상대적으로 말해서) 오늘날 더 느릴 수 있습니다. 멸종은 특정 진화 방향이 멈추기 때문에 진화의 유일한 경로는 아닙니다. x86은 28 년 (지금까지 존재)에 잘 적응했다고 말할 수 있습니다.
Olof Forshell 2010

4
메모리 속도는 8086 즈음에 CPU와 거의 비슷합니다. Texas Instruments의 9900은 이러한 일이 발생했기 때문에 작동하는 디자인을 가지고 있습니다. 그러나 CPU는 다시 한 번 앞서 나가고 있습니다. 지금은이를 관리하는 데 도움이되는 캐시가 있습니다.
staticsan

3
@Olof Forshell : 8080 어셈블리 코드가 8086 코드로 변환 될 수 있다는 점에서 어셈블러와 호환되었습니다. 그 관점에서 8080을 8008과 확장으로 볼 수있는 것처럼 8080에 확장이 추가되었습니다.
David Thornley 2011 년

3
@Olof Forshell : 8086이 그런 일이 일어나도록 설계된 것을 제외하고는. 그것은 8080의 확장이었고 대부분의 (아마도 모든) 8080 명령어는 일대일로 매핑되었으며 분명히 유사한 의미를 가지고 있습니다. 어떤 방식으로 푸시하든 IBM 360 아키텍처에는 해당되지 않습니다.
David Thornley

13

여기에 몇 가지 추가 측면이 있습니다.

작업 "a = b / c"x86이이를 다음과 같이 구현한다고 생각해보십시오.

  mov eax,b
  xor edx,edx
  div dword ptr c
  mov a,eax

div 명령의 추가 보너스로 edx는 나머지를 포함합니다.

RISC 프로세서는 먼저 b와 c의 주소를로드하고, b와 c를 메모리에서 레지스터로로드하고, 분할을 수행하고 a의 주소를로드 한 다음 결과를 저장해야합니다. Dst, src 구문 :

  mov r5,addr b
  mov r5,[r5]
  mov r6,addr c
  mov r6,[r6]
  div r7,r5,r6
  mov r5,addr a
  mov [r5],r7

여기에는 일반적으로 나머지가 없습니다.

포인터를 통해 변수를로드해야하는 경우 두 시퀀스 모두 더 길어질 수 있지만 다른 레지스터에 이미로드 된 포인터가 하나 이상있을 수 있기 때문에 RISC에 대한 가능성은 적습니다. x86은 레지스터가 적기 때문에 포인터가 그중 하나에있을 가능성이 더 적습니다.

장점과 단점:

RISC 명령어는 명령어 스케줄링을 개선하기 위해 주변 코드와 혼합 될 수 있습니다. x86에서는 대신 CPU 자체 내에서이 작업을 수행하는 (순서에 따라 다소 잘) 가능성이 적습니다. 위의 RISC 시퀀스는 일반적으로 32 비트 아키텍처에서 28 바이트 길이 (각각 32 비트 / 4 바이트 너비의 명령어 7 개)입니다. 이렇게하면 명령어를 가져올 때 (7 회 가져 오기) 오프 칩 메모리가 더 많이 작동합니다. 밀도가 높은 x86 시퀀스에는 더 적은 명령어가 포함되어 있으며 너비는 다양하지만 평균 4 바이트 / 명령어도 여기에서 볼 수 있습니다. 7 번의 가져 오기 속도를 높이기위한 명령어 캐시가 있어도 x86과 비교하여 다른 곳에서 3 개의 부족한 부분이 있음을 의미합니다.

저장 / 복원 할 레지스터가 더 적은 x86 아키텍처는 아마도 스레드 전환을 수행하고 RISC보다 빠르게 인터럽트를 처리 할 것임을 의미합니다. 저장 및 복원 할 레지스터가 많을수록 인터럽트를 수행하는 데 더 많은 임시 RAM 스택 공간이 필요하고 스레드 상태를 저장하기위한 더 영구적 인 스택 공간이 필요합니다. 이러한 측면은 x86을 순수한 RTOS 실행에 더 적합한 후보로 만들 것입니다.

좀 더 개인적인 메모에서 x86보다 RISC 어셈블리를 작성하는 것이 더 어렵다는 것을 알았습니다. RISC 루틴을 C로 작성하고 생성 된 코드를 컴파일하고 수정하여이 문제를 해결합니다. 이것은 코드 생산 관점에서는 더 효율적이고 실행 관점에서는 덜 효율적입니다. 추적해야 할 모든 32 개의 레지스터. x86에서는 그 반대입니다. "실제"이름을 가진 6-8 개의 레지스터를 사용하면 문제를보다 쉽게 ​​관리 할 수 ​​있고 생성 된 코드가 예상대로 작동 할 것이라는 확신을 갖게됩니다.

추한? 그것은 보는 사람의 눈에 있습니다. 나는 "다른"을 선호합니다.


내 예제에서 a, b 및 c는 즉각적인 값이 아닌 메모리 기반 변수로 간주되어야합니다.
Olof Forshell 2010

... "dword ptr"은 크기를 알 수없는 변수의 크기를 지정하는 데 사용됩니다. 예를 들어 단순히 외부로 선언되거나 게으른 경우.
Olof Forshell 2010

2
먼저 C로 작성하고 어셈블러로 추출하라는 제안을들은 것은 처음이 아닙니다. 확실히 도움이됩니다
Joe Plante 2014-09-27

초기에는 모든 프로세서가 RISC였습니다. CISC는 매우 느린 철 코어 메모리 시스템에 대한 완화 전략으로 등장했습니다. 따라서 CISC는 더 적고 강력한 명령을 사용하고 메모리 하위 시스템에 대한 스트레스를 줄이고 대역폭을 더 잘 사용했습니다. 마찬가지로 레지스터는 원래 누적을 수행하기위한 온칩, CPU 내 메모리 위치로 생각되었습니다. 제가 RISC 시스템을 마지막으로 벤치마킹 한 것은 1993 년-SPARC 및 HP Prisim이었습니다. SPARC는 전반적으로 끔찍했습니다. 프리 심은 추가 / 서브 / 멀티에서 486보다 최대 20 배 빠르지 만 초월 적으로 빨랐습니다. CISC가 더 좋습니다.

당신은 말할 @OlofForshell there typically won't be a reminder하지만 위키는 MIPS 그것을 가지고 있다고 말한다 : en.wikipedia.org/wiki/MIPS_instruction_set#Integer
알렉스 쥬 코브 스키

10

이 질문에는 잘못된 가정이 있다고 생각합니다. x86을 추악하다고 부르는 것은 주로 RISC에 집착하는 학자들입니다. 실제로 x86 ISA는 RISC ISA에서 5-6 개의 명령어를 사용하는 단일 명령어 작업으로 수행 할 수 있습니다. RISC 팬은 최신 x86 CPU가 이러한 "복잡한"명령을 마이크로 옵스로 분해한다고 반박 할 수 있습니다. 하나:

  1. 많은 경우에 그것은 부분적으로 만 사실이거나 전혀 사실이 아닙니다. x86에서 가장 유용한 "복잡한"명령어는 mov %eax, 0x1c(%esp,%edi,4)주소 지정 모드 와 같은 것 입니다.
  2. 현대 기계에서 종종 더 중요한 것은 소비 된주기의 수 (대부분의 작업이 CPU 바인딩이 아니기 때문에)가 아니라 코드의 명령 캐시 영향입니다. 5-6 개의 고정 크기 (일반적으로 32 비트) 명령어는 5 바이트를 넘지 않는 복잡한 명령어 하나 이상에 캐시에 영향을줍니다.

x86은 약 10 ~ 15 년 전에 RISC의 모든 좋은 측면을 실제로 흡수했으며, RISC의 나머지 특성 (실제로 정의하는 것-최소 명령 집합)은 해롭고 바람직하지 않습니다.

CPU 제조의 비용과 복잡성과 에너지 요구 사항 외에도 x86은 최고의 ISA 입니다. 다르게 말하는 사람은 이데올로기 나 의제가 그들의 추론을 방해하는 것입니다.

반면에 CPU 비용이 중요한 임베디드 장치 또는 에너지 소비가 가장 중요한 임베디드 / 모바일 장치를 대상으로하는 경우 ARM 또는 MIPS가 더 적합 할 것입니다. 쉽게 3 ~ 4 배 더 큰 코드를 처리하는 데 필요한 추가 램과 바이너리 크기를 처리해야하며 성능에 근접 할 수는 없습니다. 이것이 중요한지는 당신이 무엇을 실행할 것인지에 달려 있습니다.


3
에너지 소비가 가장 큰 관심사 인 경우 ARM 또는 MIPS가 더 합리적 일 수 있습니다 . 따라서 ARM 또는 MIPS가 더 의미 가있는 측면이 하나 이상 있다면 x86 이 반드시 최고의 ISA가되지 않을까요?
Shahbaz 2013 년

이것이 제가 "비용과 에너지 요구 사항을 제외하고" "최고"를 인정한 이유입니다.
R .. GitHub의 STOP 돕기 ICE

1
인텔이 CPU 속도를 낮추고 다이 크기가 작아서 전력 차이가 크게 제거되었다고 생각합니다. 64k L1 및 1MB L2 캐시가있는 새로운 Celeron 듀얼 64 비트 CPU는 7.5 와트 칩입니다. 그것은 나의 "스타 벅스"행 아웃 머신이고, 배터리 수명은 엄청나게 길고 P6 머신 주위에서 울릴 것이다. 주로 부동 소수점 계산을하는 사람으로서 나는 오래 전에 RISC를 포기했습니다. 그것은 단지 크롤링합니다. 특히 SPARC는 끔찍한 빙하였습니다. RISC가 왜 좋지 않은지에 대한 완벽한 예는 Intel i860 CPU입니다. 인텔은 다시는 거기에 가지 않았습니다.

@RocketRoy : 7.5 와트는 연중 무휴로 전원이 공급되거나 (전체 시간 동안 유용한 계산을 수행하지 않는) 3.7v / 2000mAh 배터리로 실행되는 장치에는 실제로 허용되지 않습니다.
R .. GitHub STOP HELPING ICE

2
@RocketRoy "인텔 i860 CPU. 인텔은 다시는 거기에 가지 않았습니다." 약간의 연구 후, I860는 소리를 많이 VLIW 컴파일러 명령 한 명령 병렬 .... : 아이테니엄 같은
조나단 라인 하트

9

x86 어셈블러 언어는 그렇게 나쁘지 않습니다. 기계 코드에 도달했을 때 정말 추악 해지기 시작합니다. 명령어 인코딩, 주소 지정 모드 등은 대부분의 RISC CPU보다 훨씬 더 복잡합니다. 그리고 이전 버전과의 호환성을 위해 내장 된 추가 재미가 있습니다. 프로세서가 특정 상태에있을 때만 시작되는 기능입니다.

예를 들어, 16 비트 모드에서 주소 지정은 완전히 이상하게 보일 수 있습니다. 에 대한 주소 지정 모드가 [BX+SI]있지만 [AX+BX]. 필요에 따라 사용할 수있는 레지스터에 값이 있는지 확인해야하기 때문에 이와 같은 것은 레지스터 사용을 복잡하게 만드는 경향이 있습니다.

(다행히도 32 비트 모드는 훨씬 더 정상적이며 (예를 들어 세분화와 같이 때때로 다소 이상하지만) 16 비트 x86 코드는 더 이상 부트 로더 및 일부 임베디드 환경과 관련이 없습니다.)

인텔이 x86을 최고의 프로세서로 만들려고했던 옛날부터 남은 것들도 있습니다. 아무도 실제로 더 이상 수행하지 않는 작업을 수행하는 몇 바이트 길이의 명령은 솔직히 너무 느리거나 복잡하기 때문입니다. 두 가지 예에 대한 ENTER 및 LOOP 명령어 -C 스택 프레임 코드는 대부분의 컴파일러에서 "enter"가 아니라 "push ebp; mov ebp, esp"와 같습니다.


2
일부 프로세서에서는 "push / mov"가 더 빠르기 때문에 "enter"대 "push / mov"문제가 발생했다고 생각합니다. 일부 프로세서에서는 "enter"가 더 빠릅니다. C'est la vie.
Dietrich Epp

4
x86 기반 머신을 사용하고 그것을 살펴보기 시작했을 때 (m68k 배경을 가짐), asm 프로그래밍이 답답하다고 느끼기 시작했습니다. 마치 C와 같은 언어로 프로그래밍을 배운 것처럼 asm과 연락을 취해야합니다 ... 표현력, 용이성, 명확성, "일관성", "직관력"을 잃어 버리는 느낌이 들었습니다. x86으로 asm 프로그래밍을 시작했다면 생각했을 것입니다. 그렇게 나쁘지는 않습니다 ... 어쩌면 ... 저는 MMIX와 MIPS도했고 그들의 "asm lang"은 x86보다 훨씬 낫습니다 (Q에 적합한 PoV이지만 아닐 수도 있습니다)
ShinTakezou

주소 지정 모드 문제는 80386에서 수정되었습니다. 16 비트 코드에만 제한된 주소 지정 모드가 있으며 32 비트 코드가 훨씬 좋습니다. 특수 접두사를 사용하여 16 비트 코드에서 32 비트 주소 지정 모드를 얻을 수 있으며 그 반대의 경우도 마찬가지입니다.
fuz

@FUZxxl : 예 ... 추악함이 대부분 16 비트 코드로 제한되어 있다고 언급 했어야했습니다 . 고정 (내 생각). :)
cHao

인식 된 비 우아함은 대부분 8086의 레지스터가 범용 레지스터라는 오해에서 비롯됩니다. 그것은 틀 렸습니다. 그들 각각은 특별한 목적을 가지고 있으며 그들의 목적을 고수하지 않으면 나쁜 시간을 보낼 것입니다.
fuz

3

나는 전문가는 아니지만 사람들이 좋아하지 않는 많은 기능이 성능이 좋은 이유 일 수 있습니다. 몇 년 전에는 레지스터 (스택 대신), 레지스터 프레임 등이 아키텍처를 인간에게 더 단순하게 보이게하는 좋은 솔루션으로 간주되었습니다. 그러나 요즘 중요한 것은 캐시 성능이며 x86의 가변 길이 단어를 사용하면 캐시에 더 많은 명령을 저장할 수 있습니다. 반대자들이 한때 칩의 절반을 차지했다고 지적했던 "명령 디코딩"은 더 이상 그렇게 많이되지 않습니다.

저는 병렬 처리가 오늘날 가장 중요한 요소 중 하나라고 생각합니다. 적어도 이미 사용할 수있을만큼 충분히 빠르게 실행되는 알고리즘의 경우입니다. 소프트웨어에서 높은 병렬성을 표현하면 하드웨어가 메모리 대기 시간을 분할 (또는 완전히 숨길 수 있음) 할 수 있습니다. 물론 더 먼 미래의 아키텍처는 아마도 양자 컴퓨팅과 같은 것입니다.

nVidia로부터 Intel의 실수 중 하나는 바이너리 형식을 하드웨어에 가깝게 유지했다는 것입니다. CUDA의 PTX는 빠른 레지스터 사용 계산 (그래프 색상)을 수행하므로 nVidia는 스택 머신 대신 레지스터 머신을 사용할 수 있지만 여전히 모든 오래된 소프트웨어를 손상시키지 않는 업그레이드 경로를 가지고 있습니다.


9
RISC는 인간 개발자를 염두에두고 설계되지 않았습니다. RISC이면의 아이디어 중 하나는 어셈블리를 작성한 사람, 이상적으로는 컴파일러에게 칩의 복잡성을 덜어주는 것이 었습니다. 레지스터가 많을수록 메모리 사용량이 적고 명령어 간의 종속성이 줄어들어 더 깊은 파이프 라인과 더 높은 성능이 가능합니다. x86-64에는 x86보다 두 배 많은 일반 레지스터가 있으며 이것만으로도 상당한 성능 향상을 가져옵니다. 그리고 대부분의 x86 칩에 대한 명령은 캐시 된 후가 아니라 캐시되기 전에 디코딩됩니다 (크기는 여기서 중요하지 않습니다).
Dietrich Epp

3
@Dietrich Epp : 전적으로 사실이 아닙니다. x86-64는 ISA에서 더 많은 레지스터를 볼 수 있지만 최신 x86 구현에는 일반적으로 실행 속도를 높이기 위해 ISA의 레지스터에 매핑되는 RISC 스타일 레지스터 파일이 있습니다.
Billy ONeal 2010

"nVidia로부터 인텔의 실수 중 하나가 바이너리 형식을 하드웨어에 가깝게 유지했다는 사실을 들었습니다." -나는 이것과 CUDA의 PTX 부분을 얻지 못했습니다.
claws

1
@Dietrech Epp : "대부분의 x86 칩에 대한 명령은 캐시 된 후가 아니라 캐시되기 전에 디코딩됩니다."사실이 아닙니다. 디코딩되기 전에 캐시됩니다. Pentium 4에는 디코딩 후 캐시 된 추가 추적 캐시가 있다고 생각하지만 중단되었습니다.
Nathan Fellman

사실이 아닙니다. 최신 "샌디 브리지"프로세서는 일종의 추적 캐시 (예 : 펜티엄 4의 경우, 오 그 늙은 소년 : D)를 사용하므로 기술이 사라지고 다시 돌아옵니다 ...
Quonux

3

사람들이 이미 언급 한 이유 외에도 :

  • x86-16은 하나의 메모리 위치를 최대 4096 개의 다른 방식으로 주소 지정하고 RAM을 1MB로 제한하고 프로그래머가 두 가지 다른 크기의 포인터를 처리하도록 하는 다소 이상한 메모리 주소 지정 체계 를 가졌 습니다. 다행히도 32 비트로의 이동으로 인해이 기능이 불필요 해졌지만 x86 칩은 여전히 ​​세그먼트 레지스터를 가지고 있습니다.
  • 동안하지 않는 오류 86 자체 , 86 호출 규칙은 (MS-DOS는 어떤 컴파일러와 함께 제공되지 않은 주로하기 때문에)의 혼란으로 우리를 떠나 있었다 MIPS와 같은 표준화되지 않은 __cdecl, __stdcall, __fastcall, 등

흠 .. x86 경쟁자를 생각할 때 MIPS는 생각하지 않습니다. ARM 또는 PowerPC 아마도 ....
Billy ONeal

@Billy : x86은 거의 영원히 존재했습니다. 한때 MIPS는 x86 경쟁자였습니다. x86은 MIPS와 경쟁 할 수있는 수준에 도달하기 위해 작업을 잘 랐던 것을 기억합니다. (MIPS와 SPARC가 워크 스테이션 분야에서 싸우고있을 때 돌아 왔습니다.)
Shannon Severance

@Shannon Severance : 한때 어떤 것이 있었다고해서 그것이 의미하는 것은 아닙니다.
Billy ONeal

2
@supercat : 플랫 x86-32 메모리 모델 시대의 사람들이 잊는 경향이있는 것은 16 비트는 64k의 메모리를 의미한다는 것입니다. 순진한 프로그래머에 대한 심한 처벌). 64k를 처리하는 방법은 거의 없지만 8086 솔루션은 좋은 타협이었습니다.
올로프 Forshell

2
@OlofForshell : 많은 사람들이 8086이 68000 (16MB의 선형 주소 지정 공간과 4 기가의 명확한 경로를 가지고 있음)만큼 좋지 않다는 사실을 한탄했다고 생각합니다. 확실히 32 비트 프로세서를 사용하면 64K 이상에 쉽게 액세스 할 수 있지만 8086은 8 비트 8080에서 한 단계 더 발전하도록 설계된 16 비트 아키텍처입니다. 인텔이 도약해야 할 이유가 없습니다. 8 비트에서 32 비트로 직접.
supercat 2013-06-12

3

x86을 대상으로하는 컴파일러를 작성하려고 시도하거나 x86 머신 에뮬레이터를 작성하거나 하드웨어 디자인에서 ISA를 구현하려고 시도하는 경우에도 답의 일부를 얻을 수있을 것이라고 생각합니다.

나는 "x86이 추하다"는 것을 이해하지만 MIPS (예를 들어)보다 x86 어셈블리를 작성 하는 것이 더 재미 있다고 생각합니다 . 후자는 지루합니다. 그것은 항상 인간보다는 컴파일러에게 좋은 것을 의미했습니다. 시도하면 칩이 컴파일러 작성자에게 더 적대적 일 수 있을지 모르겠습니다.

저에게 가장 추악한 부분은 (실제 모드) 분할이 작동하는 방식입니다. 모든 물리적 주소에는 4096 개의 segment : offset 별칭이 있습니다. 언제 마지막으로 필요 했습니까? 세그먼트 부분이 32 비트 주소의 고차 비트 였다면 상황이 훨씬 더 간단했을 것입니다.


m68k는 x86 (많은 m68k 프로그래머에게 그렇게 "인간적"으로 보일 수 없음)보다 훨씬 더 재미 있고 인간에게 좋습니다.
ShinTakezou 2010 년

segment : offset 주소 지정은 CP / M 세계와 어느 정도 호환성을 유지하려는 시도였습니다. 최악의 결정 중 하나입니다.
Turing Complete

@Turing Complete : segment : offset은 주로 CP / M 세계와의 호환성을 유지하려는 시도가 아닙니다. 16 비트 프로세서가 코드, 데이터, 스택 및 기타 메모리 영역을 서로 다른 세그먼트에 배치하여 64KB 이상을 처리 할 수 ​​있도록하는 것은 매우 성공적인 시도였습니다.
Olof Forshell 2011 년

1
실제로 데이터와 스택을 서로 다른 세그먼트에 배치하는 것은 C에게는 전혀 쓸모가 없었습니다. asm에만 사용할 수있었습니다. C에서 포인터는 저장 기간이 정적, 자동 또는 동적으로 할당 된 데이터를 가리킬 수 있으므로 세그먼트를 제거 할 방법이 없습니다. Pascal이나 Fortran 등에 유용했을 수도 있지만, 당시 이미 지배적 인 언어였던 C에게는 유용하지 않았을 수도 있습니다.
R .. GitHub STOP HELPING ICE

2
@Bernd : fs / gs가 스레드 로컬 저장소로 선택된 이유는 세그먼트 레지스터가 이에 적합하지 않기 때문입니다. x86이 레지스터에 대해 심각하게 고갈되고 세그먼트 레지스터가 사용되지 않은 것입니다. 스레드 구조를 가리키는 범용 레지스터도 마찬가지로 작동했을 것입니다. 실제로 레지스터가 더 많은 많은 RISC 시스템은 스레드 포인터로 하나를 사용합니다.
R .. GitHub STOP HELPING ICE

1
  1. x86에는 매우 제한된 범용 레지스터 세트가 있습니다.

  2. 효율적인로드 / 스토어 방법론 대신 가장 낮은 수준 (CISC 지옥)에서 매우 비효율적 인 개발 스타일을 장려합니다.

  3. 인텔은 아주 어리석은 세그먼트 / 오프셋-메모리 주소 지정 모델을 도입하여 (현재 이미!) 오래된 기술과 호환되도록 끔찍한 결정을 내 렸습니다.

  4. 모두가 32 비트를 사용하던 당시 x86은 빈약 한 16 비트 (대부분-8088-8 비트 외부 데이터 경로 만있는 경우에도 더 무섭습니다!) CPU로 주류 PC 세계를 막았습니다.


저에게는 (그리고 저는 개발자의 관점에서 모든 세대의 PC를 본 DOS 베테랑입니다!) 포인트 3은 최악이었습니다.

90 년대 초 (주류!)에 있었던 다음과 같은 상황을 상상해보십시오.

a) 레거시 이유로 미친 제한이있는 운영 체제 (쉽게 액세스 할 수있는 640kB의 RAM)-DOS

b) RAM 측면에서 더 많은 작업을 수행 할 수있는 운영 체제 확장 (Windows)이지만 게임 등의 경우에는 제한적이며 지구상에서 가장 안정적인 것은 아닙니다. 여기에서 90 년대 초반에 대해 이야기하고 있습니다)

c) 대부분의 소프트웨어는 여전히 DOS였으며 일부 프로그램은 좋아하고 다른 프로그램은 싫어하는 EMM386.exe가 있었기 때문에 특수 소프트웨어를위한 부팅 디스크를 자주 만들어야했습니다 (특히 게이머-이 당시에는 AVID 게이머였습니다. 여기에 대해 이야기하고 있습니다)

d) 우리는 MCGA 320x200x8 비트로 제한되었습니다 (좋아, 특별한 트릭으로 조금 더 있었지만 360x480x8은 가능했지만 런타임 라이브러리 지원없이 만 가능), 다른 모든 것은 지저분하고 끔찍했습니다 ( "VESA"-lol).

e) 그러나 하드웨어 측면에서 우리는 최대 1024x768을 지원하는 몇 메가 바이트의 RAM과 VGA 카드가있는 32 비트 시스템을 사용했습니다.

이 나쁜 상황의 이유는 무엇입니까?

인텔의 단순한 디자인 결정. 기계 명령어 수준 (바이너리 수준이 아님!)이 이미 죽어가는 것에 대한 호환성은 8085라고 생각합니다. 다른 겉보기에 관련되지 않은 문제 (그래픽 모드 등)는 기술적 인 이유와 매우 좁기 때문에 관련되었습니다. x86 플랫폼이 그 자체로 가져온 마음이있는 아키텍처.

오늘날 상황은 다르지만 어셈블러 개발자 나 x86 용 컴파일러 백엔드를 빌드하는 사람에게 문의하십시오. 엄청나게 적은 수의 범용 레지스터는 끔찍한 성능 킬러 일뿐입니다.


8086 세그먼트 아키텍처의 유일한 주요 문제점은 비 전용 세그먼트 레지스터 (ES)가 하나 뿐이고 프로그래밍 언어가이를 효과적으로 작동하도록 설계되지 않았다는 것입니다. 사용하는 확장 주소 지정 스타일은 객체가 임의의 주소에서 시작할 수 있다고 기대하지 않는 객체 지향 언어에서 매우 잘 작동합니다 (단락 경계에서 객체를 정렬하는 경우 객체 참조는 4). 초기 매킨토시 코드를 PC 코드와 비교해 보면 8086은 실제로 68000에 비해 꽤 괜찮아 보입니다.
supercat

@supercat : 실제로 es 레지스터는 무언가, 즉 저장 (movs, stos) 또는 스캔 (cmps 및 scas)이 필요한 문자열 명령어 전용 WAS입니다. 모든 세그먼트 레지스터에서 64KiB 주소 지정이 주어지면 코드, 데이터 및 스택 메모리 (cs, ds, ss) 이외의 메모리에 대한 "누락 된 링크"도 제공되었습니다. 세그먼트 레지스터는 레지스터의 64Kib 메모리 블록 외부에서 주소를 지정할 수 없다는 점에서 일종의 메모리 보호 체계를 제공했습니다. x86이 16 비트 아키텍처 였고 그날의 리소그래피 제약을 감안할 때 어떤 더 나은 솔루션을 제안 하시겠습니까?
Olof Forshell 2016

@OlofForshell : ES는 문자열 명령어에 사용되었지만이를 사용하지 않는 코드에 대해 커밋되지 않은 레지스터로 사용할 수 있습니다. 너무 많은 opcode 공간을 요구하지 않고 seg-reg 병목 현상을 완화하는 방법은 "rseg"접두사를 사용하여 다음 r / m-format 명령어에 대해 "r"필드가 CS / SS / DS에서 선택하도록 지정하는 것입니다. / ES / FS / GS / ?? / ?? AX / BX / CX / DX / SI / DI / SP / BP 대신 FS / GS에 대한 접두사와 LFS 및 LGS (LDS 및 LES와 같은)에 대한 지침을 갖습니다. 8086의 마이크로 아키텍처가 어떻게 배치되었는지는 모르겠지만 그와 같은 것이 효과가있을 수 있다고 생각합니다.
supercat

@supercat : 내가 썼 듯이, "레지스터는 또한 ... 이외의 메모리에 대한 누락 된 링크를 제공합니다."Fs와 gs는 내가 기억하는 것처럼 386이 될 때까지 도착하지 않았습니다.
Olof Forshell 2016

1
@OlofForshell : 그렇게하지 않았기 때문에 80286 아키텍처는 대부분의면에서 8086 아키텍처보다 더 나빠졌습니다. 내 요점은 세그먼트 레지스터를 몇 개 더 추가하면 (또는 하나라도) 8086 아키텍처를 훨씬 더 유용하게 만들 수 있으며, 세그먼트 레지스터가 다음과 같이 액세스 할 수 있다면 명령어 세트가 더 깨끗하고 유용 할 수 있다는 것입니다. 다른 것들.
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.