에뮬레이터는 어떻게 작동하고 어떻게 작성되나요?[닫은]

StackOverflow https://stackoverflow.com/questions/448673

  •  19-08-2019
  •  | 
  •  

문제

에뮬레이터는 어떻게 작동하나요?NES/SNES 또는 C64 에뮬레이터를 보면 깜짝 놀랐습니다.

http://www.tommowalker.co.uk/snemzelda.png

특정 조립 지침을 해석하여 해당 기계의 프로세서를 에뮬레이트해야 합니까?또 무엇이 들어가나요?일반적으로 어떻게 설계됩니까?

에뮬레이터(특히 게임 시스템) 작성에 관심이 있는 사람에게 조언을 해주실 수 있나요?

도움이 되었습니까?

해결책

에뮬레이션은 다면적인 영역입니다.기본 아이디어와 기능적 구성 요소는 다음과 같습니다.여러 부분으로 나누고 편집을 통해 세부 사항을 채울 예정입니다.내가 설명할 많은 내용에는 프로세서의 내부 작동에 대한 지식이 필요합니다. 즉, 어셈블리 지식이 필요합니다.특정 사항에 대해 제가 너무 모호한 경우 이 답변을 계속 개선할 수 있도록 질문해 주세요.

기본 아이디어:

에뮬레이션은 프로세서와 개별 구성 요소의 동작을 처리하여 작동합니다.시스템의 각 개별 부분을 구축한 다음 하드웨어에서 전선을 연결하는 것처럼 해당 부분을 연결합니다.

프로세서 에뮬레이션:

프로세서 에뮬레이션을 처리하는 방법에는 세 가지가 있습니다.

  • 해석
  • 동적 재컴파일
  • 정적 재컴파일

이러한 모든 경로의 전반적인 목표는 동일합니다.코드 조각을 실행하여 프로세서 상태를 수정하고 '하드웨어'와 상호 작용합니다.프로세서 상태는 특정 프로세서 대상에 대한 프로세서 레지스터, 인터럽트 핸들러 등의 집합체입니다.6502의 경우 레지스터를 나타내는 여러 개의 8비트 정수가 있습니다. A, X, Y, P, 그리고 S;16비트도 있을 거예요 PC 등록하다.

통역은 다음과 같이 시작됩니다. IP (명령 포인터 -라고도 함 PC, 프로그램 카운터) 메모리에서 명령어를 읽습니다.코드는 이 명령어를 구문 분석하고 이 정보를 사용하여 프로세서에서 지정한 대로 프로세서 상태를 변경합니다.해석의 핵심 문제는 다음과 같습니다. 매우 느린;주어진 명령어를 처리할 때마다 이를 디코딩하고 필요한 작업을 수행해야 합니다.

동적 재컴파일을 사용하면 해석과 마찬가지로 코드를 반복하지만 단지 opcode를 실행하는 대신 작업 목록을 작성합니다.분기 명령에 도달하면 이 작업 목록을 호스트 플랫폼용 기계어 코드로 컴파일한 다음 이 컴파일된 코드를 캐시하고 실행합니다.그런 다음 주어진 명령 그룹을 다시 누르면 캐시에서 코드를 실행하기만 하면 됩니다.(그런데 대부분의 사람들은 실제로 명령어 목록을 작성하지 않고 즉석에서 기계어 코드로 컴파일합니다. 이로 인해 최적화가 더 어려워지지만 충분한 사람들이 관심을 갖지 않는 한 이 답변의 범위를 벗어납니다.)

정적 재컴파일을 사용하면 동적 재컴파일과 동일한 작업을 수행하지만 분기를 따릅니다.결국에는 프로그램의 모든 코드를 나타내는 코드 덩어리를 구축하게 되며, 그런 다음 추가 간섭 없이 실행할 수 있습니다.다음과 같은 문제가 없다면 이는 훌륭한 메커니즘이 될 것입니다.

  • 처음부터 프로그램에 없는 코드(예:압축, 암호화, 런타임 시 생성/수정 등)은 다시 컴파일되지 않으므로 실행되지 않습니다.
  • 주어진 바이너리에서 모든 코드를 찾는 것은 다음과 동일하다는 것이 입증되었습니다. 정지 문제

이러한 것들이 결합되어 99%의 경우 정적 재컴파일이 완전히 불가능해집니다.더 많은 정보를 얻기 위해 Michael Steil이 정적 재컴파일에 대해 훌륭한 연구를 수행했습니다. 제가 본 것 중 최고였습니다.

프로세서 에뮬레이션의 또 다른 측면은 하드웨어와 상호 작용하는 방식입니다.여기에는 실제로 두 가지 측면이 있습니다.

  • 프로세서 타이밍
  • 인터럽트 처리

