aboutsummaryrefslogtreecommitdiffhomepage
path: root/sample/test0.cpp
blob: 8acff9e984e0fc30342a00f12c5aea34f9b7a32d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
	#pragma warning(disable:4514)
	#pragma warning(disable:4786)
#endif
#include <stdio.h>
#include <stdlib.h>
#include "xbyak/xbyak.h"

class Sample : public Xbyak::CodeGenerator {
	void operator=(const Sample&);
public:
	Sample(void *userPtr = 0, size_t size = Xbyak::DEFAULT_MAX_CODE_SIZE) : Xbyak::CodeGenerator(size, userPtr)
	{
		inLocalLabel(); // use local label for multiple instance
#ifdef XBYAK32
		mov(ecx, ptr [esp + 4]); // n
#elif defined(XBYAK64_GCC)
		mov(ecx, edi); // n
#else
		// n = ecx
#endif
		xor(eax, eax); // sum
		test(ecx, ecx);
		jz(".exit");
		xor(edx, edx); // i
	L(".lp");
		add(eax, edx);
		inc(edx);

		cmp(edx, ecx);
		jbe(".lp"); // jmp to previous @@
	L(".exit"); // <B>
		ret();
		outLocalLabel(); // end of local label
	}
};

class AddFunc : public Xbyak::CodeGenerator {
	void operator=(const AddFunc&);
public:
	AddFunc(int y)
	{
#ifdef XBYAK32
		mov(eax, ptr [esp + 4]);
		add(eax, y);
#elif defined(XBYAK64_WIN)
		lea(rax, ptr [rcx + y]);
#else
		lea(eax, ptr [edi + y]);
#endif
		ret();
	}
	int (*get() const)(int) { return (int (*)(int))(const void*)getCode(); }
};

class CallAtoi : public Xbyak::CodeGenerator {
	void operator=(const CallAtoi&);
public:
	CallAtoi()
	{
#ifdef XBYAK64
#ifdef XBYAK64_WIN
		sub(rsp, 32); // return-address is destroied if 64bit debug mode
#endif
		mov(rax, (size_t)atoi);
		call(rax);
#ifdef XBYAK64_WIN
		add(rsp, 32);
#endif
#else
		mov(eax, ptr [esp + 4]);
		push(eax);
		call((void*)atoi);
		add(esp, 4);
#endif
		ret();
	}
	int (*get() const)(const char *) { return (int (*)(const char *))(const void*)getCode(); }
};

class JmpAtoi : public Xbyak::CodeGenerator {
	void operator=(const JmpAtoi&);
public:
	JmpAtoi()
	{
		/* already pushed "456" */
#ifdef XBYAK64
		mov(rax, (size_t)atoi);
		jmp(rax);
#else
		jmp((void*)atoi);
#endif
	}
	int (*get() const)(const char *) { return (int (*)(const char *))(const void*)getCode(); }
};

int main()
{
	try {
		Sample s;
		printf("Xbyak version=%s\n", s.getVersionString());
#ifdef XBYAK64_GCC
		puts("64bit mode(gcc)");
#elif defined(XBYAK64_WIN)
		puts("64bit mode(win)");
#else
		puts("32bit");
#endif
		int (*func)(int) = (int (*)(int))(const void*)s.getCode();
		for (int i = 0; i <= 10; i++) {
			printf("0 + ... + %d = %d\n", i, func(i));
		}
		for (int i = 0; i < 10; i++) {
			AddFunc a(i);
			int (*add)(int) = a.get();
			int y = add(i);
			printf("%d + %d = %d\n", i, i, y);
		}
		CallAtoi c;
		printf("call atoi(\"123\") = %d\n", c.get()("123"));
		JmpAtoi j;
		printf("jmp atoi(\"456\") = %d\n", j.get()("456"));
		{
			// use memory allocated by user
			using namespace Xbyak;
			const size_t codeSize = 1024;
			uint8 buf[codeSize + 16];
			uint8 *p = CodeArray::getAlignedAddress(buf);
			CodeArray::protect(p, codeSize, true);
			Sample s(p, codeSize);
			int (*func)(int) = (int (*)(int))(const void*)s.getCode();
			if ((uint8*)func != p) {
				fprintf(stderr, "internal error %p %p\n", p, func);
				return 1;
			}
			printf("0 + ... + %d = %d\n", 100, func(100));
			CodeArray::protect(p, codeSize, false);
		}
		puts("OK");
	} catch (Xbyak::Error err) {
		printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
	} catch (...) {
		printf("unknown error\n");
	}
}