C++プログラマのためのアセンブラ入門(続き)

(一記事のサイズ制限を越えてしまうようなので分割。前回の続き)

情報処理の試験で使う casl 2 と comet 2 を実装してみましょう

実装例

#if	defined( _MSC_VER )
// C4351 : 新しい動作: 配列 '%1' の要素は既定で初期化されます
// C4917 : 'identifier' : GUID はクラス、インターフェイスまたは名前空間のみに関連付けることができます。
// C4571 : catch(...) の意味が Visual C++ 7.1 から変更されています。構造化例外 (SEH) はキャッチされません。
// C4514 : 'function' : 参照されていないインライン関数は削除されました。
// C4710 : 'function' : インライン関数ではありません。
#pragma	warning( disable : 4351 4917 4571 4514 4710 )
#include	<windows.h>
#endif // _MSC_VER
#include	<stdio.h>
#include	<stdarg.h>
#include	<vector>
#include	<algorithm>

#define	elementsizeof( a )	sizeof((a)[0])
#define	elementsof( a )	(sizeof((a))/elementsizeof((a)))

typedef signed char	signed_int8_t;
typedef unsigned char	unsigned_int8_t;
typedef signed short	signed_int16_t;
typedef unsigned short	unsigned_int16_t;
typedef signed int	signed_int32_t;
typedef unsigned int	unsigned_int32_t;

template<typename T> struct is_pointer {
	static const bool	value = false;
};
template<typename T> struct is_pointer<T*> {
	static const bool	value = true;
};
template<typename T> struct is_pointer<const T*> {
	static const bool	value = true;
};
template<typename T> struct is_integral {
	static const bool	value = false;
};
template<> struct is_integral<signed_int16_t> {
	static const bool	value = true;
};
template<> struct is_integral<unsigned_int16_t> {
	static const bool	value = true;
};
//template<> struct is_integral<int> {
//	static const bool	value = true;
//};
template<typename T> struct is_int16 {
	static const bool	value = false;
};
template<> struct is_int16<signed_int16_t> {
	static const bool	value = true;
};
template<> struct is_int16<unsigned_int16_t> {
	static const bool	value = true;
};
template<typename T> struct is_int32 {
	static const bool	value = false;
};
template<> struct is_int32<signed_int32_t> {
	static const bool	value = true;
};
template<> struct is_int32<unsigned_int32_t> {
	static const bool	value = true;
};
template<typename lhs, typename rhs> struct is_same {
	static const bool	value = false;
};
template<typename T> struct is_same<T,T> {
	static const bool	value = true;
};

struct enable_if_result_t {};
template<bool _conditional_value, typename _result_type = enable_if_result_t> struct enable_if_helper_t {};
template<typename _result_type> struct enable_if_helper_t<true,_result_type> { typedef _result_type	type; };
template<bool _conditional_value, typename _result_type = enable_if_result_t> struct enable_if : public enable_if_helper_t<_conditional_value,_result_type> {};
enable_if_result_t*	enabler = NULL;

union union_int16_t {
	unsigned_int16_t	x;
	unsigned_int8_t	h[2];
};
union union_int32_t {
	unsigned_int32_t	e;
	unsigned_int16_t	x[2];
	unsigned_int8_t	h[4];
};

enum register16_type {
	register16_type_gr0,
	register16_type_gr1,
	register16_type_gr2,
	register16_type_gr3,
	register16_type_gr4,
	register16_type_gr5,
	register16_type_gr6,
	register16_type_gr7,
	register16_type_sp,
	register16_type_pr,
	register16_type_fr,
	register16_types
};

struct register16_t {
	typedef unsigned_int16_t	value_type;
protected:
	register16_type	m_type;
	value_type	m_value;
	value_type	:16;
public:
	register16_type	type() const {
		return	m_type;
	}
	register16_t&	operator=( value_type	rhs ){
		m_value = rhs;
		return	*this;
	}
	operator const value_type&() const {
		return	m_value;
	}
	operator value_type&(){
		return	m_value;
	}
	explicit register16_t( register16_type	type ):
	m_type(type),
	m_value()
	{
	}
	register16_t&	operator=( const register16_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}

	// レジスタは必ずタイプを指定する
	register16_t() = delete;
	// レジスタをコピーして実体を作ることはない
	register16_t( const register16_t&	rhs ) = delete;
	// レジスタを移動して実体を作ることはない
	register16_t( register16_t&&	rhs ) = delete;
	// レジスタを移動することはない
	register16_t&	operator=( register16_t&&	rhs ) = delete;
};

#define	opcode_nop	0x00
#define	opcode_ld	0x10
#define	opcode_st	0x11
#define	opcode_lad	0x12
#define	opcode_adda	0x20
#define	opcode_addl	0x21
#define	opcode_suba	0x22
#define	opcode_subl	0x23
#define	opcode_and	0x30
#define	opcode_or	0x31
#define	opcode_xor	0x32
#define	opcode_cpa	0x40
#define	opcode_cpl	0x41
#define	opcode_sla	0x50
#define	opcode_sra	0x51
#define	opcode_sll	0x52
#define	opcode_srl	0x53
#define	opcode_jmi	0x61
#define	opcode_jnz	0x62
#define	opcode_jne	0x63
#define	opcode_jump	0x64
#define	opcode_jpl	0x65
#define	opcode_jov	0x66
#define	opcode_push	0x70
#define	opcode_pop	0x71
#define	opcode_call	0x80
#define	opcode_ret	0x81
#define	opcode_1	0x04	// 新しい形式: mnemonic r1, r2
#define	opcodes	256

#define	COMET2OP_BITSIZEOF_OPCODE	8
#define	COMET2OP_BITSIZEOF_GR		4
#define	COMET2OP_BITSIZEOF_XR		4
#define	COMET2OP_BITSIZEOF_ADDRESS	16