프로세서 타이밍:

특정 플랫폼, 특히 NES, SNES 등과 같은 구형 콘솔의 경우 에뮬레이터가 완전히 호환되기 위해서는 엄격한 타이밍이 필요합니다.NES에는 CPU가 정확한 순간에 메모리에 픽셀을 넣어야 하는 PPU(픽셀 처리 장치)가 있습니다.해석을 사용하면 쉽게 주기를 계산하고 적절한 타이밍을 에뮬레이션할 수 있습니다.동적/정적 재컴파일을 사용하면 상황이 /많이/ 더 복잡해집니다.

인터럽트 처리:

인터럽트는 CPU가 하드웨어와 통신하는 기본 메커니즘입니다.일반적으로 하드웨어 구성 요소는 CPU에 관심 있는 인터럽트를 알려줍니다.이는 매우 간단합니다. 코드에서 특정 인터럽트가 발생하면 인터럽트 핸들러 테이블을 보고 적절한 콜백을 호출합니다.

하드웨어 에뮬레이션:

특정 하드웨어 장치를 에뮬레이트하는 데는 두 가지 측면이 있습니다.

  • 장치의 기능을 에뮬레이션
  • 실제 장치 인터페이스 에뮬레이션

하드 드라이브의 경우를 예로 들어 보겠습니다.기능은 백업 스토리지, 읽기/쓰기/포맷 루틴 등을 생성하여 에뮬레이션됩니다.이 부분은 일반적으로 매우 간단합니다.

장치의 실제 인터페이스는 좀 더 복잡합니다.이는 일반적으로 메모리 매핑된 레지스터의 조합입니다(예:장치가 신호를 보내기 위해 변경 사항을 감시하는 메모리 부분) 및 인터럽트.하드 드라이브의 경우 읽기 명령, 쓰기 등을 배치한 다음 이 데이터를 다시 읽는 메모리 매핑 영역이 있을 수 있습니다.

더 자세히 설명하고 싶지만 사용할 수 있는 방법은 백만 가지가 있습니다.여기에 구체적인 질문이 있는 경우 언제든지 문의해 주시면 정보를 추가해 드리겠습니다.

자원:

나는 여기서 꽤 좋은 소개를 했다고 생각하지만, 추가 영역.어떤 질문이라도 기꺼이 도와드리겠습니다.나는 단지 엄청난 복잡성으로 인해 이 대부분에 대해 매우 모호했습니다.

필수 Wikipedia 링크:

일반 에뮬레이션 리소스:

  • 소발 -- 여기가 제가 에뮬레이션을 시작한 곳입니다. 먼저 에뮬레이터를 다운로드하고 결국 엄청난 양의 문서 아카이브를 약탈했습니다.이것은 당신이 가질 수 있는 최고의 자원입니다.
  • NGEmu -- 직접적인 리소스는 많지 않지만 포럼은 타의 추종을 불허합니다.
  • RomHacking.net -- 문서 섹션에는 널리 사용되는 콘솔의 기계 아키텍처에 관한 리소스가 포함되어 있습니다.

참조할 에뮬레이터 프로젝트:

  • 아이언바벨 -- Nemerle로 작성되었으며 코드를 즉시 C#으로 다시 컴파일하는 .NET용 에뮬레이션 플랫폼입니다.부인 성명:이것은 내 프로젝트이므로 뻔뻔한 플러그를 용서하십시오.
  • BSnes -- 완벽한 주기 정확도를 목표로 하는 멋진 SNES 에뮬레이터입니다.
  • 마메 -- 그만큼 아케이드 에뮬레이터.훌륭한 참고 자료입니다.
  • 6502asm.com -- 이것은 멋진 작은 포럼이 있는 JavaScript 6502 에뮬레이터입니다.
  • 다이나렉'd 6502asm -- 이것은 제가 하루나 이틀에 걸쳐 수행한 작은 해킹입니다.저는 6502asm.com의 기존 에뮬레이터를 가져와 엄청난 속도 향상을 위해 코드를 JavaScript로 동적으로 다시 컴파일하도록 변경했습니다.

프로세서 재컴파일 참조:

  • Michael Steil(위에서 참조)이 수행한 정적 재컴파일에 대한 연구는 다음과 같이 정점을 이루었습니다. 이 종이 소스 등을 찾을 수 있습니다 여기.

부록:

이 답변이 제출된 지 1년이 훨씬 넘었고 많은 관심을 받아 이제 몇 가지 사항을 업데이트해야 할 때라고 생각했습니다.

