ポインタのコア

  目次

アセンブラを読む
ポインタ表現によるデータのセット
ポインタで関数を呼び出す
インラインアセンブラで書く



  アセンブラを読む



プロジェクトの設定でコンパイルオプションに /FAs を追加します

  
#include "stdafx.h"

struct BUFF {
	int a;
	short b;
	double c;
	long d;
	char e[6];
};
typedef struct BUFF REC;

int main(int argc, char* argv[])
{
	char rec[24];
	REC *ptr;

	*((int *)rec) = 1;
	ptr = (REC *)rec;
	ptr->a = 1;

	return 0;
}

  

  
	TITLE	Y:\lightbox\VC\Console\StructTest\StructTest.cpp
	.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS	ENDS
$$SYMBOLS	SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS	ENDS
$$TYPES	SEGMENT BYTE USE32 'DEBTYP'
$$TYPES	ENDS
_TLS	SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS	ENDS
;	COMDAT _main
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
FLAT	GROUP _DATA, CONST, _BSS
	ASSUME	CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC	_main
;	COMDAT _main
_TEXT	SEGMENT
_rec$ = -24
_ptr$ = -28
_main	PROC NEAR					; COMDAT

; 16   : {

	push	ebp
	mov	ebp, esp
	sub	esp, 92					; 0000005cH
	push	ebx
	push	esi
	push	edi
	lea	edi, DWORD PTR [ebp-92]
	mov	ecx, 23					; 00000017H
	mov	eax, -858993460				; ccccccccH
	rep stosd

; 17   : 	char rec[24];
; 18   : 	REC *ptr;
; 19   : 
; 20   : 	*((int *)rec) = 1;

	mov	DWORD PTR _rec$[ebp], 1

; 21   : 	ptr = (REC *)rec;

	lea	eax, DWORD PTR _rec$[ebp]
	mov	DWORD PTR _ptr$[ebp], eax

; 22   : 	ptr->a = 1;

	mov	ecx, DWORD PTR _ptr$[ebp]
	mov	DWORD PTR [ecx], 1

; 23   : 
; 24   : 	return 0;

	xor	eax, eax

; 25   : }

	pop	edi
	pop	esi
	pop	ebx
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

  



  ポインタ表現によるデータのセット

コンパイルオプションで、カテゴリを「コード生成」にして、構造体メンバのアライメントを "1バイト" にする事

  
#include "stdafx.h"
#include <string.h>

struct BUFF {
	int a;
	short b;
	double c;
	long d;
	char e[6];
};
typedef struct BUFF REC;

int main(int argc, char* argv[])
{
	char rec[24];
	REC *ptr;

	*((int *)rec)			= 10000;
	*((short *)(rec+4))		= 20000;
	*((double *)(rec+6))		= 123.456;
	*((long *)(rec+14))		= 30000;
	strcpy( rec+18, "ABCDE" );

	ptr = (REC *)rec;
	
	printf( "%d\n", ptr->a );
	printf( "%d\n", ptr->b );
	printf( "%lf\n", ptr->c );
	printf( "%d\n", ptr->d );
	printf( "%s\n", ptr->e );

	return 0;
}

  



  ポインタで関数を呼び出す

  
#include "stdafx.h"

int TestFunc1( void )
{
	printf("%s\n", "関数1の呼び出し" );
	return 0;
}

int TestFunc2( int a )
{
	printf("%s 引数の値は%d\n", "関数2の呼び出し", a );
	return 0;
}

int main(int argc, char* argv[])
{
	char *ptr;

	TestFunc1();

	ptr = (char *)TestFunc1;

	((int (*)(void))ptr)();

	ptr = (char *)TestFunc2;

	((int (*)(int))ptr)( 10 );

	return 0;
}

  



  インラインアセンブラで書く

「ポインタ表現によるデータのセット」をインラインアセンブラで書いてみます

  
#include "stdafx.h"

struct BUFF {
	int a;
	short b;
	double c;
	long d;
	char e[6];
};
typedef struct BUFF REC;

int main(int argc, char* argv[])
{
	char buff[24];

	_asm {
		mov DWORD PTR buff,10000
		mov WORD PTR buff+4,20000
		mov DWORD PTR buff+14,30000
		mov BYTE PTR buff+18,'A'
		mov BYTE PTR buff+19,'B'
		mov BYTE PTR buff+20,'C'
		mov BYTE PTR buff+21,'D'
		mov BYTE PTR buff+22,'E'
		mov BYTE PTR buff+23,'\0'
	}

	REC *ptr;

	ptr = (REC *)buff;

	printf( "%d\n", ptr->a );
	printf( "%d\n", ptr->b );
	printf( "%d\n", ptr->d );
	printf( "%s\n", ptr->e );

	return 0;
}


  

さすがに、 double のセットは無理です。



  ポインタによるトークン分解

  
#include "stdafx.h"
#include <string.h>

char buff[] = "ABC,DEF,GHI,JKL,MNO";

// *****************************************************
// 各トークンの先頭アドレスをポインタの配列に格納する
// *****************************************************
void SetPointer( int len, char *buff, char *Data[] )
{

	int i;
	int counter = 0;
	for( i = 0; i < len; i++ ) {
		if ( i == 0 ) {
			Data[counter] = buff;
			counter++;
		}
		if ( buff[i] == '\0' ) {
			Data[counter] = buff+i+1;
			counter++;
		}
	}

}

int main(int argc, char* argv[])
{
	// *****************************************************
	// buff 内の確認
	// *****************************************************
	printf("%s\n", buff );


	// *****************************************************
	// buff を1バイトづつ表示
	// *****************************************************
	int i;
	int len;

	len = strlen( buff );

	for( i = 0; i < len; i++ ) {
		printf( "%c", buff[i] );
	}
	printf("\n");

	// *****************************************************
	// ',' を '\0' に置き換え
	// *****************************************************

	for( i = 0; i < len; i++ ) {
		if ( buff[i] == ',' ) {
			buff[i] = '\0';
		}
	}

	// *****************************************************
	// トークンの数を数える
	// *****************************************************
	int nToken = 0;

	for( i = 0; i < len; i++ ) {
		if ( buff[i] == '\0' ) {
			nToken++;
		}
	}
	nToken++;
	printf( "トークンの数 = %d\n", nToken );

	// *****************************************************
	// 各トークンの先頭アドレスをポインタの配列に格納する
	// *****************************************************

	char **Data = new char *[nToken];

	int counter = 0;
	for( i = 0; i < len; i++ ) {
		if ( i == 0 ) {
			Data[counter] = buff;
			counter++;
		}
		if ( buff[i] == '\0' ) {
			Data[counter] = buff+i+1;
			counter++;
		}
	}

	// *****************************************************
	// 各トークンを表示する
	// *****************************************************
	
	for( i = 0; i < nToken; i++ ) {
		printf("%s\n", Data[i]);
	}

	return 0;
}


  










  infoboard   管理者用   
このエントリーをはてなブックマークに追加





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