in line assembler x86

Test01 : memory access

Test02 : Calculation

Test03 : flow control

Test01 : memory access


cat test01.cpp
#include <cstdio>
// C4514 unreferenced inline function has been removed
#pragma warning(disable : 4514) 

struct A {
	int member1;
	int member2;
	int member3;
};
struct B {
	int member1;
};



int main(int argc,char ** argv){
	// accessing memeory
	int i;

	_asm mov i,100
	printf("i=%d\n",i);


	char ch1, ch2;
	__asm {
		mov ch1, 0x41
		mov ch2, 0x42
	}

	printf("ch1=%c, ch2=%c\n", ch1, ch2);

	// comment for in line asm ';'
	__asm nop ; do nothing

	__asm {
		nop ;  comment for assembler
			nop /* comment for C */
			nop // comment for C++
	}

	// accessing registers
	unsigned int i2;
	unsigned short int s;

	__asm {
		mov eax, 0x44434241;
		mov i2, eax;
		mov s, ax;
		mov ch1, al;
		mov ch2, ah;
	}

	printf("i=%X\n", i);
	printf("s=%X\n", s);
	printf("ch1=%c, ch2=%c\n", ch1, ch2);

	// pointer
	int v1 = 10, v2;
	int* p = &v1;

	__asm {
		mov ebx, p      ; EBX = p
		mov eax, [ebx]  ; EAX = *p
		mov v2, eax     ; v2 = EAX
		mov [ebx], 100  ; *p = 100
	}

	printf("v1=%d, v2=%d\n", v1, v2);

	// array
	char text[6];

	__asm {
		mov text[0], 'A';
		mov text[1], 'r';
		mov text[2], 'r';
		mov text[3], 'a';
		mov text[4], 'y';
		mov text[5], 0;
	}

	printf("%s\n", text);

	// in-line asm    : c
	//  LENGTH ary    : sizeof(ary)/sizeof(ary[0]) 
	//  SIZE ary      : sizeof(ary)
	//  TYPE ary      : sizeof(ary[0])

	int _length, _size, _type;

	int ary[6] = { 0x10, 0x20, 0x30, 0x40, 0x50 , 0x60 };

	__asm {
		mov _length, length ary
		mov _size, size ary
		mov _type, type ary

		mov ary[0], 0x100
		mov ary[type ary * 1], 0x200
		mov ary[type ary * 2], 0x300
		mov ary[type ary * 3], 0x400
		mov ary[type ary * 4], 0x500
		mov ary[type ary * 5], 0x600
	}

	printf("length=%d\n", _length);
	printf("size=%d\n", _size);
	printf("type=%d\n", _type);

	printf("ary[0]=%X\n", ary[0]);
	printf("ary[1]=%X\n", ary[1]);
	printf("ary[2]=%X\n", ary[2]);
	printf("ary[3]=%X\n", ary[3]);
	printf("ary[4]=%X\n", ary[4]);
	printf("ary[5]=%X\n", ary[5]);

	// struct

	struct A obj;
	struct A* pt = &obj;

	__asm {
		mov ebx, pt;
		mov [ebx]pt.member1, 10 ; it is necessary to give a struct tag name 
								; to distinguist with struct B.member1
		mov [ebx].member2, 20	; if member name is unique, it can be omitted.
		mov obj.member3, 30
	}

	printf("member1=%d\n", obj.member1);
	printf("member2=%d\n", obj.member2);
	printf("member3=%d\n", obj.member3);



	return 0;
}

cat makefile
.PHONY: all test mmm clean 
.SUFFIXES: .exe .obj 

TARGET=test01

all: $(TARGET).exe 

LOPT=

OBJS=$(TARGET).obj 

$(TARGET).obj: $(TARGET).cpp

$(TARGET).exe: $(OBJS)  
	link $^ /out:$@ $(LOPT)

.cpp.obj:
	cl -c -Wall -Od $<

test: $(TARGET).exe
	./$(TARGET).exe 

clean:
	@-rm $(TARGET).exe *.obj *~  1>/dev/null 2>&1