아마도 지금 에뮬레이션에서 가장 흥미로운 점은 libcpu, 앞서 언급한 Michael Steil에 의해 시작되었습니다.재컴파일(정적 및 동적!)을 위해 LLVM을 사용하는 다수의 CPU 코어를 지원하기 위한 라이브러리입니다.엄청난 잠재력을 갖고 있으며 에뮬레이션에 큰 도움이 될 것이라고 생각합니다.

에뮤 문서 또한 에뮬레이션 목적에 매우 유용한 시스템 문서의 훌륭한 저장소를 보유하고 있다는 사실이 내 관심을 끌었습니다.나는 거기에서 많은 시간을 보내지 않았지만 거기에는 훌륭한 자원이 많이 있는 것 같습니다.

이 게시물이 도움이 되어 기쁘고, 올해 말/내년 초까지 해당 주제에 대한 책을 마무리할 수 있기를 바랍니다.

다른 팁

빅터 모야 델 바리오 (Victor Moya del Barrio)라는 사람 이이 주제에 대한 논문을 썼습니다. 152 페이지에 대한 많은 좋은 정보. PDF를 다운로드 할 수 있습니다 여기.

등록하고 싶지 않은 경우 scribd, PDF 타이틀은 Google을 할 수 있습니다. "에뮬레이션 프로그래밍 기술에 대한 연구". PDF에는 몇 가지 다른 소스가 있습니다.

에뮬레이션은 어려워 보일 수 있지만 실제로 시뮬레이션하는 것보다 매우 쉽습니다.

모든 프로세서에는 일반적으로 상태, 상호 작용 등을 설명하는 잘 작성된 사양이 있습니다.

성능에 전혀 신경 쓰지 않으면 매우 우아한 객체 지향 프로그램을 사용하여 가장 오래된 프로세서를 쉽게 모방 할 수 있습니다. 예를 들어, X86 프로세서는 레지스터 상태 (Easy), 메모리 상태를 유지하기위한 것 (Easy) 및 각각의 사령부를 취하고 기계의 현재 상태에 적용 할 수있는 무언가가 필요합니다. 정확도를 원한다면 메모리 번역, 캐싱 등을 모방 할 수 있지만 가능합니다.

실제로, 많은 마이크로 칩 및 CPU 제조업체는 칩의 에뮬레이터와 칩 자체에 대한 프로그램을 테스트하여 칩 사양 또는 하드웨어에서 칩의 실제 구현에 문제가 있는지 알아내는 데 도움이됩니다. 예를 들어, 교착 상태를 일으킬 수있는 칩 사양을 작성할 수 있으며 하드웨어에서 마감일이 발생하면 칩 구현의 무언가보다 더 큰 문제를 나타내므로 사양에서 재생할 수 있는지 확인하는 것이 중요합니다.

물론, 비디오 게임을위한 에뮬레이터는 일반적으로 성능에 관심이 있으므로 순진한 구현을 사용하지 않으며 예를 들어 드로잉 및 사운드를 사용하기 위해 호스트 시스템의 OS와 인터페이스하는 코드도 포함됩니다.

오래된 비디오 게임 (NES/SNE 등)의 매우 느린 성능을 고려할 때 현대 시스템에서는 에뮬레이션이 매우 쉽습니다. 사실, 모든 SNES 게임이나 Atari 2600 게임 세트를 다운로드 할 수 있다는 것은 훨씬 더 놀랍습니다. 이러한 시스템이 모든 카트리지에 무료로 액세스 할 수 있었을 때 모든 카트리지에 자유롭게 액세스 할 수 있다는 점을 고려하면 꿈이 이루어 졌을 것입니다.

나는이 질문이 조금 늙었다는 것을 알고 있지만 토론에 무언가를 추가하고 싶습니다. 여기에서 대부분의 답변은 에뮬레이터를 중심으로 이들이 모방 한 시스템의 기계 지침을 해석합니다.

그러나 "Ultrahle"이라고하는 매우 잘 알려진 예외가 있습니다.위키 백과 기사). 지금까지 만든 가장 유명한 에뮬레이터 중 하나 인 Ultrahle은 상업용 Nintendo 64 게임 (홈 컴퓨터에서 괜찮은 성능을 가진)을 널리 알려지지 않았을 때 널리 알려진 것으로 간주되었습니다. 사실, Nintendo는 Ultrahle이 만들어 졌을 때 Nintendo 64의 새로운 타이틀을 제작했습니다!

처음으로, 나는 이전에 인쇄 잡지의 에뮬레이터에 관한 기사를 보았습니다.

