1 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
2 	#pragma warning(disable:4514)
3 	#pragma warning(disable:4786)
4 #endif
5 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
6 	#pragma warning(disable:4456)
7 #endif
8 #include <stdio.h>
9 #include <stdlib.h>
10 #define XBYAK_NO_OP_NAMES
11 #include "xbyak/xbyak.h"
12 
13 class Sample : public Xbyak::CodeGenerator {
14 	void operator=(const Sample&);
15 public:
Sample(void * userPtr=0,size_t size=Xbyak::DEFAULT_MAX_CODE_SIZE)16 	Sample(void *userPtr = 0, size_t size = Xbyak::DEFAULT_MAX_CODE_SIZE) : Xbyak::CodeGenerator(size, userPtr)
17 	{
18 		inLocalLabel(); // use local label for multiple instance
19 #ifdef XBYAK32
20 		mov(ecx, ptr [esp + 4]); // n
21 #elif defined(XBYAK64_GCC)
22 		mov(ecx, edi); // n
23 #else
24 		// n = ecx
25 #endif
26 		xor_(eax, eax); // sum
27 		test(ecx, ecx);
28 		jz(".exit");
29 		xor_(edx, edx); // i
30 	L(".lp");
31 		add(eax, edx);
32 		inc(edx);
33 
34 		cmp(edx, ecx);
35 		jbe(".lp"); // jmp to previous @@
36 	L(".exit"); // <B>
37 		ret();
38 		outLocalLabel(); // end of local label
39 	}
40 };
41 
42 class AddFunc : public Xbyak::CodeGenerator {
43 	void operator=(const AddFunc&);
44 public:
AddFunc(int y)45 	AddFunc(int y)
46 	{
47 #ifdef XBYAK32
48 		mov(eax, ptr [esp + 4]);
49 		add(eax, y);
50 #elif defined(XBYAK64_WIN)
51 		lea(rax, ptr [rcx + y]);
52 #else
53 		lea(eax, ptr [edi + y]);
54 #endif
55 		ret();
56 	}
get() const57 	int (*get() const)(int) { return getCode<int(*)(int)>(); }
58 };
59 
60 class CallAtoi : public Xbyak::CodeGenerator {
61 	void operator=(const CallAtoi&);
62 public:
CallAtoi()63 	CallAtoi()
64 	{
65 #ifdef XBYAK64
66 #ifdef XBYAK64_WIN
67 		sub(rsp, 32); // return-address is destroied if 64bit debug mode
68 #endif
69 		mov(rax, (size_t)atoi);
70 		call(rax);
71 #ifdef XBYAK64_WIN
72 		add(rsp, 32);
73 #endif
74 #else
75 		mov(eax, ptr [esp + 4]);
76 		push(eax);
77 #ifdef XBYAK_VARIADIC_TEMPLATE
78 		call(atoi);
79 #else
80 		call(reinterpret_cast<const void*>(atoi));
81 #endif
82 		add(esp, 4);
83 #endif
84 		ret();
85 	}
get() const86 	int (*get() const)(const char *) { return getCode<int (*)(const char *)>(); }
87 };
88 
89 class JmpAtoi : public Xbyak::CodeGenerator {
90 	void operator=(const JmpAtoi&);
91 public:
JmpAtoi()92 	JmpAtoi()
93 	{
94 		/* already pushed "456" */
95 #ifdef XBYAK64
96 		mov(rax, (size_t)atoi);
97 		jmp(rax);
98 #else
99 		jmp(reinterpret_cast<const void*>(atoi));
100 #endif
101 	}
get() const102 	int (*get() const)(const char *) { return getCode<int (*)(const char *)>(); }
103 };
104 
105 struct Reset : public Xbyak::CodeGenerator {
initReset106 	void init(int n)
107 	{
108 		xor_(eax, eax);
109 		mov(ecx, n);
110 		test(ecx, ecx);
111 		jnz("@f");
112 		ret();
113 	L("@@");
114 		for (int i = 0; i < 10 - n; i++) {
115 			add(eax, ecx);
116 		}
117 		sub(ecx, 1);
118 		jnz("@b");
119 		ret();
120 	}
121 };
122 
testReset()123 void testReset()
124 {
125 	puts("testReset");
126 	Reset code;
127 	int (*f)(int) = code.getCode<int(*)(int)>();
128 	for (int i = 0; i < 10; i++) {
129 		code.init(i);
130 		int v = f(i);
131 		printf("%d %d\n", i, v);
132 		code.reset();
133 	}
134 }
135 
main()136 int main()
137 {
138 	try {
139 		Sample s;
140 		printf("Xbyak version=%s\n", s.getVersionString());
141 #ifdef XBYAK64_GCC
142 		puts("64bit mode(gcc)");
143 #elif defined(XBYAK64_WIN)
144 		puts("64bit mode(win)");
145 #else
146 		puts("32bit");
147 #endif
148 		int (*func)(int) = s.getCode<int (*)(int)>();
149 		for (int i = 0; i <= 10; i++) {
150 			printf("0 + ... + %d = %d\n", i, func(i));
151 		}
152 		for (int i = 0; i < 10; i++) {
153 			AddFunc a(i);
154 			int (*add)(int) = a.get();
155 			int y = add(i);
156 			printf("%d + %d = %d\n", i, i, y);
157 		}
158 		CallAtoi c;
159 		printf("call atoi(\"123\") = %d\n", c.get()("123"));
160 		JmpAtoi j;
161 		printf("jmp atoi(\"456\") = %d\n", j.get()("456"));
162 		{
163 			// use memory allocated by user
164 			using namespace Xbyak;
165 			const size_t codeSize = 4096;
166 			uint8 buf[codeSize + 16];
167 			uint8 *p = CodeArray::getAlignedAddress(buf);
168 			Sample s(p, codeSize);
169 			if (!CodeArray::protect(p, codeSize, CodeArray::PROTECT_RWE)) {
170 				fprintf(stderr, "can't protect\n");
171 				return 1;
172 			}
173 			int (*func)(int) = s.getCode<int (*)(int)>();
174 			const uint8 *funcp = reinterpret_cast<const uint8*>(func);
175 			if (funcp != p) {
176 				fprintf(stderr, "internal error %p %p\n", p, funcp);
177 				return 1;
178 			}
179 			printf("0 + ... + %d = %d\n", 100, func(100));
180 			CodeArray::protect(p, codeSize, CodeArray::PROTECT_RW);
181 		}
182 		puts("OK");
183 		testReset();
184 	} catch (std::exception& e) {
185 		printf("ERR:%s\n", e.what());
186 	} catch (...) {
187 		printf("unknown error\n");
188 	}
189 }
190 
191