mmm:
	cat $(TARGET).cpp
	@echo
	cat makefile

html:
	cat /dev/clipboard | code2html.exe | unix2dos

install: $(TARGET).exe
	cp $(TARGET).exe ~/bin



$ make test
./test01.exe
i=100
ch1=A, ch2=B
i=64
s=4241
ch1=A, ch2=B
v1=100, v2=10
Array
length=6
size=24
type=4
ary[0]=100
ary[1]=200
ary[2]=300
ary[3]=400
ary[4]=500
ary[5]=600
member1=10
member2=20
member3=30


Test02 : Calculation

cat test02.cpp
#include <cstdio>
// C4514 unreferenced inline function has been removed
#pragma warning(disable : 4514) 

int main() {
	int result;

	// add
	__asm {
		mov eax, 10;
		add eax, 100;

		mov result, eax;
		add result, 40;
	}

	printf("result=%d\n", result);

	// sub
	__asm {
		mov eax, 100;
		sub eax, 30;

		mov result, eax;
		sub result, 20;
	}

	printf("result=%d\n", result);

	// mul
	//  AL*src(8bit)   -> AX 
	//  AX*src(16bit)  -> DX:AX 
	//  EAX*src(32bit) -> EDX:EAX 
	int iEAX, iEDX, value32 = 5;

	__asm {
		mov eax, 10;
		mul value32;

		mov iEAX, eax;
		mov iEDX, edx;
	}

	printf("edx=%d eax=%d\n", iEDX, iEAX);
	short iAX, iDX, value16 = 1234;

	__asm {
		mov ax, 12345;
		mul value16;

		mov iAX, ax;
		mov iDX, dx;
	}

	printf("dx=%d ax=%d\n", iDX, iAX);

	// div                Quatient   :  remainder
	//  AL/src(8bit)   -> AL         : AH
	//  AX/src(16bit)  -> AX         : DX
	//  EAX/src(32bit) -> EAX        : EDX
	#define DIVISOR 16

	char value8 = 5, iAL, iAH;

	__asm {
		mov ax, DIVISOR;
		div value8;

		mov iAL, al;
		mov iAH, ah;
	}

	printf("%d / %d = %d, remainder= %d\n", DIVISOR, value8, iAL, iAH);

	// inc, dec
	int i = 100;

	__asm {
		mov eax, 0;

		INC eax;
		INC eax;
		INC eax;

		DEC i;
		DEC i;

		mov iEAX, eax;
	}

	printf("EAX=%d, i=%d\n", iEAX, i);

	// and or xor
	
	int and_r, or_r, xor_r;

	__asm {
		mov eax, 0xFF00FF00;
		and eax, 0x0F0FF00F;
		mov and_r, eax;

		mov eax, 0xFF00FF00;
		or eax, 0x0F0FF00F;
		mov or_r, eax;

		mov eax, 0xFF00FF00;
		xor eax, 0x0F0FF00F;
		mov xor_r, eax;
	}

	printf("and=%X, or=%X, xor=%X\n", and_r, or_r, xor_r);

	// shift
	{
		int a = 100, b = 40, c = -10, d = -1;

		__asm {
			shl a, 2;
			shr b, 3;

			sar c, 1;
			shr d, 1;
		}

		printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d);
	}

	// rot
	{
		int a = 0xFF00FF00, b = 0x0F0F0F0F;

		__asm {
			rol a, 4;
			ror b, 4;
		}

		printf("a=%X, b=%X\n", a, b);
	}	


	return 0;
}


cat makefile
.PHONY: all test mmm clean 
.SUFFIXES: .exe .obj 

TARGET=test02

all: $(TARGET).exe 

LOPT=

OBJS=$(TARGET).obj 

$(TARGET).obj: $(TARGET).cpp

$(TARGET).exe: $(OBJS)  
	link $^ /out:$@ $(LOPT)

.cpp.obj:
	cl -c -Wall -Od $<

test: $(TARGET).exe
	./$(TARGET).exe 