Ultrahle의 개념은 기계 레벨 호출 대신 C 라이브러리 통화를 에뮬레이션하여 불가능한 것을 가능하게하는 것이 었습니다.

볼만한 가치가있는 것은 Imran Nazar의 글쓰기 시도입니다. 게임 보이 JavaScript의 에뮬레이터.

80 년대의 BBC 마이크로 컴퓨터 (Google에 vbeeb를 입력)의 나만의 에뮬레이터를 만들었을 때 알아야 할 사항이 많이 있습니다.

  • 당신은 실제를 모방하지 않고 복제품이 될 것입니다. 대신, 당신은 에뮬레이션입니다 상태. 좋은 예는 계산기, 실제 물건에는 버튼, 화면, 케이스 등이 있습니다. 그러나 계산기를 모방하려면 버튼이 위 또는 아래에 있는지 여부를 모방하면 LCD의 세그먼트가 켜져 있는지 등을 모방해야합니다. 기본적으로 숫자 세트. 계산기에서 변경할 수있는 모든 가능한 조합을 나타냅니다.
  • 실제처럼 나타나고 행동하려면 에뮬레이터의 인터페이스 만 있으면됩니다. 이것이 더 설득력이 높을수록 에뮬레이션이 더 가까워집니다. 무대 뒤에서 일어나는 일은 당신이 좋아하는 것일 수 있습니다. 그러나 에뮬레이터를 쉽게 작성하기 위해 실제 시스템, 즉 칩, 디스플레이, 키보드, 회로 보드 및 추상 컴퓨터 코드 사이에 정신적 매핑이 발생합니다.
  • 컴퓨터 시스템을 모방하려면 더 작은 청크로 분해하고 해당 청크를 개별적으로 모방하는 것이 가장 쉽습니다. 그런 다음 완제품을 위해 전체를 함께 묶습니다. 입력 및 출력이있는 블랙 박스 세트와 마찬가지로 객체 지향 프로그래밍에 아름답게 적합합니다. 이 덩어리를 더 세분화하여 삶을 더 쉽게 만들 수 있습니다.

실제로 말하면, 당신은 일반적으로 에뮬레이션의 속도와 충실도를 위해 글을 쓰려고합니다. 이는 대상 시스템의 소프트웨어가 소스 시스템의 원래 하드웨어보다 더 느리게 실행되기 때문입니다. 이는 프로그래밍 언어, 컴파일러, 대상 시스템 등의 선택을 제한 할 수 있습니다.
또한 마이크로 프로세서에서 트랜지스터의 전압 상태를 모방 할 필요는 없지만 마이크로 프로세서의 레지스터 세트의 상태를 모방해야 할 필요는 없을 것입니다.
일반적으로 에뮬레이션의 세부 수준이 작을수록 원래 시스템에 더 충실도가 있습니다.
마지막으로, 이전 시스템에 대한 정보는 불완전하거나 존재하지 않을 수 있습니다. 따라서 독창적 인 장비를 잡는 것이 필수적이거나 적어도 다른 사람이 쓴 또 다른 좋은 에뮬레이터를 떼어냅니다!

예, 전체 바이너리 머신 코드 혼란을 "손으로"해석해야합니다. 뿐만 아니라 대부분의 경우 대상 머신과 동등한 이국적인 하드웨어를 시뮬레이션해야합니다.

간단한 접근법은 지침을 하나씩 해석하는 것입니다. 잘 작동하지만 느립니다. 더 빠른 접근 방식은 재 컴파일 - 소스 머신 코드를 대상 기계 코드로 변환하는 것입니다. 대부분의 지침은 일대일로 매핑되지 않기 때문에 이것은 더 복잡합니다. 대신 추가 코드가 포함 된 정교한 작업 계좌를 만들어야합니다. 그러나 결국 그것은 훨씬 빠릅니다. 대부분의 현대 에뮬레이터 가이 작업을 수행합니다.

에뮬레이터를 개발할 때 시스템이 작동하는 프로세서 어셈블리 (Z80, 8080, PS CPU 등)를 해석하는 것입니다.

또한 시스템이 가지고있는 모든 주변 장치 (비디오 출력, 컨트롤러)를 모방해야합니다.

당신은 Good Old와 같은 Simpe 시스템의 에뮬레이터를 작성해야합니다. 게임 보이 (Z80 프로세서를 사용하는 것은 착각하지 않습니다) 또는 C64.

에뮬레이터는 시뮬레이션 해야하는 많은 해킹 (비정상적인 효과), 타이밍 문제 등이 있기 때문에 생성하기가 매우 어렵습니다.

이것의 예는 참조하십시오 http://queue.acm.org/detail.cfm?id=1755886.

