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