aboutsummaryrefslogtreecommitdiffhomepage
path: root/sample/test0.cpp
blob: afbaf83fa242e8aec7b40c109fe2482d4ac0f0fe (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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
	#pragma warning(disable:4514)
	#pragma warning(disable:4786)
#endif
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
	#pragma warning(disable:4456)
#endif
#include <stdio.h>
#include <stdlib.h>
#define XBYAK_NO_OP_NAMES
#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 getCode<int(*)(int)>(); }
};

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);
#ifdef XBYAK_VARIADIC_TEMPLATE
		call(atoi);
#else
		call(reinterpret_cast<const void*>(atoi));
#endif
		add(esp, 4);
#endif
		ret();
	}
	int (*get() const)(const char *) { return getCode<int (*)(const char *)>(); }
};

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(reinterpret_cast<const void*>(atoi));
#endif
	}
	int (*get() const)(const char *) { return getCode<int (*)(const char *)>(); }
};

struct Reset : public Xbyak::CodeGenerator {
	void init(int n)
	{
		xor_(eax, eax);
		mov(ecx, n);
		test(ecx, ecx);
		jnz("@f");
		ret();
	L("@@");
		for (int i = 0; i < 10 - n; i++) {
			add(eax, ecx);
		}
		sub(ecx, 1);
		jnz("@b");
		ret();
	}
};

void testReset()
{
	puts("testReset");
	Reset code;
	int (*f)(int) = code.getCode<int(*)(int)>();
	for (int i = 0; i < 10; i++) {
		code.init(i);
		int v = f(i);
		printf("%d %d\n", i, v);
		code.reset();
	}
}

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) = s.getCode<int (*)(int)>();
		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 = 4096;
			uint8_t buf[codeSize + 16];
			uint8_t *p = CodeArray::getAlignedAddress(buf);
			Sample s(p, codeSize);
			if (!CodeArray::protect(p, codeSize, CodeArray::PROTECT_RWE)) {
				fprintf(stderr, "can't protect\n");
				return 1;
			}
			int (*func)(int) = s.getCode<int (*)(int)>();
			const uint8_t *funcp = reinterpret_cast<const uint8_t*>(func);
			if (funcp != p) {
				fprintf(stderr, "internal error %p %p\n", p, funcp);
				return 1;
			}
			printf("0 + ... + %d = %d\n", 100, func(100));
			CodeArray::protect(p, codeSize, CodeArray::PROTECT_RW);
		}
		puts("OK");
		testReset();
	} catch (std::exception& e) {
		printf("ERR:%s\n", e.what());
	} catch (...) {
		printf("unknown error\n");
	}
}