또한 1MHz를 모방하기위한 멀티 GHZ CPU가 필요한 이유를 보여줍니다.

또한 Darek Mihocka 's를 확인하십시오 Emulators.com JIT에 대한 교육 수준 최적화 및 효율적인 에뮬레이터 구축에 대한 다른 많은 제품에 대한 훌륭한 조언.

나는 게임 콘솔을 모방하기 위해 멋진 일을 한 적이 없지만 Andrew Tanenbaums에 설명 된 기계의 에뮬레이터를 작성하는 과제가 한 번 코스를 수강했습니다. 구조화 된 컴퓨터 조직. 그것은 재미 있었고 나에게 많은 아하 순간을 주었다. 실제 에뮬레이터를 작성하기 전에 다이빙을하기 전에 그 책을 선택할 수 있습니다.

실제 시스템이나 자신의 물건을 모방하는 것에 대한 조언? 에뮬레이터가 전체 하드웨어를 에뮬레이션하여 작동한다고 말할 수 있습니다. 어쩌면 회로로 내려 가지 않을 수도 있습니다 (HW가하는 것처럼 비트가 움직이는 비트. 바이트를 움직이는 것이 최종 결과이므로 바이트를 복사하는 것이 좋습니다). 에뮬레이터는 시뮬레이션 해야하는 많은 해킹 (비정상적인 효과), 타이밍 문제 등이 있기 때문에 생성하기가 매우 어렵습니다. 하나 (입력) 조각이 잘못된 경우 전체 시스템이 아래로 수행하거나 버그/글리치를 가질 수 있습니다.

그만큼 공유 소스 장치 에뮬레이터 Buildable 소스 코드를 PocketPC/스마트 폰 에뮬레이터에 포함합니다 (Visual Studio, Windows에서 실행 필요). 이진 릴리스의 V1 및 V2에서 작업했습니다.

많은 에뮬레이션 문제를 해결합니다. - 게스트 가상에서 게스트 물리적으로 호스트 가상으로 효율적인 주소 변환 - 게스트 코드의 JIT 컴파일 - 호스트 키보드 및 마우스 용 네트워크 어댑터, 터치 스크린 및 오디오와 같은 주변 장치의 시뮬레이션 - 저장/ 저장/ 저장/ 저전력 모드에서 이력서 시뮬레이션을 위해 상태 복원

@Cody Brocious가 제공 한 답변을 추가합니다
새로운 시스템 (CPU, I/O 등)을 가상 시스템에 모방하는 가상화의 맥락에서 다음 범주의 에뮬레이터를 볼 수 있습니다.

해석 : Bochs는 통역사의 예이며, X86 PC 에뮬레이터이며, 게스트 시스템에서 각 명령어를 가져옵니다. 다른 명령어 (호스트 ISA)에서 의도 된 효과를 생성하기 위해 다른 명령어 세트로 번역합니다. 'T는 모든 명령이 동일한주기를 거치도록 모든 것을 캐시합니다.

동적 Emalator : QEMU는 동적 에뮬레이터입니다. 게스트 명령의 비행 번역에서도 결과를 캐시합니다. 가장 중요한 부분은 에뮬레이션이 더 빨라질 수 있도록 호스트 시스템에서 가능한 많은 지침을 실행한다는 것입니다. 또한 Cody가 언급했듯이 코드를 블록 (단일 실행 흐름)으로 나눕니다.

정적 에뮬레이터 : 가상화에 도움이 될 수있는 정적 에뮬레이터가 없다는 것을 알고 있습니다.

에뮬레이션을 시작하는 방법.

1. 저수준 프로그래밍을 기반으로 한 책을 섭취하면 Nintendo의 "척"운영 체제 ... 게임 보이 ...

2. 에뮬레이션에 관한 책을 구체적으로, 아마도 OS 개발. (당신은 OS를 만들지 않을 것이지만 가장 가까운 것입니다.

3. 일부 오픈 소스 에뮬레이터, 특히 에뮬레이터를 만들고 싶은 시스템의 일부를 살펴보십시오.

4. IDE/Compliler에 더 복잡한 코드의 코피 스 니펫. 이렇게하면 긴 코드를 작성하면 절약됩니다. 이것이 제가 OS 개발을 위해하는 일입니다. Linux 지구를 사용하십시오.

나는 에뮬레이션에 관한 기사를 썼다 JavaScript의 Chip-8 시스템.

시스템이 그다지 복잡하지 않기 때문에 시작하기에 좋은 곳이지만 여전히 Opcode, Stack, Registers 등이 어떻게 작동하는지 배우십시오.

나는 곧 NES를위한 더 긴 가이드를 쓸 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top