#define	COMET2OP16_BITOFFSETOF_OPCODE	(COMET2OP_BITSIZEOF_XR+COMET2OP_BITSIZEOF_GR)
#define	COMET2OP16_BITOFFSETOF_GR	(COMET2OP_BITSIZEOF_XR)
#define	COMET2OP16_BITOFFSETOF_XR	0
#define	COMET2OP16_GET_OPCODE( op )	(((op)>>COMET2OP16_BITOFFSETOF_OPCODE) & ((1<<COMET2OP_BITSIZEOF_OPCODE)-1))
#define	COMET2OP16_GET_GR( op )	(((op)>>COMET2OP16_BITOFFSETOF_GR) & ((1<<COMET2OP_BITSIZEOF_GR)-1))
#define	COMET2OP16_GET_XR( op )	(((op)>>COMET2OP16_BITOFFSETOF_XR) & ((1<<COMET2OP_BITSIZEOF_XR)-1))
#define	COMET2OP16_MAKE( opcode, gr, xr )	(static_cast<unsigned_int16_t>(((opcode)<<COMET2OP16_BITOFFSETOF_OPCODE)|((gr)<<COMET2OP16_BITOFFSETOF_GR)|((xr)<<COMET2OP16_BITOFFSETOF_XR)))

#define	COMET2OP32_BITOFFSETOF_OPCODE	COMET2OP16_BITOFFSETOF_OPCODE
#define	COMET2OP32_BITOFFSETOF_GR	COMET2OP16_BITOFFSETOF_GR
#define	COMET2OP32_BITOFFSETOF_XR	COMET2OP16_BITOFFSETOF_XR
#define	COMET2OP32_BITOFFSETOF_ADDRESS	(COMET2OP32_BITOFFSETOF_OPCODE+COMET2OP_BITSIZEOF_OPCODE)
#define	COMET2OP32_MAKE( opcode, gr, xr, addr )	(((opcode)<<COMET2OP32_BITOFFSETOF_OPCODE)|((gr)<<COMET2OP32_BITOFFSETOF_GR)|((xr)<<COMET2OP32_BITOFFSETOF_XR)|((addr)<<COMET2OP32_BITOFFSETOF_ADDRESS))
#define	COMET2OP32_GET_OPCODE( op )	(((op)>>COMET2OP32_BITOFFSETOF_OPCODE) & ((1<<COMET2OP_BITSIZEOF_OPCODE)-1))
#define	COMET2OP32_GET_GR( op )	(((op)>>COMET2OP32_BITOFFSETOF_GR) & ((1<<COMET2OP_BITSIZEOF_GR)-1))
#define	COMET2OP32_GET_XR( op )	(((op)>>COMET2OP32_BITOFFSETOF_XR) & ((1<<COMET2OP_BITSIZEOF_XR)-1))
#define	COMET2OP32_GET_ADDRESS( op )	(static_cast<unsigned_int32_t>(((op)>>COMET2OP32_BITOFFSETOF_ADDRESS) & ((1<<COMET2OP_BITSIZEOF_ADDRESS)-1))

