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

はじめに

新人さんといわず中堅くらいになったプログラマでもアセンブラがわからないという人が最近は多いようです
「ポインタがわからない」「マルチスレッドがわからない」というようなことも結局はアセンブラを理解していないところが大きいように思います

そこでここではアセンブラを使わず C++ だけでアセンブラについて説明してみましょう

動作の詳細としてのアセンブラ

C/C++ の動作の詳細としてのアセンブラ入門は「C/C++ ポインタ入門」に譲ります

アセンブラ

ここでは「アセンブラ」という言葉を CPU が解釈可能なバイナリコードの意味で使ったりアセンブリ言語の意味で使ったりソースファイルをアセンブルするアプリケーションであるアセンブラの意味で使ったりしています

CPU / MPU

プログラムを実行する主体であるハードウェアであるところの CPU ができることは、その CPU の 命令セットにあるものだけです
例えば intelx86 / ia32 は、http://www.intel.com/jp/download/index.htm#ia32 にあるドキュメントに一覧があります

レジスタに値を入れる、レジスタに入っている値を操作する、メモリからレジスタに値を読み込む、レジスタからメモリに値を書き込む、条件によってフラグを立てる、指定のアドレスにジャンプする
CPU にできるのはたったこれだけです

たったこれだけのことがわからないはずがないですよね
わらないというのはただアセンブリ言語の文法や CPU の動作の仕組みを理解していないというだけのことではないでしょうか

プログラマであるなら分らないことがあったときの対処方法は簡単です
書いてみればいいのです

intdos, int86

昔々 MS-DOS の頃、C プログラマアセンブラのわからない人は intdos や int86 などといった API を使うことでアセンブラに馴染むことができました

struct WORDREGS {
	unsigned short ax;
	unsigned short bx;
	unsigned short cx;
	unsigned short dx;
	unsigned short si;
	unsigned short di;
	unsigned short cflag;
};
struct BYTEREGS {
	unsigned char al, ah;
	unsigned char bl, bh;
	unsigned char cl, ch;
	unsigned char dl, dh;
};
union REGS {
	struct WORDREGS x;
	struct BYTEREGS h;
};

int intdos( int no, union REGS* iregs, union REGS* oregs );
int int86( int no, union REGS* iregs, union REGS* oregs );

今はもうこんなのはありませんが、インラインアセンブラが使えますから同じようなものを自分で実装することも簡単です

インラインアセンブラ

インラインアセンブラなら C++ のコード中に本当にアセンブラで書いてみることも簡単です
実際に試してみるといいでしょう

アセンブラは使わずにと言いましたが、例えば CPUID 命令を使おうとするとこんな感じになるでしょうか

x86環境の場合

x86環境ではインラインアセンブラ __asm で eax にコマンド番号を指定して cpuid 命令を呼ぶだけです

inline bool	cpuid32_issupported(){
	DWORD	_eax0 = 0;
	DWORD	_eax1 = 0;
	__asm{
		pushfd
		pop	eax
		mov	_eax0, eax
		xor	eax, 00200000h
		push	eax
		popfd
		pushfd
		pop	eax
		mov	_eax1, eax
	}
	return	( _eax0 != _eax1 );
}

inline DWORD	cpuid32( DWORD	_eax, DWORD	_ecx, LPDWORD	peax = NULL, LPDWORD	pebx = NULL, LPDWORD	pecx = NULL, LPDWORD	pedx = NULL ){
	DWORD	_ebx = 0;
	DWORD	_edx = 0;
	__asm{
		mov	eax, _eax
		mov	ecx, _ecx
		cpuid
		mov	_eax, eax
		mov	_ebx, ebx
		mov	_ecx, ecx
		mov	_edx, edx
	}
	if( peax ){
		*peax = _eax;
	}
	if( pebx ){
		*pebx = _ebx;
	}
	if( pecx ){
		*pecx = _ecx;
	}
	if( pedx ){
		*pedx = _edx;
	}
	return	_eax;
}

簡単ですよね

x64環境の場合

x64環境ではインラインアセンブラは使えないので別に .asmファイルを用意する必要があります
少し見た目が違うだけで随分難しそうになってしまいましたか?
でも命令自体は同じなのでやっている内容は x86環境のときと同じですよ

EXTERN_C bool __fastcall	cpuid64_issupported();
EXTERN_C DWORD __fastcall	cpuid64( DWORD	_eax, DWORD	_ecx, LPDWORD	peax, LPDWORD	pebx, LPDWORD	pecx, LPDWORD	pedx );
	PUBLIC	cpuid64_issupported
	PUBLIC	cpuid64
	.CODE
	ALIGN	8
; bool	cpuid64_issupported();
cpuid64_issupported PROC FRAME
	sub	rsp, 20h
	.allocstack	20h
	.endprolog
	
	pushfq
	pop	rax
	mov	rcx, rax
	xor	rax, 00200000h
	push	rax
	popfq
	pushfq
	pop	rdx
	xor	rax, rax
	test	rcx, rdx
	setne	al
	
	add	rsp, 20h
	ret
	ALIGN	8
cpuid64_issupported ENDP
	ALIGN	8
; DWORD	cpuid64( DWORD	_eax, DWORD	_ecx, LPDWORD	peax, LPDWORD	pebx, LPDWORD	pecx, LPDWORD	pedx );
cpuid64 PROC FRAME
	sub	rsp, 20h
	.allocstack	20h
	push	rbx
	.pushreg	rbx
	push	r10
	.pushreg	r10
	push	r11
	.pushreg	r11
	.endprolog
	
	mov	r11, QWORD PTR [rsp+68h]
	mov	r10, QWORD PTR [rsp+60h]
	mov	rax, rcx
	mov	rcx, rdx
	cpuid
	test	r8, r8
	je	@f
	mov	DWORD PTR [r8], eax
@@:
	test	r9, r9
	je	@f
	mov	DWORD PTR [r9], ebx
@@:
	test	r10, r10
	je	@f
	mov	DWORD PTR [r10], ecx
@@:
	test	r11, r11
	je	@f
	mov	DWORD PTR [r11], edx
@@:
	
	pop	r11
	pop	r10
	pop	rbx
	add	rsp, 20h
	
	ret
	ALIGN	8
cpuid64 ENDP
_TEXT ENDS
	END

カスタムビルドは例えばこんな感じ:

ml64.exe /c /nologo /Zi /Fo"$(IntDir)\$(InputName).obj" $(InputFileName)
使用例

当たり前のことですが、中身の実装が C++ でもアセンブラでも使う側にとってはただの関数です

#if	defined( WIN64 ) || defined( _WIN64 )
#define	cpuid_issupported	cpuid64_issupported
#define	cpuid	cpuid64
#else // WIN64
#define	cpuid_issupported	cpuid32_issupported
#define	cpuid	cpuid32
#endif // WIN64

#define	CPUID_GET_VERSION			0
#define	CPUID_GET_SIGNATURE			1
#define	CPUID_GET_CONFIGURATIONS	2
#define	CPUID_GET_SERIAL_NUMBER		3
#define	CPUID_GET_EX_VERSION		0x80000000
#define	CPUID_GET_EX_SIGNATURE		0x80000001
#define	CPUID_GET_EX_BRAND_STRING1	0x80000002
#define	CPUID_GET_EX_BRAND_STRING2	0x80000003
#define	CPUID_GET_EX_BRAND_STRING3	0x80000004

#define	CPUID_VENDORID_MAX			(3*sizeof(DWORD))
#define	CPUID_EXVENDORID_MAX		(3*sizeof(DWORD))
#define	CPUID_EXBRANDSTRING_MAX		(4*sizeof(DWORD)*3)
#define	CPUID_CONFIGURATIONS_MAX	(4*sizeof(DWORD)-1)

#define	CPUID_FLAGS_EX			0x80000000
#define	CPUID_FLAGS_SUPPORTED	0x00200000

#pragma	pack( push )
#pragma	pack( 1 )
typedef struct _CPUID_PROCESSOR_SERIAL_NUMBER {
	BYTE	b[16];
} CPUID_PROCESSOR_SERIAL_NUMBER, FAR *LPCPUID_PROCESSOR_SERIAL_NUMBER;