clean:
	@-rm $(TARGET).exe *.obj *~  1>/dev/null 2>&1

mmm:
	cat $(TARGET).cpp
	@echo
	cat makefile

html:
	cat /dev/clipboard | code2html.exe | unix2dos

install: $(TARGET).exe
	cp $(TARGET).exe ~/bin



$ make test
./test02.exe
result=150
result=50
edx=0 eax=50
dx=232 ax=29378
16 / 5 = 3, remainder= 1
EAX=3, i=98
and=F00F000, or=FF0FFF0F, xor=F00F0F0F
a=400, b=5, c=-5, d=2147483647
a=F00FF00F, b=F0F0F0F0



Test03 : flow control

cat test03.cpp
#include <cstdio>
// C4514 unreferenced inline function has been removed
#pragma warning(disable : 4514) 

void func() {
	printf("function called\n");
}
int func2(int arg1, int arg2, int arg3) {
	printf("arg1=%d, arg2=%d, arg3=%d\n", arg1, arg2, arg3);
	return arg1 + arg2 + arg3;
}


int main() {

	// jump
	int value = 0;

	__asm {
		jmp label        
			add value, 100  
			label:
			add value, 1000;
	}

	printf("value=%d\n", value);

	char * tc = "value==100\n";
	char * fc = "value!=100\n";
	char * result;

	printf("value:");
	scanf_s("%d",&value);

	__asm {
		cmp value, 100 
		jz cmp_true    ; jump if equal

		mov ebx, fc;
		mov result, ebx;
		jmp end        

	cmp_true:
		mov ebx, tc;
		mov result, ebx;
	end:
	}

	printf(result);

	// conditional jumps
	// JA	above (CF = 0 & ZF = 0)
	// JAE	above or equal(CF = 0) 
	// JB	below(CF = 1) 
	// JBE  below or equal(CF = 1 | ZF = 1) 
	// JC   if carry set (CF = 1) 
	// JCXZ if CX==0
	// JE   equal(ZF = 1) 
	// JG   greater (ZF = 0 & SF = OF) 
	// JGE  greater or equal(SD = OF) 
	// JL   less(SF ! OF) 
	// JLE  less or equal(ZF = 1 | SF ! OF) 
	// JNA  not above(CF = 1 | ZF = 1) 
	// JNAE not above or equal(CF = 1) 
	// JNB  not below(CF = 0) 
	// JNBE not below or equal(CF = 0 & ZF = 0) 
	// JNC  if no carry set(CF = 0) 
	// JNE  != (ZF = 0) 
	// JNG  not greater (ZF = 1 | SF ! OF) 
	// JNGE not greater or equal (SF ! OF) 
	// JNL  not less(SF = OF) 
	// JNLE not less or equal (ZF = 0 & SF = OF) 
	// JNO  no overflow(OF = 0) 
	// JNP  no parity(PF = 0) 
	// JNS  no sign(SF = 0) (non negative)
	// JNZ  non zero(ZF = 0) 
	// JO   overflow(PF = 1) 
	// JP   parity(PF = 1) 
	// JPE  even parity(PF = 1) 
	// JPO  odd parity(PF = 0) 
	// JS   sign(SF = 1) (negative)
	// JZ   zero(ZF = 1) 
	//
	int a, b;
	char * r1 = "a > b\n";
	char * r2 = "a < b\n";
	char * r3 = "a == b\n";

	printf("a :");
	scanf_s("%d", &a);

	printf("b :");
	scanf_s("%d", &b);

	__asm {
		mov eax, a;
		cmp eax, b;
		ja label1;
		jb label2;

		mov ebx, r3;
		mov result, ebx;
		jmp end2;
label1:
		mov ebx, r1;
		mov result, ebx;
		jmp end2;
label2:
		mov ebx, r2;
		mov result, ebx;
end2:
	}

	printf(result);

	// loop
	char teststr[32];
	char * p = teststr;

	__asm {
		mov al, 'A';
		mov ecx, 26;
label3:
		mov ebx, p;
		mov [ebx], al;

		inc p;
		inc al;

		cmp ecx, 0    
		dec ecx  
		ja label3

		mov ebx, p;
		mov [ebx], 0;
	}

	printf("%s\n", teststr);

	p = teststr;
	__asm {
		mov al, 'a';
		mov ecx, 26;
label4:
		mov ebx, p;
		mov [ebx], al;

		inc p;
		inc al;

		loop label4;

		mov ebx, p;
		mov [ebx], 0;
	}

	printf("%s\n", teststr);

	// call - ret
	int rr1, rr2, rr3, rr4;

	__asm {
		jmp end3;

setZero:
		mov eax, 0;
		mov ebx, 0;
		mov ecx, 0;
		mov edx, 0;
		ret;

setRegister:
		mov rr1, eax;
		mov rr2, ebx;
		mov rr3, ecx;
		mov rr4, edx;
		ret;
end3:
	}

	__asm call setRegister
	printf("EAX=%d, EBX=%d, ECX=%d, EDX=%d\n", rr1, rr2, rr3, rr4);

	__asm {
		call setZero
		call setRegister
	}
	printf("EAX=%d, EBX=%d, ECX=%d, EDX=%d\n", rr1, rr2, rr3, rr4);

	// recursive call
	int c;

	__asm call routine1;
	printf("A=%d, B=%d, C=%d\n", a, b, c);

	// push pop
	int r, v;

	__asm mov r, esp;
	printf("ESP=%p\n", r);

	__asm {
		push 10;
		mov r, esp;
	}
	printf("Push ESP=%p\n", r);

	__asm {
		push 20;
		mov r, esp;
	}
	printf("Push ESP=%p\n", r);

	__asm {
		push 30;
		mov r, esp;
	}
	printf("Push ESP=%p\n", r);

	__asm {
		pop v;
		mov r, esp;
	}
	printf("Pop V=%d, ESP=%p\n", v, r);

	__asm {
		pop v;
		mov r, esp;
	}
	printf("Pop V=%d, ESP=%p\n", v, r);

	__asm {
		pop v;
		mov r, esp;
	}
	printf("Pop V=%d, ESP=%p\n", v, r);

	// function call

	__asm call func;

	// function call with parameter and return value

	__asm {
		push 1000;
		push 100;
		push 10;
		call func2;

		pop ebx;
		pop ebx;
		pop ebx;

		mov result, eax;
	}

	printf("result=%d\n", result);


	return 0;
	__asm {
routine1:
		mov a, 10;
		call routine2;
		ret;
routine2:
		mov b, 20;
		call routine3;
		ret;
routine3:
		mov c, 30;
		ret
	}
}


