Może te materiały ci coś pomogą:
Film na YT o opcodach x86
https://www.youtube.com/watch?v=efxJP1ZNmf4&index=2&list=PLFA77B1208A54E4C9
Dokumentacja Intel x86. Patrz dokładniej na Rozdział 2, oraz APPENDIX A i B.
http://www.intel.pl/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
Jeżeli tworzysz maszynę wirtualną, to opcode jest poprostu liczbą reprezentującą instrukcję procesora. Może ona również zawierać jakieś argumenty dla instrukcji i/lub prefiksy.
Opcody w procesorach RISC (np. ARM, ale chyba tylko w tzw. trybie ARM. W trybie THUMB opcody chyba mogły już mieć zmienną wielkość, a JAZELLE już na pewno) chyba zazwyczaj mają opcody stałej wielkości. Coś takiego jest nieco prostrze w implementacji, ale kod zabiera więcej pamięci i potem może być ciężko rozszeżać instruction set.
W procesorach typu CISC (x86 nie jest typowym CISC, ale nadaje się jako przykład) zazwyczaj instrukcje mają zmienną długość. Przy interpretacji takiego opcodu procesor może np. najpierw wczytać pierwszy bajt i wtedy zdecydować, czy to cała instrukcja, czy potrzebuje kolejnego bajtu i tak dalej, aż wczyta całą instrukcję wraz z argumentami. Taki procesor jest nieco trudniejszy w implementacji, ale kod jest gęstrzy i łatwiej rozszeżać instruction set (bo nie jesteś ograniczony np. do 4 bajtów).