typedef struct _CPUID_INFORMATION {
	DWORD	dwSize;
	DWORD	dwFlags;
	DWORD	dwLevels;
	BYTE	bVendorId[CPUID_VENDORID_MAX+1];
	DWORD	dwSignature;
	DWORD	dwFeatureFlags[3];
	BYTE	cConfigurations;
	BYTE	bConfigurations[CPUID_CONFIGURATIONS_MAX];
	CPUID_PROCESSOR_SERIAL_NUMBER	bProcessorSerialNumber;
} CPUID_INFORMATION, FAR* LPCPUID_INFORMATION;

typedef struct _CPUID_INFORMATION_EX {
	// CPUID_INFORMATION compatible
	DWORD	dwSize;
	DWORD	dwFlags;
	DWORD	dwLevels;
	BYTE	bVendorId[CPUID_VENDORID_MAX+1];
	DWORD	dwSignature;
	DWORD	dwFeatureFlags[3];
	BYTE	cConfigurations;
	BYTE	bConfigurations[CPUID_CONFIGURATIONS_MAX];
	CPUID_PROCESSOR_SERIAL_NUMBER	bProcessorSerialNumber;
	// CPUID_INFORMATION_EX
	DWORD	dwEXLevels;
	BYTE	bEXVendorId[CPUID_EXVENDORID_MAX+1];
	DWORD	dwEXFeatureFlags[4];
	BYTE	bEXBrandString[CPUID_EXBRANDSTRING_MAX+1];
} CPUID_INFORMATION_EX, FAR* LPCPUID_INFORMATION_EX;
#pragma	pack( pop )

inline STDMETHODIMP	cpuid_getinformation( LPCPUID_INFORMATION	pinfo ){
	HRESULT	hresult = S_OK;
	if( !pinfo ||(( pinfo->dwSize != sizeof( CPUID_INFORMATION ))&&( pinfo->dwSize != sizeof( CPUID_INFORMATION_EX )))){
		hresult = E_INVALIDARG;
	}
	if( SUCCEEDED( hresult )){
		CPUID_INFORMATION_EX	info = { sizeof( info ) };
		if( cpuid_issupported()){
			info.dwFlags |= CPUID_FLAGS_SUPPORTED;
			DWORD	dwVendorId[3] = {};
			DWORD	dwLevels = cpuid( CPUID_GET_VERSION, 0, NULL, &dwVendorId[0], &dwVendorId[2], &dwVendorId[1] );
			if(( dwLevels & 0xffff0000 ) == 0x00000000 ){
				info.dwLevels = dwLevels & 0x0000ffff;
				if( dwLevels >= CPUID_GET_VERSION ){
					for( size_t	n = 0; n < elementsof( dwVendorId ); ++n ){
						for( size_t	m = 0; m < elementsizeof( dwVendorId ); ++m ){
							info.bVendorId[n*4+m] = ( BYTE )(( dwVendorId[n] >> (8*m)) & 0x0000000ff );
						}
					}
				}
				if( dwLevels >= CPUID_GET_SIGNATURE ){
					cpuid( CPUID_GET_SIGNATURE, 0, &info.dwSignature, &info.dwFeatureFlags[0], &info.dwFeatureFlags[1], &info.dwFeatureFlags[2] );
				}
				if( dwLevels >= CPUID_GET_CONFIGURATIONS ){
					DWORD	dwConfigurations[4] = {};
					cpuid( CPUID_GET_CONFIGURATIONS, 0, &dwConfigurations[0], &dwConfigurations[1], &dwConfigurations[2], &dwConfigurations[3] );
					LPBYTE	pbConfigurations = &(( LPBYTE )dwConfigurations)[1];
					info.cConfigurations = ( BYTE )( dwConfigurations[0] & 0x000000ff );
					for( size_t	n = 0; n < elementsof( info.bConfigurations ); ++n ){
						info.bConfigurations[n] = pbConfigurations[n];
					}
				}
				if( dwLevels >= CPUID_GET_SERIAL_NUMBER ){
					DWORD	dwProcessorSerialNumber[4] = {};
					cpuid( CPUID_GET_SERIAL_NUMBER, 0, &dwProcessorSerialNumber[0], &dwProcessorSerialNumber[1], &dwProcessorSerialNumber[2], &dwProcessorSerialNumber[3] );
					CopyMemory( &info.bProcessorSerialNumber, dwProcessorSerialNumber, sizeof( info.bProcessorSerialNumber ));
				}
			}
			DWORD	dwEXVendorId[3] = {};
			DWORD	dwEXLevels = cpuid( CPUID_GET_EX_VERSION, 0, NULL, &dwEXVendorId[0], &dwEXVendorId[2], &dwEXVendorId[1] );
			if(( dwEXLevels & 0xffff0000 ) == CPUID_FLAGS_EX ){
				info.dwEXLevels = dwEXLevels & 0x0000ffff;
				info.dwFlags |= CPUID_FLAGS_EX;
				if( dwEXLevels >= CPUID_GET_EX_VERSION ){
					for( size_t	n = 0; n < elementsof( dwEXVendorId ); ++n ){
						for( size_t	m = 0; m < elementsizeof( dwEXVendorId ); ++m ){
							info.bEXVendorId[n*4+m] = ( BYTE )(( dwEXVendorId[n] >> (8*m)) & 0x0000000ff );
						}
					}
				}
				if( dwEXLevels >= CPUID_GET_EX_SIGNATURE ){
					cpuid( CPUID_GET_EX_SIGNATURE, 0, &info.dwEXFeatureFlags[0], &info.dwEXFeatureFlags[1], &info.dwEXFeatureFlags[2], &info.dwEXFeatureFlags[3] );
				}
				if( dwEXLevels >= CPUID_GET_EX_BRAND_STRING1 ){
					LONG	cParts = dwEXLevels - CPUID_GET_EX_BRAND_STRING1;
					if( cParts > 3 ){
						cParts = 3;
					}
					for( LONG	l = 0; l < cParts; ++l ){
						DWORD	dwEXBrandString[4] = {};
						cpuid( CPUID_GET_EX_BRAND_STRING1+l, 0, &dwEXBrandString[0], &dwEXBrandString[1], &dwEXBrandString[2], &dwEXBrandString[3] );
						for( size_t	n = 0; n < elementsof( dwEXBrandString ); ++n ){
							for( size_t	m = 0; m < elementsizeof( dwEXBrandString ); ++m ){
								info.bEXBrandString[4*sizeof( DWORD )*l+n*4+m] = ( BYTE )(( dwEXBrandString[n] >> (8*m)) & 0x0000000ff );
							}
						}
					}
				}
			}
		}
		if( pinfo->dwSize == sizeof( CPUID_INFORMATION_EX )){
			*( LPCPUID_INFORMATION_EX )pinfo = *( LPCPUID_INFORMATION_EX )&info;
		}
		else if( pinfo->dwSize == sizeof( CPUID_INFORMATION )){
			*( LPCPUID_INFORMATION )pinfo = *( LPCPUID_INFORMATION )&info;
		}
		//else{
		//	hresult = E_UNEXPECTED;	// 事前にチェックしてあるからここには来ないはず
		//}
	}
	return	hresult;
}

アセンブラと CPU を C++ で実装する

わからないなら書いてしまえばいいというのは、アセンブラを使ってみようということでもありますが、アセンブラと CPU を C++ で書いてしまおうという意味でもあります
アセンブラも CPU も書いてしまいましょう

なんのことかわかりませんか?

次のようなクラスを書いてみようということです

int	main(){
	vm_t	vm;
	register8_t&	al_ = vm.al_();
	
	asm_t	asm_;
	
	asm_.mov( al_, 3 );
	signed_int32_t	label0 = asm_.label();
	asm_.dec( al_ );
	asm_.jnz( label0 );

	vm.exec( asm_ );
	return	0;
}

これはアセンブラではありませんが、見た目はアセンブラですよね
でも C++ ですから、何をやっているかなんていうのは簡単ですよね
こんなものを書いてみましょう

実装例
#if	defined( _MSC_VER )
//  C4351 : 新しい動作: 配列 '%1' の要素は既定で初期化されます
#pragma	warning( disable : 4351 )
#endif // _MSC_VER
#include	<stdio.h>
#include	<stdarg.h>
#include	<vector>

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;

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

