그러나 중복없는 니모닉에 대한 테이블을 저장하는 효율적인 방법은 없습니까?
이것은 알고리즘 및 데이터 구조 질문이되었습니다.
많은 opcode 테이블 항목 (최소한 0f
이스케이프 바이트가없는 테이블의 경우 : http://sparksandflames.com/files/x86InstructionChart.html)은 4 또는 2 그룹으로 반복됩니다. 즉, 동일한 6 또는 7 비트 접두어로 같은 연상 기호.
분명히 구조체의 256 개 항목 테이블은 간단하지만 중복됩니다. 매우 빠르며 사용하기 쉽습니다. 캐시 미스가 발생하지 않을 정도로 작기 때문입니다. (특히 공통 항목은 캐시에서 뜨거워 지므로 x86 코드는 동일한 연산 코드를 많이 사용합니다.)
공간에 단순 성과 성능을 교환 할 수 있습니다.
하나의 멤버가 낮은 2 비트으로 인덱싱 될 보조 테이블에 대한 포인터 인 구조의 64 개 항목 테이블을 가질 수 있습니다. 포인터가 NULL이면 명령어가 add
/and
/xor
/등의 패턴을 따르고 낮은 2 비트는 피연산자 크기와 방향 (r/m, reg 또는 reg, r/m).
구조체에는 특정 접두사가있는 경우 다른 지침 (예 : rep nop
은 pause
)으로 전환하기위한 항목이 필요합니다. 또한 AVX VEX 접두어는 다른 명령어의 잘못된 인코딩이었던 것을 사용합니다. x86은 현재의 모든 확장 기능에 대한 완전한 작업을 원한다면 디코딩하는 것이 아주 이상합니다.
실제로는 은 기능 포인터 테이블을 사용하는 것이 가장 간단하고 효율적일 수도 있습니다. 또는 const char* mnemonic
및 int (*decode)(const char*mnemonic, const char *insn_bytes, unsigned prefix_bitmap)
기능을 가진 구조체, 많은 opcodes 같은 디코딩 기능을 가리킬 수 있지만 여전히 다른 니모닉을 얻을 수 있습니다. 때때로 함수는 전달 된 니모 닉을 무시할 것이지만 필요한 다른 시간은 무시합니다. 많은 디코드 함수가 호출하는 어드레싱 모드를 디코딩하는 공통 기능을 갖게됩니다.
동적 재 컴파일을하는 대신 해석하는 x86 에뮬레이터를 구현하는 방법과 매우 비슷합니다. 일반적인 디코드 루프와 함수 포인터를 통한 디스 패칭. 당신이 사용할 수
이보다 더 복잡한 데이터 구조는 접두사 나무 일명 radix trie이다. https://en.wikipedia.org/wiki/Trie#Bitwise_tries을 참조하십시오.
밀도가 너무 높아 조회 테이블이 훨씬 더 의미가 있기 때문에 바보 같은 시즌에 접어 들고 있습니다.(정의되지 않은 opcode는 거의 없습니다.)
하단 2 비트도 opcode의 일부입니다. 예를 들어, ['jcc'] (http://felixcloutier.com/x86/Jcc.html) 명령어는 0x70에서부터 모든 opcode 값에 대해 다른 니모닉을 가지고 있습니다 0x7F. 실제로 ModR/M 바이트의'/ r' 필드가 opcode의 일부이기도합니다. (예 :'shl'과'shr'). –
최신 x86 기계어 코드의 문제점은 * 효율적/간단한 방법으로 디코딩 할 수 없다는 것입니다. 예를 들어'rep nop'은 실제로'pause'로 해독됩니다. 그렇지 않으면'rep bsf'가'tzcnt'로 해독됩니다 (BMI1이 지원되면 그렇지 않으면'bsf'로 해독됩니다). 따라서 다른 지침의 필수 접두어를 확인해야합니다. –
@PeterCordes 내가 사용했던 리소스 중 하나는 http://www.c-jump.com/CIS77/CPU/x86/X77_0050_add_opcode.htm opcode의 유일한 6 개의 MSB가 아닌 예외가 있다는 것을 알고 있습니다. 바이트는 무릎 관절염을 나타냅니다. 그러나 일반 지시의 경우에는 그들이 말하는대로이 방법으로 보입니다. 저는이 정규 사례에 대해 어떻게 이들 6 가지 MSB를 사용하여 예에서했던 것처럼 니모닉을 결정할 수 있는지 묻고 있습니다. – Jorayen