class comet2op_t {
	const unsigned_int16_t*	m_pr;
public:
	unsigned_int16_t	opcode() const {
		return	( unsigned_int16_t )COMET2OP16_GET_OPCODE( m_pr[0] );
	}
	unsigned_int16_t	gr() const {
		return	( unsigned_int16_t )COMET2OP16_GET_GR( m_pr[0] );
	}
	unsigned_int16_t	xr() const {
		return	( unsigned_int16_t )COMET2OP16_GET_XR( m_pr[0] );
	}
	unsigned_int16_t	addr() const {
		return	m_pr[1];
	}
	comet2op_t( const unsigned_int16_t*	pr ):
	m_pr(pr)
	{
	}
};
class mnemonic_data_t : public std::vector<unsigned_int16_t> {
	unsigned_int32_t	m_is_data:1;
	unsigned_int32_t	:31;
	unsigned_int32_t	:32;
public:
	using std::vector<unsigned_int16_t>::push_back;
	template<typename T> void	push_back( T	s, typename enable_if<is_same<T,const char*>::value>::type* = 0 ){
		if( s ){
			while( *s ){
				push_back( static_cast<unsigned_int16_t>(*s));
				++s;
			}
		}
	}
	bool	is_data() const {
		return	m_is_data;
	}
	explicit mnemonic_data_t( size_t	cd, unsigned_int16_t	d0, va_list	ap ):
	std::vector<unsigned_int16_t>(),
	m_is_data(true)
	{
		push_back( d0 );
		for( size_t	n = 0; n < cd-1; ++n ){
			unsigned_int16_t	d = static_cast<unsigned_int16_t>(va_arg( ap, int ));
			push_back( d );
		}
	}
	explicit mnemonic_data_t( size_t	cd, const char*	d0, va_list	ap ):
	std::vector<unsigned_int16_t>(),
	m_is_data(true)
	{
		push_back( d0 );
		for( size_t	n = 0; n < cd-1; ++n ){
			const char*	d = va_arg( ap, const char* );
			push_back( d );
		}
	}
	template<typename T> explicit mnemonic_data_t( T	d, typename enable_if<is_int16<T>::value>::type* = 0 ):
	std::vector<unsigned_int16_t>(),
	m_is_data(false)
	{
		push_back( d );
	}
	template<typename T> explicit mnemonic_data_t( T	d, typename enable_if<is_int32<T>::value>::type* = 0 ):
	std::vector<unsigned_int16_t>(),
	m_is_data(false)
	{
		union_int32_t	temp = { d };
		push_back( temp.x[0] );
		push_back( temp.x[1] );
	}
	mnemonic_data_t():
	std::vector<unsigned_int16_t>(),
	m_is_data(false)
	{
	}
	mnemonic_data_t( const mnemonic_data_t&	rhs ):
	std::vector<unsigned_int16_t>(rhs),
	m_is_data(rhs.m_is_data)
	{
	}
	mnemonic_data_t&	operator=( const mnemonic_data_t&	rhs ){
		if( this != &rhs ){
			std::vector<unsigned_int16_t>::operator=(rhs);
			m_is_data = rhs.m_is_data;
		}
		return	*this;
	}
};
class mnemonic_t : public mnemonic_data_t {
protected:
	signed_int16_t*	m_addr;
public:
	operator unsigned_int32_t() const {
		return	COMET2OP32_MAKE(opcode(),gr(),xr(),addr());
	}
	unsigned_int32_t	opcode() const {
		return	( unsigned_int32_t )COMET2OP16_GET_OPCODE( (*this)[0] );
	}
	unsigned_int32_t	gr() const {
		return	( unsigned_int32_t )COMET2OP16_GET_GR( (*this)[0] );
	}
	unsigned_int32_t	xr() const {
		return	( unsigned_int32_t )COMET2OP16_GET_XR( (*this)[0] );
	}
	unsigned_int32_t	addr() const {
		return	m_addr ? static_cast<unsigned_int32_t>(*m_addr) : static_cast<unsigned_int32_t>((*this)[1]);
	}
	bool	read( unsigned_int16_t*	data, size_t	celt_data, size_t*	pcelt_read ) const {
		bool	success = true;
		size_t	celt_read = 0;
		if( !data ||( celt_data < size())){
			success = false;
		}
		if( success ){
			if(( size() == 2 )&& !is_data() && !xr()){
				union_int32_t	temp = { *this };
				data[celt_read] = temp.x[0];
				++celt_read;
				data[celt_read] = temp.x[1];
				++celt_read;
			}
			else{
				for( const_iterator	p = begin(); p != end(); ++p ){
					data[celt_read] = *p;
					++celt_read;
				}
			}
		}
		if( pcelt_read ){
			*pcelt_read = celt_read;
		}
		return	success;
	}
	mnemonic_t&	operator=( const mnemonic_t&	rhs ){
		if( this != &rhs ){
			mnemonic_data_t::operator=( rhs );
			m_addr = rhs.m_addr;
		}
		return	*this;
	}
	mnemonic_t( const mnemonic_t&	rhs ):
	mnemonic_data_t(rhs),
	m_addr(rhs.m_addr)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode ):
	mnemonic_data_t(COMET2OP16_MAKE(opcode,0,0)),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr ):
	mnemonic_data_t(COMET2OP16_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0)),
	m_addr(NULL)
	{
	}
	template<typename T> explicit mnemonic_t( unsigned_int32_t	opcode, T	addr, typename enable_if<is_integral<T>::value>::type*& = enabler ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,0,0,addr)),
	m_addr(NULL)
	{
	}
	template<typename T> explicit mnemonic_t( unsigned_int32_t	opcode, T	addr, typename enable_if<is_pointer<T>::value>::type*& = enabler ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,0,0,0)),
	m_addr(addr)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, unsigned_int16_t	offset, register16_t&	xr ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,0,xr.type() - register16_type_gr0 + 1,offset)),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, signed_int16_t	offset, register16_t&	xr ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,0,xr.type() - register16_type_gr0 + 1,offset)),
	m_addr(NULL)
	{
	}
	template<typename T> explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr, T	addr, typename enable_if<is_integral<T>::value>::type*& = enabler ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0,addr)),
	m_addr(NULL)
	{
	}
	template<typename T> explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr, T	addr, typename enable_if<is_pointer<T>::value>::type*& = enabler ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0,0)),
	m_addr(addr)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr, unsigned_int16_t	offset, register16_t&	xr ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1,offset)),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr, signed_int16_t	offset, register16_t&	xr ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1,offset)),
	m_addr(NULL)
	{
	}
	// 新しい形式
	explicit mnemonic_t( unsigned_int32_t	opcode, register16_t&	gr, register16_t&	xr ):
	mnemonic_data_t(COMET2OP16_MAKE(opcode|opcode_1,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1)),
	m_addr(NULL)
	{
	}
	// データ用
	struct data_tag {};
	explicit mnemonic_t( data_tag, size_t	cd, int	d0, va_list	ap ):
	mnemonic_data_t(cd,static_cast<unsigned_int16_t>(d0),ap),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( data_tag, size_t	cd, unsigned_int16_t	d0, va_list	ap ):
	mnemonic_data_t(cd,d0,ap),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( data_tag, size_t	cd, const char*	d0, va_list	ap ):
	mnemonic_data_t(cd,d0,ap),
	m_addr(NULL)
	{
	}
	// 直接用
	explicit mnemonic_t( unsigned_int32_t	opcode, unsigned_int32_t	gr, unsigned_int32_t	xr, unsigned_int32_t	addr ):
	mnemonic_data_t(COMET2OP32_MAKE(opcode,gr,xr,addr)),
	m_addr(NULL)
	{
	}
	explicit mnemonic_t( unsigned_int32_t	opcode, unsigned_int32_t	gr, unsigned_int32_t	xr ):
	mnemonic_data_t(COMET2OP16_MAKE(opcode,gr,xr)),
	m_addr(NULL)
	{
	}
private:
	mnemonic_t();
};

#define	FR_BITOFFSET_ZF	(0u)
#define	FR_BITOFFSET_SF	(1u)
#define	FR_BITOFFSET_OF	(2u)
#define	FR_ZF	(1u<<FR_BITOFFSET_ZF)
#define	FR_SF	(1u<<FR_BITOFFSET_SF)
#define	FR_OF	(1u<<FR_BITOFFSET_OF)
#define	FR_ALL	static_cast<unsigned_int16_t>(-1)
struct fr_t : public register16_t {
	fr_t():register16_t(register16_type_fr){}
	