enum register8_type {
	register8_type_al,
	register8_type_ah,
	register8_type_bl,
	register8_type_bh,
	register8_type_cl,
	register8_type_ch,
	register8_type_dl,
	register8_type_dh,
	register8_types
};
enum register16_type {
	register16_type_ax,
	register16_type_bx,
	register16_type_cx,
	register16_type_dx,
	register16_type_si,
	register16_type_di,
	register16_type_bp,
	register16_type_sp,
	register16_type_cflags,
	register16_types
};
enum register32_type {
	register32_type_eax,
	register32_type_ebx,
	register32_type_ecx,
	register32_type_edx,
	register32_type_esi,
	register32_type_edi,
	register32_type_ebp,
	register32_type_esp,
	register32_type_eflags,
	register32_type_eip,
	register32_types
};

class asm_t;
class vm_t;

struct register8_t;
struct register16_t;
struct register32_t;

struct immediate8_t {
	typedef unsigned_int8_t	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	immediate8_t( value_type	value ):
	m_value(value)
	{
	}
	immediate8_t( const immediate8_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	immediate8_t&	operator=( const immediate8_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// イミディエイト値は必ず値があるので引数が必要
	immediate8_t();
};
struct immediate16_t {
	typedef unsigned_int16_t	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	immediate16_t( value_type	value ):
	m_value(value)
	{
	}
	immediate16_t( const immediate16_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	immediate16_t&	operator=( const immediate16_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// イミディエイト値は必ず値があるので引数が必要
	immediate16_t();
};
struct immediate32_t {
	typedef signed_int32_t	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	immediate32_t( value_type	value ):
	m_value(value)
	{
	}
	immediate32_t( const immediate32_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	immediate32_t&	operator=( const immediate32_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// イミディエイト値は必ず値があるので引数が必要
	immediate32_t();
};
struct address8_t {
	typedef unsigned_int8_t*	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	address8_t( value_type	value ):
	m_value(value)
	{
	}
	address8_t( const address8_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	address8_t&	operator=( const address8_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
	address8_t&	operator=( register8_t&	rhs );
private:
	// アドレスは必ず参照先があるので引数が必要
	address8_t();
};
struct address16_t {
	typedef unsigned_int16_t*	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	address16_t( value_type	value ):
	m_value(value)
	{
	}
	address16_t( const address16_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	address16_t&	operator=( const address16_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
	address16_t&	operator=( register16_t&	rhs );
private:
	// アドレスは必ず参照先があるので引数が必要
	address16_t();
};
struct address32_t {
	typedef signed_int32_t*	value_type;
protected:
	value_type	m_value;
public:
	operator value_type() const {
		return	m_value;
	}
	address32_t( value_type	value ):
	m_value(value)
	{
	}
	address32_t( const address32_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	address32_t&	operator=( const address32_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
	address32_t&	operator=( register32_t&	rhs );
private:
	// アドレスは必ず参照先があるので引数が必要
	address32_t();
};
template<typename register_type> struct indirect_t {
	typedef register_type*	value_type;
protected:
	value_type	m_value;
public:
	register_type&	operator*() const {
		return	*m_value;
	}
	indirect_t( value_type	value ):
	m_value(value)
	{
	}
	indirect_t( const indirect_t&	rhs ):
	m_value(rhs.m_value)
	{
	}
	indirect_t&	operator=( const register_type&	rhs ){
		*reinterpret_cast<typename register_type::value_type*>(static_cast<typename register_type::value_type>(*m_value)) = rhs;
		return	*this;
	}
private:
	// レジスタ間接参照は必ず参照先のレジスタがあるので引数が必要
	indirect_t();
};
struct register8_t {
	typedef unsigned_int8_t	value_type;
protected:
	register8_type	m_type;
	value_type&	m_value;
public:
	register8_t&	operator++(){
		++m_value;
		return	*this;
	}
	register8_t&	operator--(){
		--m_value;
		return	*this;
	}
	register8_t&	operator+=( value_type	d ){
		m_value += d;
		return	*this;
	}
	register8_t&	operator-=( value_type	d ){
		m_value -= d;
		return	*this;
	}
	register8_t&	operator=( value_type	rhs ){
		m_value = rhs;
		return	*this;
	}
	register8_t&	operator=( const immediate8_t&	rhs ){
		m_value = rhs;
		return	*this;
	}
	register8_t&	operator=( const address8_t&	rhs ){
		m_value = *rhs;
		return	*this;
	}
	operator value_type() const {
		return	m_value;
	}
	explicit register8_t( register8_type	type, value_type&	value ):
	m_type(type),
	m_value(value)
	{
	}
	register8_t&	operator=( register8_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// 8ビットレジスタは必ず 16ビットレジスタの一部なので独自の実体は持たない
	register8_t();
	// レジスタは必ず実体を持っているのでコピー禁止
	register8_t( const register8_t&	rhs );
};
struct register16_t {
	typedef unsigned_int16_t	value_type;
protected:
	register16_type	m_type;
	value_type&	m_value;
public:
	register16_t&	operator++(){
		++m_value;
		return	*this;
	}
	register16_t&	operator--(){
		--m_value;
		return	*this;
	}
	register16_t&	operator+=( value_type	d ){
		m_value += d;
		return	*this;
	}
	register16_t&	operator-=( value_type	d ){
		m_value -= d;
		return	*this;
	}
	register16_t&	operator=( value_type	rhs ){
		m_value = rhs;
		return	*this;
	}
	register16_t&	operator=( const immediate16_t&	rhs ){
		m_value = rhs;
		return	*this;
	}
	register16_t&	operator=( const address16_t&	rhs ){
		m_value = *rhs;
		return	*this;
	}
	operator value_type() const {
		return	m_value;
	}
	explicit register16_t( register16_type	type, value_type&	value ):
	m_type(type),
	m_value(value)
	{
	}
	register16_t&	operator=( register16_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// 16ビットレジスタは必ず 32ビットレジスタの一部なので独自の実体は持たない
	register16_t();
	// レジスタは必ず実体を持っているのでコピー禁止
	register16_t( const register16_t&	rhs );
};
struct register32_t {
	typedef signed_int32_t	value_type;
protected:
	register32_type	m_type;
	value_type	m_value;
public:
	register32_t&	operator++(){
		++m_value;
		return	*this;
	}
	register32_t&	operator--(){
		--m_value;
		return	*this;
	}
	register32_t&	operator+=( value_type	d ){
		m_value += d;
		return	*this;
	}
	register32_t&	operator-=( value_type	d ){
		m_value -= d;
		return	*this;
	}
	register32_t&	operator=( value_type	rhs ){
		m_value = rhs;
		return	*this;
	}
	register32_t&	operator=( const immediate32_t&	rhs ){
		m_value = rhs;
		return	*this;
	}
	register32_t&	operator=( const address32_t&	rhs ){
		m_value = *rhs;
		return	*this;
	}
	register32_t&	operator=( const indirect_t<register32_t>&	rhs ){
		m_value = *rhs;
		return	*this;
	}
	operator value_type() const {
		return	m_value;
	}
	indirect_t<register32_t>	operator*(){
		return	indirect_t<register32_t>(this);
	}
	register32_t( register32_type	type ):
	m_type(type),
	m_value()
	{
	}
	register32_t&	operator=( register32_t&	rhs ){
		if( this != &rhs ){
			m_value = rhs.m_value;
		}
		return	*this;
	}
private:
	// レジスタは必ずタイプを指定する
	register32_t();
	// レジスタは必ず実体を持っているのでコピー禁止
	register32_t( const register32_t&	rhs );
};
template<int _size> struct register_t;
template<> struct register_t<8> {
	typedef register8_t&	value_type;
protected:
	value_type	m_r;
public:
	operator value_type() const {
		return	m_r;
	}
	register_t( value_type	_r ):
	m_r(_r)
	{
	}
private:
	register_t();
	register_t&	operator=( const register_t& );
};
template<> struct register_t<16> {
	typedef register16_t&	value_type;
protected:
	value_type	m_r;
public:
	operator value_type() const {
		return	m_r;
	}
	register_t( value_type	_r ):
	m_r(_r)
	{
	}
private:
	register_t();
	register_t&	operator=( const register_t& );
};
template<> struct register_t<32> {
	typedef register32_t&	value_type;
protected:
	value_type	m_r;
public:
	operator value_type() const {
		return	m_r;
	}
	indirect_t<register32_t>	operator*() const {
		return	m_r.operator*();
	}
	register_t( value_type	_r ):
	m_r(_r)
	{
	}
private:
	register_t();
	register_t&	operator=( const register_t& );
};
inline address8_t&	address8_t::operator=( register8_t&	rhs ){
	*m_value = rhs;
	return	*this;
}
inline address16_t&	address16_t::operator=( register16_t&	rhs ){
	*m_value = rhs;
	return	*this;
}
inline address32_t&	address32_t::operator=( register32_t&	rhs ){
	*m_value = rhs;
	return	*this;
}
enum operand_type_t {
	operand_type_void,
	operand_type_register32,
	operand_type_register16,
	operand_type_register8,
	operand_type_address32,
	operand_type_address16,
	operand_type_address8,
	operand_type_immediate32,
	operand_type_immediate16,
	operand_type_immediate8,
	operand_type_register32_indirect,
	operand_types
};
struct operand_t {
	operand_type_t	type;
	union {
		register32_t*	r32;
		register16_t*	r16;
		register8_t*	r8;
		signed_int32_t*	p32;
		unsigned_int16_t*	p16;
		unsigned_int8_t*	p8;
		signed_int32_t	i32;
		unsigned_int16_t	i16;
		unsigned_int8_t	i8;
	};
	operand_t():
	type(operand_type_void)
	{
	}
	operand_t( register8_t&	_r ):
	type(operand_type_register8)
	{
		r8 = &_r;
	}
	operand_t( register16_t&	_r ):
	type(operand_type_register16)
	{
		r16 = &_r;
	}
	operand_t( register32_t&	_r ):
	type(operand_type_register32)
	{
		r32 = &_r;
	}
	operand_t( const address8_t&	_p ):
	type(operand_type_address8)
	{
		p8 = _p;
	}
	operand_t( const address16_t&	_p ):
	type(operand_type_address16)
	{
		p16 = _p;
	}
	operand_t( const address32_t&	_p ):
	type(operand_type_address32)
	{
		p32 = _p;
	}
	operand_t( const immediate8_t&	_i ):
	type(operand_type_immediate8)
	{
		i8 = _i;
	}
	operand_t( const immediate16_t&	_i ):
	type(operand_type_immediate16)
	{
		i16 = _i;
	}
	operand_t( const immediate32_t&	_i ):
	type(operand_type_immediate32)
	{
		i32 = _i;
	}
	operand_t( const indirect_t<register32_t>&	_r ):
	type(operand_type_register32_indirect)
	{
		r32 = &*_r;
	}
	operand_t( const register_t<8>&	_r ):
	type(operand_type_register8)
	{
		r8 = &static_cast<register8_t&>(_r);
	}
	operand_t( const register_t<16>&	_r ):
	type(operand_type_register16)
	{
		r16 = &static_cast<register16_t&>(_r);
	}
	operand_t( const register_t<32>&	_r ):
	type(operand_type_register32)
	{
		r32 = &static_cast<register32_t&>(_r);
	}
	operator register8_t&() const {
		return	*r8;
	}
	operator register16_t&() const {
		return	*r16;
	}
	operator register32_t&() const {
		return	*r32;
	}
	operator address8_t() const {
		return	p8;
	}
	operator address16_t() const {
		return	p16;
	}
	operator address32_t() const {
		return	p32;
	}
	operator immediate8_t() const {
		return	i8;
	}
	operator immediate16_t() const {
		return	i16;
	}
	operator immediate32_t() const {
		return	i32;
	}
	operator indirect_t<register32_t>() const {
		return	r32;
	}
};
template<typename T> struct operand_traits_t {
	typedef void	output_argument_type;
	typedef void	input_argument_type;
	typedef void	value_type;
	static const int	type = operand_type_void;
};
template<> struct operand_traits_t<indirect_t<register32_t> > {
	typedef indirect_t<register32_t>	output_argument_type;
	typedef const indirect_t<register32_t>&	input_argument_type;
	typedef register32_t::value_type	value_type;
	static const int	type = operand_type_register32_indirect;
};
template<> struct operand_traits_t<register_t<8> > {
	typedef register8_t&	output_argument_type;
	typedef register8_t&	input_argument_type;
	typedef register8_t::value_type	value_type;
	static const int	type = operand_type_register32;
};
template<> struct operand_traits_t<register_t<16> > {
	typedef register16_t&	output_argument_type;
	typedef register16_t&	input_argument_type;
	typedef register16_t::value_type	value_type;
	static const int	type = operand_type_register16;
};
template<> struct operand_traits_t<register_t<32> > {
	typedef register32_t&	output_argument_type;
	typedef register32_t&	input_argument_type;
	typedef register32_t::value_type	value_type;
	static const int	type = operand_type_register8;
};
template<> struct operand_traits_t<register32_t> {
	typedef register32_t&	output_argument_type;
	typedef register32_t&	input_argument_type;
	typedef register32_t::value_type	value_type;
	static const int	type = operand_type_register32;
};
template<> struct operand_traits_t<register16_t> {
	typedef register16_t&	output_argument_type;
	typedef register16_t&	input_argument_type;
	typedef register16_t::value_type	value_type;
	static const int	type = operand_type_register16;
};
template<> struct operand_traits_t<register8_t> {
	typedef register8_t&	output_argument_type;
	typedef register8_t&	input_argument_type;
	typedef register8_t::value_type	value_type;
	static const int	type = operand_type_register8;
};
template<> struct operand_traits_t<register32_t&> {
	typedef register32_t&	output_argument_type;
	typedef register32_t&	input_argument_type;
	typedef register32_t::value_type	value_type;
	static const int	type = operand_type_register32;
};
template<> struct operand_traits_t<register16_t&> {
	typedef register16_t&	output_argument_type;
	typedef register16_t&	input_argument_type;
	typedef register16_t::value_type	value_type;
	static const int	type = operand_type_register16;
};
template<> struct operand_traits_t<register8_t&> {
	typedef register8_t&	output_argument_type;
	typedef register8_t&	input_argument_type;
	typedef register8_t::value_type	value_type;
	static const int	type = operand_type_register8;
};
template<> struct operand_traits_t<address32_t> {
	typedef address32_t	output_argument_type;
	typedef const address32_t&	input_argument_type;
	typedef signed_int32_t*	value_type;
	static const int	type = operand_type_address32;
};
template<> struct operand_traits_t<address16_t> {
	typedef address16_t	output_argument_type;
	typedef const address16_t&	input_argument_type;
	typedef unsigned_int16_t*	value_type;
	static const int	type = operand_type_address16;
};
template<> struct operand_traits_t<address8_t> {
	typedef address8_t	output_argument_type;
	typedef const address8_t&	input_argument_type;
	typedef unsigned_int8_t*	value_type;
	static const int	type = operand_type_address8;
};
template<> struct operand_traits_t<const address32_t&> {
	typedef address32_t	output_argument_type;
	typedef const address32_t&	input_argument_type;
	typedef signed_int32_t*	value_type;
	static const int	type = operand_type_address32;
};
template<> struct operand_traits_t<const address16_t&> {
	typedef address16_t	output_argument_type;
	typedef const address16_t&	input_argument_type;
	typedef unsigned_int16_t*	value_type;
	static const int	type = operand_type_address16;
};
template<> struct operand_traits_t<const address8_t&> {
	typedef address8_t	output_argument_type;
	typedef const address8_t&	input_argument_type;
	typedef unsigned_int8_t*	value_type;
	static const int	type = operand_type_address8;
};
template<> struct operand_traits_t<signed_int32_t*> {
	typedef address32_t	output_argument_type;
	typedef const address32_t&	input_argument_type;
	typedef signed_int32_t*	value_type;
	static const int	type = operand_type_address32;
};
template<> struct operand_traits_t<unsigned_int16_t*> {
	typedef address16_t	output_argument_type;
	typedef const address16_t&	input_argument_type;
	typedef unsigned_int16_t*	value_type;
	static const int	type = operand_type_address16;
};
template<> struct operand_traits_t<unsigned_int8_t*> {
	typedef address8_t	output_argument_type;
	typedef const address8_t&	input_argument_type;
	typedef unsigned_int8_t*	value_type;
	static const int	type = operand_type_address8;
};
template<> struct operand_traits_t<immediate32_t> {
	typedef void	output_argument_type;
	typedef const immediate32_t&	input_argument_type;
	typedef signed_int32_t	value_type;
	static const int	type = operand_type_immediate32;
};
template<> struct operand_traits_t<immediate16_t> {
	typedef void	output_argument_type;
	typedef const immediate16_t&	input_argument_type;
	typedef unsigned_int16_t	value_type;
	static const int	type = operand_type_immediate16;
};
template<> struct operand_traits_t<immediate8_t> {
	typedef void	output_argument_type;
	typedef const immediate8_t&	input_argument_type;
	typedef unsigned_int8_t	value_type;
	static const int	type = operand_type_immediate8;
};
template<> struct operand_traits_t<const immediate32_t&> {
	typedef void	output_argument_type;
	typedef const immediate32_t&	input_argument_type;
	typedef signed_int32_t	value_type;
	static const int	type = operand_type_immediate32;
};
template<> struct operand_traits_t<const immediate16_t&> {
	typedef void	output_argument_type;
	typedef const immediate16_t&	input_argument_type;
	typedef unsigned_int16_t	value_type;
	static const int	type = operand_type_immediate16;
};
template<> struct operand_traits_t<const immediate8_t&> {
	typedef void	output_argument_type;
	typedef const immediate8_t&	input_argument_type;
	typedef unsigned_int8_t	value_type;
	static const int	type = operand_type_immediate8;
};
template<> struct operand_traits_t<signed_int32_t> {
	typedef void	output_argument_type;
	typedef const immediate32_t&	input_argument_type;
	typedef signed_int32_t	value_type;
	static const int	type = operand_type_immediate32;
};
template<> struct operand_traits_t<unsigned_int16_t> {
	typedef void	output_argument_type;
	typedef const immediate16_t&	input_argument_type;
	typedef unsigned_int16_t	value_type;
	static const int	type = operand_type_immediate16;
};
template<> struct operand_traits_t<unsigned_int8_t> {
	typedef void	output_argument_type;
	typedef const immediate8_t&	input_argument_type;
	typedef unsigned_int8_t	value_type;
	static const int	type = operand_type_immediate8;
};
template<bool _value> struct bool_type {
	static const bool	value = _value;
};
template<typename argument_type, int = operand_traits_t<argument_type>::type> struct is_register : public bool_type<false> {};
template<typename argument_type> struct is_register<argument_type,operand_type_register32> : public  bool_type<true> {};
template<typename argument_type> struct is_register<argument_type,operand_type_register16> : public  bool_type<true> {};
template<typename argument_type> struct is_register<argument_type,operand_type_register8> : public  bool_type<true> {};
template<typename argument_type, int = operand_traits_t<argument_type>::type> struct is_address : public bool_type<false> {};
template<typename argument_type> struct is_address<argument_type,operand_type_address32> : public  bool_type<true> {};
template<typename argument_type> struct is_address<argument_type,operand_type_address16> : public  bool_type<true> {};
template<typename argument_type> struct is_address<argument_type,operand_type_address8> : public  bool_type<true> {};
template<typename argument_type, int = operand_traits_t<argument_type>::type> struct is_immediate : public bool_type<false> {};
template<typename argument_type> struct is_immediate<argument_type,operand_type_immediate32> : public  bool_type<true> {};
template<typename argument_type> struct is_immediate<argument_type,operand_type_immediate16> : public  bool_type<true> {};
template<typename argument_type> struct is_immediate<argument_type,operand_type_immediate8> : public  bool_type<true> {};

enum opcode_t {
	opcode_nop,
	opcode_mov,
	opcode_lea,
	opcode_inc,
	opcode_dec,
	opcode_jmp,
	opcode_jz,
	opcode_jnz,
	opcode_push,
	opcode_pop,
	opcode_call,
	opcode_ret,
	opcodes
};
class mnemonic_t {
protected:
	typedef void	(*callback0_t)( vm_t&, opcode_t );
	typedef void	(*callback1_t)( vm_t&, opcode_t, const operand_t& );
	typedef void	(*callback2_t)( vm_t&, opcode_t, const operand_t&, const operand_t& );
	typedef void	(*callback3_t)( vm_t&, opcode_t, const operand_t&, const operand_t&, const operand_t& );
	struct callback_t {
		callback0_t	m_callback;
	public:
		void	operator()( vm_t&	vm, opcode_t	opcode ){
			m_callback( vm, opcode );
		}
		void	operator()( vm_t&	vm, opcode_t	opcode, const operand_t&	operand1 ){
			reinterpret_cast<callback1_t>(m_callback)( vm, opcode, operand1 );
		}
		void	operator()( vm_t&	vm, opcode_t	opcode, const operand_t&	operand1, const operand_t&	operand2 ){
			reinterpret_cast<callback2_t>(m_callback)( vm, opcode, operand1, operand2 );
		}
		void	operator()( vm_t&	vm, opcode_t	opcode, const operand_t&	operand1, const operand_t&	operand2, const operand_t&	operand3 ){
			reinterpret_cast<callback3_t>(m_callback)( vm, opcode, operand1, operand2, operand3 );
		}
		callback_t( callback0_t	callback ):
		m_callback(callback)
		{
		}
		callback_t( callback1_t	callback ):
		m_callback(reinterpret_cast<callback0_t>(callback))
		{
		}
		callback_t( callback2_t	callback ):
		m_callback(reinterpret_cast<callback0_t>(callback))
		{
		}
		callback_t( callback3_t	callback ):
		m_callback(reinterpret_cast<callback0_t>(callback))
		{
		}
	};
	callback_t	m_callback;
	opcode_t	m_opcode;
	std::vector<operand_t>	m_operands;
public:
	opcode_t	opcode() const {
		return	m_opcode;
	}
	const operand_t&	operand( size_t	n ) const {
		return	m_operands[n];
	}
	const operand_t&	operator[]( size_t	n ) const {
		return	m_operands[n];
	}
	size_t	size() const {
		return	m_operands.size();
	}
	mnemonic_t( callback0_t	callback, opcode_t	opcode ):
	m_callback(callback),
	m_opcode(opcode)
	{
	}
	mnemonic_t( callback1_t	callback, opcode_t	opcode, const operand_t&	operand1 ):
	m_callback(callback),
	m_opcode(opcode)
	{
		m_operands.push_back( operand1 );
	}
	mnemonic_t( callback2_t	callback, opcode_t	opcode, const operand_t&	operand1, const operand_t&	operand2 ):
	m_callback(callback),
	m_opcode(opcode)
	{
		m_operands.push_back( operand1 );
		m_operands.push_back( operand2 );
	}
	mnemonic_t( callback3_t	callback, opcode_t	opcode, const operand_t&	operand1, const operand_t&	operand2, const operand_t&	operand3 ):
	m_callback(callback),
	m_opcode(opcode)
	{
		m_operands.push_back( operand1 );
		m_operands.push_back( operand2 );
		m_operands.push_back( operand3 );
	}
	void	exec( vm_t&	vm ){
		if( m_operands.empty()){
			m_callback( vm, m_opcode );
		}
		else if( m_operands.size() == 1 ){
			m_callback( vm, m_opcode, m_operands[0] );
		}
		else if( m_operands.size() == 2 ){
			m_callback( vm, m_opcode, m_operands[0], m_operands[1] );
		}
		else if( m_operands.size() == 3 ){
			m_callback( vm, m_opcode, m_operands[0], m_operands[1], m_operands[2] );
		}
	}
};
struct eax_t : public register32_t {
	struct ax_t : public register16_t {
		register8_t	al_;
		register8_t	ah_;
		
		ax_t( unsigned_int16_t&	value ):
		register16_t(register16_type_ax,value),
		al_(register8_type_al,reinterpret_cast<union_int16_t&>(value).h[0]),
		ah_(register8_type_ah,reinterpret_cast<union_int16_t&>(value).h[1])
		{
		}
		using register16_t::operator=;
	};
	ax_t	ax_;
	
	eax_t():
	register32_t(register32_type_eax),
	ax_(reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct ebx_t : public register32_t {
	struct bx_t : public register16_t {
		register8_t	bl_;
		register8_t	bh_;
		
		bx_t( unsigned_int16_t&	value ):
		register16_t(register16_type_bx,value),
		bl_(register8_type_bl,reinterpret_cast<union_int16_t&>(value).h[0]),
		bh_(register8_type_bh,reinterpret_cast<union_int16_t&>(value).h[1])
		{
		}
		using register16_t::operator=;
	};
	bx_t	bx_;
	
	ebx_t():
	register32_t(register32_type_ebx),
	bx_(reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct ecx_t : public register32_t {
	struct cx_t : public register16_t {
		register8_t	cl_;
		register8_t	ch_;
		
		cx_t( unsigned_int16_t&	value ):
		register16_t(register16_type_cx,value),
		cl_(register8_type_cl,reinterpret_cast<union_int16_t&>(value).h[0]),
		ch_(register8_type_ch,reinterpret_cast<union_int16_t&>(value).h[1])
		{
		}
		using register16_t::operator=;
	};
	cx_t	cx_;
	
	ecx_t():
	register32_t(register32_type_ecx),
	cx_(reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct edx_t : public register32_t {
	struct dx_t : public register16_t {
		register8_t	dl_;
		register8_t	dh_;
		
		dx_t( unsigned_int16_t&	value ):
		register16_t(register16_type_dx,value),
		dl_(register8_type_dl,reinterpret_cast<union_int16_t&>(value).h[0]),
		dh_(register8_type_dh,reinterpret_cast<union_int16_t&>(value).h[1])
		{
		}
		using register16_t::operator=;
	};
	dx_t	dx_;
	
	edx_t():
	register32_t(register32_type_edx),
	dx_(reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct esi_t : public register32_t {
	register16_t	si_;
	
	esi_t():
	register32_t(register32_type_esi),
	si_(register16_type_si,reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct edi_t : public register32_t {
	register16_t	di_;
	
	edi_t():
	register32_t(register32_type_edi),
	di_(register16_type_di,reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct ebp_t : public register32_t {
	register16_t	bp_;
	
	ebp_t():
	register32_t(register32_type_ebp),
	bp_(register16_type_bp,reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct esp_t : public register32_t {
	register16_t	sp_;
	
	esp_t():
	register32_t(register32_type_esp),
	sp_(register16_type_sp,reinterpret_cast<union_int32_t&>(m_value).x[0])
	{
	}
	using register32_t::operator=;
};
struct eip_t : public register32_t {
	eip_t():
	register32_t(register32_type_eip)
	{
	}
	using register32_t::operator=;
};
#define	CFLAGS_CF	0x00000001	// キャリーフラグ
#define	CFLAGS_PF	0x00000004	// パリティフラグ
#define	CFLAGS_ZF	0x00000040	// ゼロフラグ
#define	CFLAGS_SF	0x00000080	// サインフラグ
#define	CFLAGS_OF	0x00000800	// オーバーフローフラグ
#define	EFLAGS_CF	CFLAGS_CF
#define	EFLAGS_PF	CFLAGS_PF
#define	EFLAGS_ZF	CFLAGS_ZF
#define	EFLAGS_SF	CFLAGS_SF
#define	EFLAGS_OF	CFLAGS_OF
#if	!defined( _BIT_COUNT_ )
inline unsigned_int8_t	bit_count_population8( unsigned_int8_t	b ) {
	b = static_cast<unsigned_int8_t>(( b & 0x55 ) + (( b >> 1 ) & 0x55 ));	// 01010101
	b = static_cast<unsigned_int8_t>(( b & 0x33 ) + (( b >> 2 ) & 0x33 ));	// 00110011
	b = static_cast<unsigned_int8_t>(( b & 0x0f ) + (( b >> 4 ) & 0x0f ));	// 00001111
	return	b;
}
#endif // _BIT_COUNT_
class eflags_t : public register32_t {
	struct cflags_t : public register16_t {
		cflags_t( unsigned_int16_t&	value ):register16_t(register16_type_cflags,value){}
		
		bool	cf() const {
			return	!!( m_value & CFLAGS_CF );
		}
		bool	pf() const {
			return	!!( m_value & CFLAGS_PF );
		}
		bool	zf() const {
			return	!!( m_value & CFLAGS_ZF );
		}
		bool	sf() const {
			return	!!( m_value & CFLAGS_SF );
		}
		bool	of() const {
			return	!!( m_value & CFLAGS_OF );
		}
	};
	cflags_t	m_cflags;
public:
	eflags_t():register32_t(register32_type_eflags),m_cflags(reinterpret_cast<union_int32_t&>(m_value).x[0]){}
	
	bool	cf() const {
		return	m_cflags.cf();
	}
	bool	pf() const {
		return	m_cflags.pf();
	}
	bool	zf() const {
		return	m_cflags.zf();
	}
	bool	sf() const {
		return	m_cflags.sf();
	}
	bool	of() const {
		return	m_cflags.of();
	}
	void	cmp1( signed_int32_t	value, signed_int32_t	mask ){
		signed_int32_t	flags = 0;
		if( mask & CFLAGS_ZF ){
			if( !value ){
				flags |= CFLAGS_ZF;
			}
		}
		if( mask & CFLAGS_SF ){
			if( value < 0 ){
				flags |= CFLAGS_SF;
			}
		}
		if( mask & CFLAGS_PF ){
			if( ~bit_count_population8( reinterpret_cast<union_int32_t&>(value).h[0] ) & 1 ){
				flags |= CFLAGS_PF;
			}
		}
		m_value = ( m_value & ~mask ) | ( flags & mask );
	}
	void	cmp2( signed_int32_t	lhs, signed_int32_t	rhs, signed_int32_t	mask ){
		cmp1( lhs, mask & (CFLAGS_ZF|CFLAGS_SF|CFLAGS_PF));
		mask &= ~(CFLAGS_ZF|CFLAGS_SF|CFLAGS_PF);

		signed_int32_t	flags = 0;
		if( mask & CFLAGS_OF ){
			// true : 0x7ffffffff <-> 0x800000000
			if( static_cast<signed_int32_t>( static_cast<unsigned_int32_t>(lhs) ^ static_cast<unsigned_int32_t>(rhs)) < 0 ){
				flags |= CFLAGS_OF;
			}
		}
		m_value = ( m_value & ~mask ) | ( flags & mask );
	}
	void	cmp3( signed_int32_t	lhs, signed_int32_t	rhs, signed_int32_t	d, signed_int32_t	mask ){
		cmp2( lhs, rhs, mask & (CFLAGS_ZF|CFLAGS_SF|CFLAGS_PF|CFLAGS_OF));
		mask &= ~(CFLAGS_ZF|CFLAGS_SF|CFLAGS_PF|CFLAGS_OF);

		signed_int32_t	flags = 0;
		if( mask & CFLAGS_CF ){
			// true : 0xffffffff <-> 0x00000000
			if(( static_cast<unsigned_int32_t>(lhs) < static_cast<unsigned_int32_t>(rhs)) != ( d < 0 )){
				flags |= CFLAGS_CF;
			}
		}
		m_value = ( m_value & ~mask ) | ( flags & mask );
	}
	using register32_t::operator=;
};
class vm_t {
protected:
	eax_t	m_eax;
	ebx_t	m_ebx;
	ecx_t	m_ecx;
	edx_t	m_edx;
	esi_t	m_esi;
	edi_t	m_edi;
	ebp_t	m_ebp;
	esp_t	m_esp;
	eip_t	m_eip;
	eflags_t	m_eflags;
	char	m_stack[1024];
public:
	register32_t&	eax_(){ return m_eax; }
	register32_t&	ebx_(){ return m_ebx; }
	register32_t&	ecx_(){ return m_ecx; }
	register32_t&	edx_(){ return m_edx; }
	register32_t&	esi_(){ return m_esi; }
	register32_t&	edi_(){ return m_edi; }
	register32_t&	ebp_(){ return m_ebp; }
	register32_t&	esp_(){ return m_esp; }
	register16_t&	ax_(){ return m_eax.ax_; }
	register16_t&	bx_(){ return m_ebx.bx_; }
	register16_t&	cx_(){ return m_ecx.cx_; }
	register16_t&	dx_(){ return m_edx.dx_; }
	register16_t&	si_(){ return m_esi.si_; }
	register16_t&	di_(){ return m_edi.di_; }
	register16_t&	bp_(){ return m_ebp.bp_; }
	register8_t&	al_(){ return m_eax.ax_.al_; }
	register8_t&	ah_(){ return m_eax.ax_.ah_; }
	register8_t&	bl_(){ return m_ebx.bx_.bl_; }
	register8_t&	bh_(){ return m_ebx.bx_.bh_; }
	register8_t&	cl_(){ return m_ecx.cx_.cl_; }
	register8_t&	ch_(){ return m_ecx.cx_.ch_; }
	register8_t&	dl_(){ return m_edx.dx_.dl_; }
	register8_t&	dh_(){ return m_edx.dx_.dh_; }
	
	void	cmp1( signed_int32_t	value, signed_int32_t	flags = EFLAGS_PF|EFLAGS_ZF|EFLAGS_SF ){
		m_eflags.cmp1( value, flags );
	}
	void	cmp2( signed_int32_t	lhs, signed_int32_t	rhs, signed_int32_t	flags = EFLAGS_PF|EFLAGS_ZF|EFLAGS_SF|EFLAGS_OF ){
		m_eflags.cmp2( lhs, rhs, flags );
	}
	void	cmp3( signed_int32_t	lhs, signed_int32_t	rhs, signed_int32_t	d, signed_int32_t	flags = EFLAGS_PF|EFLAGS_ZF|EFLAGS_SF|EFLAGS_OF|EFLAGS_CF ){
		m_eflags.cmp3( lhs, rhs, d, flags );
	}
	void	reset(){
		m_eax = 0;
		m_ebx = 0;
		m_ecx = 0;
		m_edx = 0;
		m_esi = 0;
		m_edi = 0;
		m_ebp = 0;
		m_esp = reinterpret_cast<int>(&m_stack[sizeof(m_stack)]);
		m_eip = 0;
		m_eflags = 0;
	}
	void	exec( asm_t& );
	vm_t():
	m_eax(),
	m_ebx(),
	m_ecx(),
	m_edx(),
	m_esi(),
	m_edi(),
	m_ebp(),
	m_esp(),
	m_eip(),
	m_eflags(),
	m_stack()
	{
		reset();
	}
	void	nop(){
		++m_eip;
	}
	template<typename first_argument_type, typename second_argument_type> void	mov( first_argument_type	lhs, second_argument_type	rhs ){
		lhs = rhs;
		++m_eip;
	}
	template<typename first_argument_type, typename second_argument_type> void	lea( first_argument_type	lhs, second_argument_type	rhs ){
		union {
			typename operand_traits_t<second_argument_type>::value_type	rhs;
			typename operand_traits_t<first_argument_type>::value_type	lhs;
		} temp = { rhs };
		lhs = temp.lhs;
		++m_eip;
	}
	template<typename argument_type> void	inc( argument_type	operand ){
		typename operand_traits_t<argument_type>::value_type	prev = operand;
		++operand;
		cmp2( operand, prev );
		++m_eip;
	}
	template<typename argument_type> void	dec( argument_type	operand ){
		typename operand_traits_t<argument_type>::value_type	prev = operand;
		--operand;
		cmp2( operand, prev );
		++m_eip;
	}
	template<typename argument_type> void	jmp( argument_type	ip ){
		m_eip = ip;
	}
	template<typename argument_type> void	jz( argument_type	ip ){
		if( m_eflags.zf()){
			m_eip = ip;
		}
		else{
			++m_eip;
		}
	}
	template<typename argument_type> void	jnz( argument_type	ip ){
		if( !m_eflags.zf()){
			m_eip = ip;
		}
		else{
			++m_eip;
		}
	}
	template<typename argument_type> void	push( argument_type	r ){
		m_esp -= sizeof( typename operand_traits_t<argument_type>::value_type );
		*m_esp = r;
		++m_eip;
	}
	template<typename argument_type> void	pop( argument_type	r ){
		r = *reinterpret_cast<typename operand_traits_t<argument_type>::value_type*>(static_cast<signed_int32_t>(m_esp));
		m_esp += sizeof( typename operand_traits_t<argument_type>::value_type );
		++m_eip;
	}
	template<typename argument_type> void	call( argument_type	target ){
		push<register32_t&>( m_eip );
		jmp<argument_type>( target );
	}
	void	ret(){
		pop<register32_t&>( m_eip );
	}
};
// nop();
struct mnemonic_nop_t : public mnemonic_t {
	mnemonic_nop_t():mnemonic_t(nop,opcode_nop){}
	static void	nop( vm_t&	vm, opcode_t ){
		vm.nop();
	}
};
// mov( イミディエイト以外, なんでも );
template<typename first_argument_type, typename second_argument_type> struct mnemonic_mov_t : public mnemonic_t {
	mnemonic_mov_t( typename operand_traits_t<first_argument_type>::output_argument_type	lhs, typename operand_traits_t<second_argument_type>::input_argument_type	rhs ):mnemonic_t(mov,opcode_mov,lhs,rhs){}
	static void	mov( vm_t&	vm, opcode_t, const operand_t&	lhs, const operand_t&	rhs ){
		vm.mov<typename operand_traits_t<first_argument_type>::output_argument_type, typename operand_traits_t<second_argument_type>::input_argument_type>( lhs, rhs );
	}
};
// lea( レジスタ, アドレス );
template<typename first_argument_type, typename second_argument_type> struct mnemonic_lea_t : public mnemonic_t {
	mnemonic_lea_t( typename operand_traits_t<first_argument_type>::output_argument_type	lhs, typename operand_traits_t<second_argument_type>::input_argument_type	rhs ):mnemonic_t(lea,opcode_lea,lhs,rhs){}
	static void	lea( vm_t&	vm, opcode_t, const operand_t&	lhs, const operand_t&	rhs ){
		vm.lea<typename operand_traits_t<first_argument_type>::output_argument_type, typename operand_traits_t<second_argument_type>::input_argument_type>( lhs, rhs );
	}
};
// inc( レジスタ );
template<typename argument_type, bool = is_register<argument_type>::value> struct mnemonic_inc_t;
template<typename argument_type> struct mnemonic_inc_t<argument_type,true> : public mnemonic_t {
	mnemonic_inc_t( typename operand_traits_t<argument_type>::output_argument_type	operand ):mnemonic_t(inc,opcode_inc,operand){}
	static void	inc( vm_t&	vm, opcode_t, const operand_t&	operand ){
		vm.inc<typename operand_traits_t<argument_type>::output_argument_type>( operand );
	}
};
// dec( レジスタ );
template<typename argument_type, bool = is_register<argument_type>::value> struct mnemonic_dec_t;
template<typename argument_type> struct mnemonic_dec_t<argument_type,true> : public mnemonic_t {
	mnemonic_dec_t( typename operand_traits_t<argument_type>::output_argument_type	operand ):mnemonic_t(dec,opcode_dec,operand){}
	static void	dec( vm_t&	vm, opcode_t, const operand_t&	operand ){
		vm.dec<typename operand_traits_t<argument_type>::output_argument_type>( operand );
	}
};
// jmp( なんでも );
template<typename argument_type> struct mnemonic_jmp_t : public mnemonic_t {
	mnemonic_jmp_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(jmp,opcode_jmp,target){}
	static void	jmp( vm_t&	vm, opcode_t, const operand_t&	target ){
		vm.jmp<typename operand_traits_t<argument_type>::input_argument_type>( target );
	}
};
// jz( なんでも );
template<typename argument_type> struct mnemonic_jz_t : public mnemonic_t {
	mnemonic_jz_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(jz,opcode_jz,target){}
	static void	jz( vm_t&	vm, opcode_t, const operand_t&	target ){
		vm.jz<typename operand_traits_t<argument_type>::input_argument_type>( target );
	}
};
// jnz( なんでも );
template<typename argument_type> struct mnemonic_jnz_t : public mnemonic_t {
	mnemonic_jnz_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(jnz,opcode_jnz,target){}
	static void	jnz( vm_t&	vm, opcode_t, const operand_t&	target ){
		vm.jnz<typename operand_traits_t<argument_type>::input_argument_type>( target );
	}
};
// push( レジスタ );
template<typename argument_type> struct mnemonic_push_t : public mnemonic_t {
	mnemonic_push_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(push,opcode_push,target){}
	static void	push( vm_t&	vm, opcode_t, const operand_t&	value ){
		vm.push<typename operand_traits_t<argument_type>::input_argument_type>( value );
	}
};
// pop( レジスタ );
template<typename argument_type> struct mnemonic_pop_t : public mnemonic_t {
	mnemonic_pop_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(pop,opcode_pop,target){}
	static void	pop( vm_t&	vm, opcode_t, const operand_t&	value ){
		vm.pop<typename operand_traits_t<argument_type>::input_argument_type>( value );
	}
};
// call( レジスタかアドレス );
template<typename argument_type> struct mnemonic_call_t : public mnemonic_t {
	mnemonic_call_t( typename operand_traits_t<argument_type>::input_argument_type	target ):mnemonic_t(call,opcode_call,target){}
	static void	call( vm_t&	vm, opcode_t, const operand_t&	value ){
		vm.call<typename operand_traits_t<argument_type>::input_argument_type>( value );
	}
};
// ret();
struct mnemonic_ret_t : public mnemonic_t {
	mnemonic_ret_t():mnemonic_t(ret,opcode_ret){}
	static void	ret( vm_t&	vm, opcode_t ){
		vm.ret();
	}
};

class asm_t {
	std::vector<mnemonic_t>	m_mnemonics;
public:
	void	nop(){
		m_mnemonics.push_back( mnemonic_nop_t());
	}
	template<typename first_argument_type, typename second_argument_type> void	mov( first_argument_type	lhs, second_argument_type	rhs ){
		m_mnemonics.push_back( mnemonic_mov_t<first_argument_type,second_argument_type>( lhs, rhs ));
	}
	template<typename first_argument_type, typename second_argument_type> void	lea( first_argument_type	lhs, second_argument_type	rhs ){
		m_mnemonics.push_back( mnemonic_lea_t<first_argument_type,second_argument_type>( lhs, rhs ));
	}
	template<typename argument_type> void	inc( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_inc_t<argument_type>( operand ));
	}
	template<typename argument_type> void	dec( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_dec_t<argument_type>( operand ));
	}
	template<typename argument_type> void	jmp( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_jmp_t<argument_type>( operand ));
	}
	template<typename argument_type> void	jz( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_jz_t<argument_type>( operand ));
	}
	template<typename argument_type> void	jnz( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_jnz_t<argument_type>( operand ));
	}
	template<typename argument_type> void	push( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_push_t<argument_type>( operand ));
	}
	template<typename argument_type> void	pop( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_pop_t<argument_type>( operand ));
	}
	template<typename argument_type> void	call( argument_type	operand ){
		m_mnemonics.push_back( mnemonic_call_t<argument_type>( operand ));
	}
	void	ret(){
		m_mnemonics.push_back( mnemonic_ret_t());
	}
	
	signed_int32_t	label() const {
		return	static_cast<signed_int32_t>(m_mnemonics.size());
	}
	
	size_t	size() const {
		return	m_mnemonics.size();
	}
	mnemonic_t&	at( register32_t&	ip ){
		return	m_mnemonics[ip];
	}
	
	asm_t():
	m_mnemonics()
	{
	}
};
void	vm_t::exec( asm_t&	asm_ ){
	while( static_cast<size_t>(static_cast<signed_int32_t>(m_eip)) < asm_.size()){
		asm_.at( m_eip ).exec( *this );
	}
}
使用例その1
#if	!defined( UNREFERENCED_PARAMETER )
#define	UNREFERENCED_PARAMETER(a)	(void)a
#endif // UNREFERENCED_PARAMETER

int	main(){
	vm_t	vm;
	register_t<32>	eax_ = vm.eax_();
	register_t<32>	ebx_ = vm.ebx_();
	register_t<32>	ecx_ = vm.ecx_();
	register_t<32>	edx_ = vm.edx_();
	register_t<32>	esi_ = vm.esi_();
	register_t<32>	edi_ = vm.edi_();
	register_t<32>	ebp_ = vm.ebp_();
	register_t<32>	esp_ = vm.esp_();
	register_t<16>	ax_ = vm.ax_();
	register_t<16>	bx_ = vm.bx_();
	register_t<16>	cx_ = vm.cx_();
	register_t<16>	dx_ = vm.dx_();
	register_t<16>	si_ = vm.si_();
	register_t<16>	di_ = vm.di_();
	register_t<16>	bp_ = vm.bp_();
	register_t<8>	al_ = vm.al_();
	register_t<8>	ah_ = vm.ah_();
	register_t<8>	bl_ = vm.bl_();
	register_t<8>	bh_ = vm.bh_();
	register_t<8>	cl_ = vm.cl_();
	register_t<8>	ch_ = vm.ch_();
	register_t<8>	dl_ = vm.dl_();
	register_t<8>	dh_ = vm.dh_();
	UNREFERENCED_PARAMETER( eax_ );
	UNREFERENCED_PARAMETER( ebx_ );
	UNREFERENCED_PARAMETER( ecx_ );
	UNREFERENCED_PARAMETER( edx_ );
	UNREFERENCED_PARAMETER( esi_ );
	UNREFERENCED_PARAMETER( edi_ );
	UNREFERENCED_PARAMETER( ebp_ );
	UNREFERENCED_PARAMETER( esp_ );
	UNREFERENCED_PARAMETER( ax_ );
	UNREFERENCED_PARAMETER( bx_ );
	UNREFERENCED_PARAMETER( cx_ );
	UNREFERENCED_PARAMETER( dx_ );
	UNREFERENCED_PARAMETER( si_ );
	UNREFERENCED_PARAMETER( di_ );
	UNREFERENCED_PARAMETER( bp_ );
	UNREFERENCED_PARAMETER( al_ );
	UNREFERENCED_PARAMETER( ah_ );
	UNREFERENCED_PARAMETER( bl_ );
	UNREFERENCED_PARAMETER( bh_ );
	UNREFERENCED_PARAMETER( cl_ );
	UNREFERENCED_PARAMETER( ch_ );
	UNREFERENCED_PARAMETER( dl_ );
	UNREFERENCED_PARAMETER( dh_ );

	asm_t	asm_;
	
	signed_int32_t	a = 0;
	asm_.mov( ebx_, 100 );
	asm_.lea( ecx_, &a );
	asm_.mov( *ecx_, ebx_ );

	asm_.mov( al_, 3 );
	signed_int32_t	label0 = asm_.label();
	asm_.dec( al_ );
	asm_.jnz( label0 );
	
	asm_.push( ebx_ );
	asm_.pop( eax_ );

	vm.exec( asm_ );
	return	0;
}
使用例その2
int	main(){
	vm_t	vm;
	register_t<8>	al_ = vm.al_();

	asm_t	asm_;
	
	asm_.mov( al_, 3 );
	signed_int32_t	label0 = asm_.label();
	asm_.dec( al_ );
	signed_int32_t	label1 = 0;
	asm_.jz( &label1 );
	asm_.jmp( label0 );
	label1 = asm_.label();
	
	vm.exec( asm_ );
	return	0;
}
使用例その3
int	main(){
	vm_t	vm;
	register_t<32>	eax_ = vm.eax_();
	register_t<32>	ebx_ = vm.ebx_();

	asm_t	asm_;
	
	signed_int32_t	label2 = 0;
	signed_int32_t	label3 = 0;
	asm_.mov( ebx_, 100 );
	asm_.call( &label2 );
	asm_.jmp( &label3 );

	label2 = asm_.label();
	asm_.push( ebx_ );
	asm_.pop( eax_ );
	asm_.ret();
	
	label3 = asm_.label();
	asm_.mov( ebx_, 10 );
	
	vm.exec( asm_ );
	return	0;
}

どうでしょう
こうして実際に自分で書いてみるともうアセンブラなんて簡単じゃないですか?

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