cat makefile
.PHONY: all test mmm clean 
.SUFFIXES: .exe .obj 

TARGET=test03

all: $(TARGET).exe 

LOPT=

OBJS=$(TARGET).obj 

$(TARGET).obj: $(TARGET).cpp

$(TARGET).exe: $(OBJS)  
	link $^ /out:$@ $(LOPT)

.cpp.obj:
	cl -c -Wall -Od $<

test: $(TARGET).exe
	./$(TARGET).exe 

clean:
	@-rm $(TARGET).exe *.obj *~  1>/dev/null 2>&1

mmm:
	cat $(TARGET).cpp
	@echo
	cat makefile

html:
	cat /dev/clipboard | code2html.exe | unix2dos

install: $(TARGET).exe
	cp $(TARGET).exe ~/bin



$ make test
./test03.exe
value=1000
value:100
value==100
a :55
b :55
a == b
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
EAX=27, EBX=1244958, ECX=4199391, EDX=2004487988
EAX=0, EBX=0, ECX=0, EDX=0
A=10, B=20, C=30
ESP=0012FEE4
Push ESP=0012FEE0
Push ESP=0012FEDC
Push ESP=0012FED8
Pop V=30, ESP=0012FEDC
Pop V=20, ESP=0012FEE0
Pop V=10, ESP=0012FEE4
function called
arg1=10, arg2=100, arg3=1000
result=1110