	bool	zf() const {
		return	!!( m_value & FR_ZF );
	}
	bool	sf() const {
		return	!!( m_value & FR_SF );
	}
	bool	of() const {
		return	!!( m_value & FR_OF );
	}
	void	zf( bool	value ){
		if( value ){
			m_value |= FR_ZF;
		}
		else{
			m_value &= ~FR_ZF;
		}
	}
	void	sf( bool	value ){
		if( value ){
			m_value |= FR_SF;
		}
		else{
			m_value &= ~FR_SF;
		}
	}
	void	of( bool	value ){
		if( value ){
			m_value |= FR_OF;
		}
		else{
			m_value &= ~FR_OF;
		}
	}
	void	cpa( unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
		sf( static_cast<signed_int16_t>(lhs) < static_cast<signed_int16_t>(rhs));
		zf( lhs == rhs );
	}
	void	cpl( unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
		sf( lhs < rhs );
		zf( lhs == rhs );
	}
	void	cmp( unsigned_int16_t	value16 ){
		sf( static_cast<signed_int16_t>(value16) < 0 );
		zf( !value16 );
	}
	void	cpa( unsigned_int32_t	value32 ){
		unsigned_int16_t	value16 = static_cast<unsigned_int16_t>( value32 & 0x0000ffffu );
		cmp( value16 );
		of(( static_cast<signed_int16_t>(value16) < 0 ) != ( static_cast<signed_int32_t>(value32) < 0 ));
	}
	void	cpl( unsigned_int32_t	value32 ){
		unsigned_int16_t	value16 = static_cast<unsigned_int16_t>( value32 & 0x0000ffffu );
		cmp( value16 );
		of( !!( value32 & 0xffff0000u ));
	}
	using register16_t::operator=;

	// レジスタのコピーを作ることはない
	fr_t( const fr_t&	rhs ) = delete;
	// レジスタを移動することはない
	fr_t( fr_t&&	rhs ) = delete;
	// レジスタはを移動することはない
	fr_t&	operator=( fr_t&&	rhs ) = delete;
};

class asm_t {
	std::vector<mnemonic_t>	m_data;
	unsigned_int16_t	m_start;
	unsigned_int16_t	m_end;
	unsigned_int16_t	:16;
	unsigned_int16_t	:16;
	size_t	m_size;
	
	void	push_back( const mnemonic_t&	mnemonic ){
		m_data.push_back( mnemonic );
		m_size += mnemonic.size();
	}
public:
	signed_int16_t	label() const {
		return	static_cast<signed_int16_t>(m_size);
	}
	void	start(){
		m_start = static_cast<unsigned_int16_t>(m_size);
	}
	void	start( unsigned_int16_t	addr ){
		m_start = addr;
	}
	void	end(){
		m_end = static_cast<unsigned_int16_t>(m_size);
	}
	unsigned_int16_t	start() const {
		return	m_start;
	}
	unsigned_int16_t	end() const {
		return	m_end;
	}
	signed_int16_t	ds( size_t	n ){
		signed_int16_t	result = label();
		m_size += n;
		return	result;
	}
	template<size_t cd, typename T> signed_int16_t	dc( T	d0,... ){
		signed_int16_t	result = label();
		va_list	ap;
		va_start( ap, d0 );
		push_back( mnemonic_t( mnemonic_t::data_tag(), cd, d0, ap ));
		va_end( ap );
		return	result;
	}
	void	rpush(){
		push_back( mnemonic_t( opcode_push, 0, 1+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 2+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 3+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 4+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 5+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 6+1, 0 ));
		push_back( mnemonic_t( opcode_push, 0, 7+1, 0 ));
	}
	void	rpop(){
		push_back( mnemonic_t( opcode_pop, 7+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 6+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 5+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 4+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 3+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 2+1, 0 ));
		push_back( mnemonic_t( opcode_pop, 1+1, 0 ));
	}
	void	nop(){
		push_back( mnemonic_t( opcode_nop ));
	}
	void	ld( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_ld, gr, xr ));
	}
	void	ld( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_ld, gr, addr ));
	}
	void	ld( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_ld, gr, addr ));
	}
	void	ld( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_ld, gr, offset, xr ));
	}
	void	st( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_st, gr, addr ));
	}
	void	st( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_st, gr, addr ));
	}
	void	st( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_st, gr, offset, xr ));
	}
	void	lad( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_lad, gr, addr ));
	}
	void	lad( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_lad, gr, addr ));
	}
	void	lad( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_lad, gr, offset, xr ));
	}
	void	adda( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_adda, gr, xr ));
	}
	void	adda( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_adda, gr, addr ));
	}
	void	adda( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_adda, gr, addr ));
	}
	void	adda( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_adda, gr, offset, xr ));
	}
	void	addl( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_addl, gr, xr ));
	}
	void	addl( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_addl, gr, addr ));
	}
	void	addl( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_addl, gr, addr ));
	}
	void	addl( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_addl, gr, offset, xr ));
	}
	void	suba( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_suba, gr, xr ));
	}
	void	suba( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_suba, gr, addr ));
	}
	void	suba( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_suba, gr, addr ));
	}
	void	suba( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_suba, gr, offset, xr ));
	}
	void	subl( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_subl, gr, xr ));
	}
	void	subl( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_subl, gr, addr ));
	}
	void	subl( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_subl, gr, addr ));
	}
	void	subl( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_subl, gr, offset, xr ));
	}
	void	and_( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_and, gr, xr ));
	}
	void	and_( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_and, gr, addr ));
	}
	void	and_( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_and, gr, addr ));
	}
	void	and_( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_and, gr, offset, xr ));
	}
	void	or_( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_or, gr, xr ));
	}
	void	or_( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_or, gr, addr ));
	}
	void	or_( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_or, gr, addr ));
	}
	void	or_( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_or, gr, offset, xr ));
	}
	void	xor_( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_xor, gr, xr ));
	}
	void	xor_( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_xor, gr, addr ));
	}
	void	xor_( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_xor, gr, addr ));
	}
	void	xor_( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_xor, gr, offset, xr ));
	}
	void	cpa( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_cpa, gr, xr ));
	}
	void	cpa( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_cpa, gr, addr ));
	}
	void	cpa( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_cpa, gr, addr ));
	}
	void	cpa( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_cpa, gr, offset, xr ));
	}
	void	cpl( register16_t&	gr, register16_t&	xr ){
		push_back( mnemonic_t( opcode_cpl, gr, xr ));
	}
	void	cpl( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_cpl, gr, addr ));
	}
	void	cpl( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_cpl, gr, addr ));
	}
	void	cpl( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_cpl, gr, offset, xr ));
	}
	void	sla( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_sla, gr, addr ));
	}
	void	sla( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_sla, gr, addr ));
	}
	void	sla( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_sla, gr, offset, xr ));
	}
	void	sra( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_sra, gr, addr ));
	}
	void	sra( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_sra, gr, addr ));
	}
	void	sra( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_sra, gr, offset, xr ));
	}
	void	sll( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_sll, gr, addr ));
	}
	void	sll( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_sll, gr, addr ));
	}
	void	sll( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_sll, gr, offset, xr ));
	}
	void	srl( register16_t&	gr, signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_srl, gr, addr ));
	}
	void	srl( register16_t&	gr, signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_srl, gr, addr ));
	}
	void	srl( register16_t&	gr, signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_srl, gr, offset, xr ));
	}
	void	jpl( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jpl, addr ));
	}
	void	jpl( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jpl, addr ));
	}
	void	jpl( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jpl, offset, xr ));
	}
	void	jmi( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jmi, addr ));
	}
	void	jmi( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jmi, addr ));
	}
	void	jmi( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jmi, offset, xr ));
	}
	void	jnz( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jnz, addr ));
	}
	void	jnz( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jnz, addr ));
	}
	void	jnz( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jnz, offset, xr ));
	}
	void	jne( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jne, addr ));
	}
	void	jne( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jne, addr ));
	}
	void	jne( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jne, offset, xr ));
	}
	void	jov( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jov, addr ));
	}
	void	jov( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jov, addr ));
	}
	void	jov( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jov, offset, xr ));
	}
	void	jump( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_jump, addr ));
	}
	void	jump( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_jump, addr ));
	}
	void	jump( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_jump, offset, xr ));
	}
	void	push( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_push, addr ));
	}
	void	push( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_push, addr ));
	}
	void	push( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_push, offset, xr ));
	}
	void	pop( register16_t&	gr ){
		push_back( mnemonic_t( opcode_pop, gr ));
	}
	void	call( signed_int16_t	addr ){
		push_back( mnemonic_t( opcode_call, addr ));
	}
	void	call( signed_int16_t*	addr ){
		push_back( mnemonic_t( opcode_call, addr ));
	}
	void	call( signed_int16_t	offset, register16_t&	xr ){
		push_back( mnemonic_t( opcode_call, offset, xr ));
	}
	void	ret(){
		push_back( mnemonic_t( opcode_ret ));
	}
	
	bool	read( unsigned_int16_t*	data, size_t	celt_data, size_t*	pcelt_read ) const {
		bool	success = true;
		size_t	celt_read = 0;
		if( !data ||( celt_data < m_data.size())){
			success = false;
		}
		if( success ){
			for( std::vector<mnemonic_t>::const_iterator	p = m_data.begin(); p != m_data.end(); ++p ){
				size_t	m = 0;
				success = p->read( &data[celt_read], celt_data - celt_read, &m );
				if( !success ){
					break;
				}
				celt_read += m;
			}
		}
		if( pcelt_read ){
			*pcelt_read = celt_read;
		}
		return	success;
	}
	
	asm_t():
	m_data(),
	m_start(0),
	m_end(0),
	m_size(0)
	{
	}
private:
	asm_t( const asm_t& );
	asm_t&	operator=( const asm_t& );
};
class vm_t {
protected:
	static const unsigned_int16_t	c_base_address = 0x0100;
	
	typedef void	(vm_t::*operator_t)( const comet2op_t& );
	static operator_t	c_operators[opcodes];
	static register16_t vm_t::*	c_gr[8];
	register16_t	m_gr0;
	register16_t	m_gr1;
	register16_t	m_gr2;
	register16_t	m_gr3;
	register16_t	m_gr4;
	register16_t	m_gr5;
	register16_t	m_gr6;
	register16_t	m_gr7;
	register16_t	m_sp;
	register16_t	m_pr;
	fr_t	m_fr;
	unsigned_int16_t	m_memory[65536];
	unsigned_int16_t	m_start;
	unsigned_int16_t	m_end;
	
	void	output_debug_string1( const char*	name, unsigned_int16_t	gr, unsigned_int16_t	xr );
	void	output_debug_string2( const char*	name, unsigned_int16_t	gr, unsigned_int16_t	xr, unsigned_int16_t	addr );
	void	output_debug_string1( const char*	name, const comet2op_t&	op );
	void	output_debug_string2( const char*	name, const comet2op_t&	op );
	
	void	operator_adda( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_addl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_suba( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_subl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_and( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_or( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_xor( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_sla( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_sra( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_sll( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );
	void	operator_srl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs );

	void	operator1_nop( const comet2op_t& );
	void	operator2_ld( const comet2op_t& );
	void	operator2_st( const comet2op_t& );
	void	operator2_lad( const comet2op_t& );
	void	operator2_adda( const comet2op_t& );
	void	operator2_addl( const comet2op_t& );
	void	operator2_suba( const comet2op_t& );
	void	operator2_subl( const comet2op_t& );
	void	operator2_and( const comet2op_t& );
	void	operator2_or( const comet2op_t& );
	void	operator2_xor( const comet2op_t& );
	void	operator2_cpa( const comet2op_t& );
	void	operator2_cpl( const comet2op_t& );
	void	operator2_sla( const comet2op_t& );
	void	operator2_sra( const comet2op_t& );
	void	operator2_sll( const comet2op_t& );
	void	operator2_srl( const comet2op_t& );
	void	operator2_jpl( const comet2op_t& );
	void	operator2_jmi( const comet2op_t& );
	void	operator2_jnz( const comet2op_t& );
	void	operator2_jne( const comet2op_t& );
	void	operator2_jov( const comet2op_t& );
	void	operator2_jump( const comet2op_t& );
	void	operator2_push( const comet2op_t& );
	void	operator1_pop( const comet2op_t& );
	void	operator2_call( const comet2op_t& );
	void	operator1_ret( const comet2op_t& );
	void	operator1_ld( const comet2op_t& );
	void	operator1_adda( const comet2op_t& );
	void	operator1_addl( const comet2op_t& );
	void	operator1_suba( const comet2op_t& );
	void	operator1_subl( const comet2op_t& );
	void	operator1_and( const comet2op_t& );
	void	operator1_or( const comet2op_t& );
	void	operator1_xor( const comet2op_t& );
	void	operator1_cpa( const comet2op_t& );
	void	operator1_cpl( const comet2op_t& );
	
	bool	load( const asm_t& );
	void	run();
public:
	register16_t&	gr0(){ return m_gr0; }
	register16_t&	gr1(){ return m_gr1; }
	register16_t&	gr2(){ return m_gr2; }
	register16_t&	gr3(){ return m_gr3; }
	register16_t&	gr4(){ return m_gr4; }
	register16_t&	gr5(){ return m_gr5; }
	register16_t&	gr6(){ return m_gr6; }
	register16_t&	gr7(){ return m_gr7; }
	register16_t&	gr_( unsigned_int16_t	n ){ return	this->*c_gr[n]; }
	
	void	reset();
	bool	load_and_run( const asm_t&	asm_ );
	
	vm_t():
	m_gr0(register16_type_gr0),
	m_gr1(register16_type_gr1),
	m_gr2(register16_type_gr2),
	m_gr3(register16_type_gr3),
	m_gr4(register16_type_gr4),
	m_gr5(register16_type_gr5),
	m_gr6(register16_type_gr6),
	m_gr7(register16_type_gr7),
	m_sp(register16_type_sp),
	m_pr(register16_type_pr),
	m_fr(),
	m_memory(),
	m_start(),
	m_end()
	{
		reset();
	}
private:
	vm_t( const vm_t& );
	vm_t&	operator=( const vm_t& );
};
vm_t::operator_t	vm_t::c_operators[opcodes] = {
	// 0x00〜
	&vm_t::operator1_nop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x10〜
	&vm_t::operator2_ld, &vm_t::operator2_st, &vm_t::operator2_lad, NULL, &vm_t::operator1_ld, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x20〜
	&vm_t::operator2_adda, &vm_t::operator2_addl, &vm_t::operator2_suba, &vm_t::operator1_subl, &vm_t::operator1_adda, &vm_t::operator1_addl, &vm_t::operator1_suba, &vm_t::operator2_subl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x30〜
	&vm_t::operator2_and, &vm_t::operator2_or, &vm_t::operator2_xor, NULL, &vm_t::operator1_and, &vm_t::operator1_or, &vm_t::operator1_xor, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x40〜
	&vm_t::operator2_cpa, &vm_t::operator2_cpl, NULL, NULL, &vm_t::operator1_cpa, &vm_t::operator1_cpl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x50〜
	&vm_t::operator2_sla, &vm_t::operator2_sra, &vm_t::operator2_sll, &vm_t::operator2_srl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	// 0x60〜
	NULL, &vm_t::operator2_jmi, &vm_t::operator2_jnz, &vm_t::operator2_jne, &vm_t::operator2_jump, &vm_t::operator2_jpl, &vm_t::operator2_jov, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	// 0x70〜
	&vm_t::operator2_push, &vm_t::operator1_pop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	// 0x80〜
	&vm_t::operator2_call, &vm_t::operator1_ret, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	// 0x90〜
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
};
register16_t vm_t::*	vm_t::c_gr[8] = {
	&vm_t::m_gr0,
	&vm_t::m_gr1,
	&vm_t::m_gr2,
	&vm_t::m_gr3,
	&vm_t::m_gr4,
	&vm_t::m_gr5,
	&vm_t::m_gr6,
	&vm_t::m_gr7,
};

void	vm_t::output_debug_string1( const char*	name, unsigned_int16_t	gr, unsigned_int16_t	xr ){
	if( gr ){
		if( xr ){
			debug_printf( "%-4s gr%d,gr%d\n", name, gr-1, xr-1 );
		}
		else{
			debug_printf( "%-4s gr%d\n", name, gr-1 );
		}
	}
	else{
		debug_printf( "%-4s\n", name );
	}
}
void	vm_t::output_debug_string2( const char*	name, unsigned_int16_t	gr, unsigned_int16_t	xr, unsigned_int16_t	addr ){
	if( gr ){
		if( xr ){
			debug_printf( "%-4s gr%d,%d,gr%d\n", name, gr-1, addr, xr-1 );
		}
		else{
			debug_printf( "%-4s gr%d,%d\n", name, gr-1, addr );
		}
	}
	else if( xr ){
		debug_printf( "%-4s %d,gr%d\n", name, addr, xr-1 );
	}
	else{
		debug_printf( "%-4s %d\n", name, addr );
	}
}
void	vm_t::output_debug_string1( const char*	name, const comet2op_t&	op ){
	unsigned_int16_t	gr = op.gr();
	unsigned_int16_t	xr = op.xr();
	output_debug_string1( name, gr, xr );
}
void	vm_t::output_debug_string2( const char*	name, const comet2op_t&	op ){
	unsigned_int16_t	gr = op.gr();
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	output_debug_string2( name, gr, xr, addr );
}
void	vm_t::operator1_nop( const comet2op_t&	op ){
	output_debug_string1( "nop", op );
	++m_pr;
}
void	vm_t::operator2_ld( const comet2op_t&	op ){
	output_debug_string2( "ld", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	gr_( gr ) = m_memory[addr];
	m_fr.cmp( gr_( gr ));
	m_pr += 2;
}
void	vm_t::operator1_ld( const comet2op_t&	op ){
	output_debug_string1( "ld", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	gr_( gr ) = gr_( xr );
	m_fr.cmp( gr_( gr ));
	++m_pr;
}
void	vm_t::operator2_st( const comet2op_t&	op ){
	output_debug_string2( "st", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	m_memory[addr] = gr_( gr );
	m_pr += 2;
}
void	vm_t::operator2_lad( const comet2op_t&	op ){
	output_debug_string2( "lad", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	gr_( gr ) = addr;
	m_pr += 2;
}
void	vm_t::operator_adda( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = static_cast<unsigned_int32_t>(lhs) + static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu);
	m_fr.cpa( temp );
}
void	vm_t::operator2_adda( const comet2op_t&	op ){
	output_debug_string2( "adda", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_adda( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_adda( const comet2op_t&	op ){
	output_debug_string1( "adda", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_adda( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_addl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = static_cast<unsigned_int32_t>(lhs) + static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu);
	m_fr.cpl( temp );
}
void	vm_t::operator2_addl( const comet2op_t&	op ){
	output_debug_string2( "addl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_addl( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_addl( const comet2op_t&	op ){
	output_debug_string1( "addl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_addl( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_suba( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = static_cast<unsigned_int32_t>(lhs) - static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu);
	m_fr.cpa( temp );
}
void	vm_t::operator2_suba( const comet2op_t&	op ){
	output_debug_string2( "suba", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_suba( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_suba( const comet2op_t&	op ){
	output_debug_string1( "suba", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_suba( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_subl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = static_cast<unsigned_int32_t>(lhs) - static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu);
	m_fr.cpl( temp );
}
void	vm_t::operator2_subl( const comet2op_t&	op ){
	output_debug_string2( "subl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_subl( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_subl( const comet2op_t&	op ){
	output_debug_string1( "subl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_subl( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_and( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	r = static_cast<unsigned_int16_t>( lhs & rhs );
	m_fr.cmp( r );
}
void	vm_t::operator2_and( const comet2op_t&	op ){
	output_debug_string2( "and", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_and( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_and( const comet2op_t&	op ){
	output_debug_string1( "and", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_and( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_or( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	r = static_cast<unsigned_int16_t>( lhs | rhs );
	m_fr.cmp( r );
}
void	vm_t::operator2_or( const comet2op_t&	op ){
	output_debug_string2( "or", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_or( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_or( const comet2op_t&	op ){
	output_debug_string1( "or", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_or( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_xor( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	r = static_cast<unsigned_int16_t>( lhs ^ rhs );
	m_fr.cmp( r );
}
void	vm_t::operator2_xor( const comet2op_t&	op ){
	output_debug_string2( "xor", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_xor( gr_( gr ), gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_xor( const comet2op_t&	op ){
	output_debug_string1( "xor", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	operator_xor( gr_( gr ), gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator2_cpa( const comet2op_t&	op ){
	output_debug_string2( "cpa", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	m_fr.cpa( gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_cpa( const comet2op_t&	op ){
	output_debug_string1( "cpa", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	m_fr.cpa( gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator2_cpl( const comet2op_t&	op ){
	output_debug_string2( "cpl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	m_fr.cpl( gr_( gr ), m_memory[addr] );
	m_pr += 2;
}
void	vm_t::operator1_cpl( const comet2op_t&	op ){
	output_debug_string1( "cpl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	xr = op.xr()-1u;
	m_fr.cpl( gr_( gr ), gr_( xr ));
	++m_pr;
}
void	vm_t::operator_sla( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int16_t	temp = static_cast<unsigned_int16_t>( static_cast<signed_int16_t>(lhs) >> rhs );
	r = ( static_cast<unsigned_int16_t>(lhs) & 0x8000u ) | ( static_cast<unsigned_int16_t>(temp) & 0x7fffu );
	m_fr.cmp( r );
	m_fr.of( static_cast<signed_int16_t>(temp) < 0 );
}
void	vm_t::operator2_sla( const comet2op_t&	op ){
	output_debug_string2( "sla", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_sla( gr_( gr ), gr_( gr ), addr );
	m_pr += 2;
}
void	vm_t::operator_sra( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = ( static_cast<unsigned_int32_t>(static_cast<unsigned_int16_t>(lhs)) << 16 ) >>  static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>( temp >> 16 );
	m_fr.cmp( r );
	m_fr.of( !!( temp & 0x00008000u ));
}
void	vm_t::operator2_sra( const comet2op_t&	op ){
	output_debug_string2( "sra", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_sra( gr_( gr ), gr_( gr ), addr );
	m_pr += 2;
}
void	vm_t::operator_sll( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = static_cast<unsigned_int32_t>(lhs) << static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>( temp & 0x0000ffffu );
	m_fr.cmp( r );
	m_fr.of( !!( temp & 0x00010000u ));
}
void	vm_t::operator2_sll( const comet2op_t&	op ){
	output_debug_string2( "sll", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_sll( gr_( gr ), gr_( gr ), addr );
	m_pr += 2;
}
void	vm_t::operator_srl( register16_t&	r, unsigned_int16_t	lhs, unsigned_int16_t	rhs ){
	unsigned_int32_t	temp = ( static_cast<unsigned_int32_t>(lhs) << 16 ) >> static_cast<unsigned_int32_t>(rhs);
	r = static_cast<unsigned_int16_t>( temp >> 16 );
	m_fr.cmp( r );
	m_fr.of( !!( temp & 0x00008000u ));
}
void	vm_t::operator2_srl( const comet2op_t&	op ){
	output_debug_string2( "srl", op );
	unsigned_int16_t	gr = op.gr()-1u;
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	operator_srl( gr_( gr ), gr_( gr ), addr );
	m_pr += 2;
}
void	vm_t::operator2_jpl( const comet2op_t&	op ){
	output_debug_string2( "jpl", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	if( m_fr.sf() && m_fr.zf()){
		m_pr = addr;
	}
	else{
		m_pr += 2;
	}
}
void	vm_t::operator2_jmi( const comet2op_t&	op ){
	output_debug_string2( "jmi", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	if( m_fr.sf()){
		m_pr = addr;
	}
	else{
		m_pr += 2;
	}
}
void	vm_t::operator2_jnz( const comet2op_t&	op ){
	output_debug_string2( "jnz", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	if( !m_fr.zf()){
		m_pr = addr;
	}
	else{
		m_pr += 2;
	}
}
void	vm_t::operator2_jne( const comet2op_t&	op ){
	output_debug_string2( "jne", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	if( m_fr.zf()){
		m_pr = addr;
	}
	else{
		m_pr += 2;
	}
}
void	vm_t::operator2_jov( const comet2op_t&	op ){
	output_debug_string2( "jov", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	if( m_fr.of()){
		m_pr = addr;
	}
	else{
		m_pr += 2;
	}
}
void	vm_t::operator2_jump( const comet2op_t&	op ){
	output_debug_string2( "jump", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	m_pr = addr;
}
void	vm_t::operator2_push( const comet2op_t&	op ){
	output_debug_string2( "push", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	--m_sp;
	m_memory[m_sp] = addr;
	m_pr += 2;
}
void	vm_t::operator1_pop( const comet2op_t&	op ){
	output_debug_string1( "pop", op );
	unsigned_int16_t	gr = op.gr()-1u;
	gr_( gr ) = m_memory[m_sp];
	++m_sp;
	++m_pr;
}
void	vm_t::operator2_call( const comet2op_t&	op ){
	output_debug_string2( "call", op );
	unsigned_int16_t	addr = op.addr();
	unsigned_int16_t	xr = op.xr();
	if( xr ){
		addr += gr_( xr-1u );
	}
	m_pr += 2;
	--m_sp;
	m_memory[m_sp] = m_pr;
	m_pr = addr;
}
void	vm_t::operator1_ret( const comet2op_t&	op ){
	output_debug_string1( "ret", op );
	m_pr = m_memory[m_sp];
	++m_sp;
}
void	vm_t::reset(){
	m_gr0 = 0;
	m_gr1 = 0;
	m_gr2 = 0;
	m_gr3 = 0;
	m_gr4 = 0;
	m_gr5 = 0;
	m_gr6 = 0;
	m_gr7 = 0;
	m_sp = 0;
	m_pr = 0;
	m_fr = 0;
}
bool	vm_t::load( const asm_t&	asm_ ){
	bool	success = true;
	if( !asm_.end()){
		success = false;
	}
	if( success ){
		m_start = asm_.start();
		m_end = asm_.end();
		asm_.read( m_memory, elementsof( m_memory ), NULL );
	}
	return	success;
}
void	vm_t::run(){
	m_sp = 0;
	m_pr = m_start;
	while( static_cast<size_t>(static_cast<signed_int16_t>(m_pr)) != m_end ){
		comet2op_t	op( &m_memory[m_pr] );
		(this->*c_operators[op.opcode()])( op );
	}
}
bool	vm_t::load_and_run( const asm_t&	asm_ ){
	bool	success = load( asm_ );
	if( success ){
		run();
	}
	return	success;
}

使用例

int	main(){
	vm_t	vm;
	register16_t&	gr0 = vm.gr0();
	register16_t&	gr1 = vm.gr1();

	asm_t	asm_;
	
	asm_.start();
	signed_int16_t	label2 = 0;
	signed_int16_t	label3 = 0;
	asm_.lad( gr0, 100 );
	asm_.call( &label2 );
	asm_.jump( &label3 );

	label2 = asm_.label();
	asm_.rpush();
	asm_.push( 0, gr0 );
	asm_.pop( gr1 );
	asm_.rpop();
	asm_.ret();

	signed_int16_t	label4 = asm_.dc<3>( 10, 20, 30 );
	signed_int16_t	label5 = asm_.dc<2>( "aaa", "bbb" );
	(void)label5;
	
	label3 = asm_.label();
	asm_.lad( gr1, 1 );
	asm_.ld( gr0, label4, gr1 );
	asm_.end();

	vm.load_and_run( asm_ );
	return	0;
}

出力例

lad  gr0,100
call 6
push 0,gr1
push 0,gr2
push 0,gr3
push 0,gr4
push 0,gr5
push 0,gr6
push 0,gr7
push 0,gr0
pop  gr1
pop  gr7
pop  gr6
pop  gr5
pop  gr4
pop  gr3
pop  gr2
pop  gr1
ret 
jump 40
lad  gr1,1
ld   gr0,31,gr1

このように自分で実装してみると、レジスタはただの整数のグローバル変数アセンブラニーモニックはただの関数とその引数、ポインタはただのアドレスの入れ物、スレッドはメモリはそのままでレジスタだけを丸ごと入れ替えてるだけ、プロセスはメモリもレジスタも丸ごと入れ替えてるだけ、というようなことも理解できるようになったのではないでしょうか