aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-12-05 00:43:47 +0100
committerMike Pall <mike>2010-12-05 00:52:17 +0100
commit7cb250c4b4a22e834746ede4f00a72d7ccc09009 (patch)
tree2ce638e2d7312d2220574ac95aabcab02bff37a0 /src
parent513b0ba18f003a3e6c666f0b2d422d3553fdbfcb (diff)
downloadluajit-7cb250c4b4a22e834746ede4f00a72d7ccc09009.tar.gz
luajit-7cb250c4b4a22e834746ede4f00a72d7ccc09009.tar.bz2
luajit-7cb250c4b4a22e834746ede4f00a72d7ccc09009.zip
FFI: Add ffi.* library.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/Makefile.dep8
-rw-r--r--src/lib_ffi.c374
-rw-r--r--src/lib_init.c5
-rw-r--r--src/ljamalg.c1
-rw-r--r--src/lualib.h2
-rw-r--r--src/msvcbuild.bat2
7 files changed, 390 insertions, 4 deletions
diff --git a/src/Makefile b/src/Makefile
index 6e72d16b..ed9d3303 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -317,7 +317,7 @@ LJVM_BOUT= $(LJVM_S)
317LJVM_MODE= elfasm 317LJVM_MODE= elfasm
318 318
319LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \ 319LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
320 lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o 320 lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o
321LJLIB_C= $(LJLIB_O:.o=.c) 321LJLIB_C= $(LJLIB_O:.o=.c)
322 322
323LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ 323LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 75d71afb..145438db 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -20,7 +20,10 @@ lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
20 lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h 20 lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h lj_libdef.h
21lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 21lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h 22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h
23lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h 23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
24 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \
25 lj_cdata.h lj_cconv.h lj_lib.h lj_libdef.h
26lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
24lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 27lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
25 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ 28 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \
26 lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h \ 29 lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h \
@@ -148,5 +151,6 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
148 lj_target_*.h lj_record.c lj_record.h lj_asm.h lj_recdef.h lj_asm.c \ 151 lj_target_*.h lj_record.c lj_record.h lj_asm.h lj_recdef.h lj_asm.c \
149 lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c \ 152 lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c \
150 lualib.h lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ 153 lualib.h lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
151 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_init.c 154 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
155 lib_init.c
152luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 156luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
new file mode 100644
index 00000000..70d4c4a3
--- /dev/null
+++ b/src/lib_ffi.c
@@ -0,0 +1,374 @@
1/*
2** FFI library.
3** Copyright (C) 2005-2010 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#define lib_ffi_c
7#define LUA_LIB
8
9#include "lua.h"
10#include "lauxlib.h"
11#include "lualib.h"
12
13#include "lj_obj.h"
14
15#if LJ_HASFFI
16
17#include "lj_gc.h"
18#include "lj_err.h"
19#include "lj_str.h"
20#include "lj_ctype.h"
21#include "lj_cparse.h"
22#include "lj_cdata.h"
23#include "lj_cconv.h"
24#include "lj_lib.h"
25
26/* -- C type checks ------------------------------------------------------- */
27
28/* Check first argument for a C type and returns its ID. */
29static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
30{
31 TValue *o = L->base;
32 if (!(o < L->top)) {
33 err_argtype:
34 lj_err_argtype(L, 1, "C type");
35 }
36 if (tvisstr(o)) { /* Parse an abstract C type declaration. */
37 GCstr *s = strV(o);
38 CPState cp;
39 int errcode;
40 cp.L = L;
41 cp.cts = cts;
42 cp.srcname = strdata(s);
43 cp.p = strdata(s);
44 cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
45 errcode = lj_cparse(&cp);
46 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
47 return cp.val.id;
48 } else {
49 GCcdata *cd;
50 if (!tviscdata(o)) goto err_argtype;
51 cd = cdataV(o);
52 return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
53 }
54}
55
56/* Check argument for C data and return it. */
57static GCcdata *ffi_checkcdata(lua_State *L, int narg)
58{
59 TValue *o = L->base + narg-1;
60 if (!(o < L->top && tviscdata(o)))
61 lj_err_argt(L, narg, LUA_TCDATA);
62 return cdataV(o);
63}
64
65/* Convert argument to C pointer. */
66static void *ffi_checkptr(lua_State *L, int narg, CTypeID id)
67{
68 CTState *cts = ctype_cts(L);
69 TValue *o = L->base + narg-1;
70 void *p;
71 if (o >= L->top)
72 lj_err_arg(L, narg, LJ_ERR_NOVAL);
73 lj_cconv_ct_tv(cts, ctype_get(cts, id), (uint8_t *)&p, o, 0);
74 return p;
75}
76
77/* -- C type metamethods -------------------------------------------------- */
78
79#define LJLIB_MODULE_ffi_meta
80
81LJLIB_CF(ffi_meta___index)
82{
83 CTState *cts = ctype_cts(L);
84 CTInfo qual = 0;
85 CType *ct;
86 uint8_t *p;
87 TValue *o = L->base;
88 if (!(o+1 < L->top && tviscdata(o))) /* Also checks for presence of key. */
89 lj_err_argt(L, 1, LUA_TCDATA);
90 ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
91 lj_cdata_get(cts, ct, L->top-1, p);
92 return 1;
93}
94
95LJLIB_CF(ffi_meta___newindex)
96{
97 CTState *cts = ctype_cts(L);
98 CTInfo qual = 0;
99 CType *ct;
100 uint8_t *p;
101 TValue *o = L->base;
102 if (!(o+2 < L->top && tviscdata(o))) /* Also checks for key and value. */
103 lj_err_argt(L, 1, LUA_TCDATA);
104 ct = lj_cdata_index(cts, cdataV(o), o+1, &p, &qual);
105 lj_cdata_set(cts, ct, p, o+2, qual);
106 return 0;
107}
108
109/* Forward declaration. */
110static int lj_cf_ffi_new(lua_State *L);
111
112LJLIB_CF(ffi_meta___call)
113{
114 GCcdata *cd = ffi_checkcdata(L, 1);
115 if (cd->typeid == CTID_CTYPEID)
116 return lj_cf_ffi_new(L);
117 lj_err_caller(L, LJ_ERR_FFI_NYICALL);
118 return 0; /* unreachable */
119}
120
121LJLIB_CF(ffi_meta___tostring)
122{
123 GCcdata *cd = ffi_checkcdata(L, 1);
124 const char *msg = "cdata<%s>: %p";
125 CTypeID id = cd->typeid;
126 if (id == CTID_CTYPEID) {
127 msg = "ctype<%s>";
128 id = *(CTypeID *)cdataptr(cd);
129 } else {
130 CType *ct = ctype_raw(ctype_cts(L), id);
131 if (ctype_iscomplex(ct->info)) {
132 setstrV(L, L->top-1, lj_ctype_repr_complex(L, cdataptr(cd), ct->size));
133 return 1;
134 } else if (ct->size == 8 && ctype_isinteger(ct->info)) {
135 setstrV(L, L->top-1, lj_ctype_repr_int64(L, *(uint64_t *)cdataptr(cd),
136 (ct->info & CTF_UNSIGNED)));
137 return 1;
138 }
139 }
140 lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), cdataptr(cd));
141 return 1;
142}
143
144#include "lj_libdef.h"
145
146/* -- FFI library functions ----------------------------------------------- */
147
148#define LJLIB_MODULE_ffi
149
150LJLIB_CF(ffi_cdef)
151{
152 GCstr *s = lj_lib_checkstr(L, 1);
153 CPState cp;
154 int errcode;
155 cp.L = L;
156 cp.cts = ctype_cts(L);
157 cp.srcname = strdata(s);
158 cp.p = strdata(s);
159 cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
160 errcode = lj_cparse(&cp);
161 if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
162 lj_gc_check(L);
163 return 0;
164}
165
166LJLIB_CF(ffi_new)
167{
168 CTState *cts = ctype_cts(L);
169 CTypeID id = ffi_checkctype(L, cts);
170 CTSize sz;
171 CTInfo info = lj_ctype_info(cts, id, &sz);
172 TValue *o = L->base+1;
173 GCcdata *cd;
174 if ((info & CTF_VLA)) {
175 o++;
176 sz = lj_ctype_vlsize(cts, ctype_raw(cts, id),
177 (CTSize)lj_lib_checkint(L, 2));
178 }
179 if (sz == CTSIZE_INVALID)
180 lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
181 if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
182 cd = lj_cdata_new(cts, id, sz);
183 else
184 cd = lj_cdata_newv(cts, id, sz, ctype_align(info));
185 setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */
186 lj_cconv_ct_init(cts, ctype_raw(cts, id), sz, cdataptr(cd),
187 o, (MSize)(L->top - o)); /* Initialize cdata. */
188 L->top = o; /* Only return the cdata itself. */
189 lj_gc_check(L);
190 return 1;
191}
192
193LJLIB_CF(ffi_typeof)
194{
195 CTState *cts = ctype_cts(L);
196 CTypeID id = ffi_checkctype(L, cts);
197 GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
198 *(CTypeID *)cdataptr(cd) = id;
199 setcdataV(L, L->top-1, cd);
200 return 1;
201}
202
203LJLIB_CF(ffi_sizeof)
204{
205 CTState *cts = ctype_cts(L);
206 CTypeID id = ffi_checkctype(L, cts);
207 CTSize sz;
208 if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
209 sz = cdatavlen(cdataV(L->base));
210 } else {
211 CType *ct = lj_ctype_rawref(cts, id);
212 if (ctype_isvltype(ct->info))
213 sz = lj_ctype_vlsize(cts, ct, (CTSize)lj_lib_checkint(L, 2));
214 else
215 sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
216 if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) {
217 setnilV(L->top-1);
218 return 1;
219 }
220 }
221 setintV(L->top-1, (int32_t)sz);
222 return 1;
223}
224
225LJLIB_CF(ffi_alignof)
226{
227 CTState *cts = ctype_cts(L);
228 CTypeID id = ffi_checkctype(L, cts);
229 CTSize sz = 0;
230 CTInfo info = lj_ctype_info(cts, id, &sz);
231 setintV(L->top-1, 1 << ctype_align(info));
232 return 1;
233}
234
235LJLIB_CF(ffi_offsetof)
236{
237 CTState *cts = ctype_cts(L);
238 CTypeID id = ffi_checkctype(L, cts);
239 GCstr *name = lj_lib_checkstr(L, 2);
240 CType *ct = lj_ctype_rawref(cts, id);
241 CTSize ofs;
242 if (ctype_isstruct(ct->info) && ct->size != CTSIZE_INVALID) {
243 CType *fct = lj_ctype_getfield(cts, ct, name, &ofs);
244 if (fct) {
245 setintV(L->top-1, ofs);
246 if (ctype_isfield(fct->info)) {
247 return 1;
248 } else if (ctype_isbitfield(fct->info)) {
249 setintV(L->top++, ctype_bitpos(fct->info));
250 setintV(L->top++, ctype_bitbsz(fct->info));
251 return 3;
252 }
253 }
254 }
255 return 0;
256}
257
258LJLIB_CF(ffi_cast)
259{
260 CTState *cts = ctype_cts(L);
261 CTypeID id = ffi_checkctype(L, cts);
262 TValue *o = lj_lib_checkany(L, 2);
263 L->top = o+1; /* Make sure this is the last item on the stack. */
264 if (!(tviscdata(o) && cdataV(o)->typeid == id)) {
265 CTSize sz = lj_ctype_size(cts, id);
266 GCcdata *cd;
267 if (sz == CTSIZE_INVALID)
268 lj_err_caller(L, LJ_ERR_FFI_INVSIZE);
269 cd = lj_cdata_new(cts, id, sz); /* Create destination cdata. */
270 lj_cconv_ct_tv(cts, ctype_raw(cts, id), cdataptr(cd), o, CCF_CAST);
271 setcdataV(L, o, cd);
272 lj_gc_check(L);
273 }
274 return 1;
275}
276
277LJLIB_CF(ffi_string)
278{
279 CTState *cts = ctype_cts(L);
280 TValue *o = lj_lib_checkany(L, 1);
281 size_t sz = (size_t)(CTSize)lj_lib_optint(L, 2, (int32_t)CTSIZE_INVALID);
282 CType *ct = ctype_get(cts, sz==CTSIZE_INVALID ? CTID_P_CVOID : CTID_P_CCHAR);
283 const char *p;
284 L->top = o+1; /* Make sure this is the last item on the stack. */
285 lj_cconv_ct_tv(cts, ct, (uint8_t *)&p, o, 0);
286 if (sz == CTSIZE_INVALID) sz = strlen(p);
287 setstrV(L, o, lj_str_new(L, p, sz));
288 lj_gc_check(L);
289 return 1;
290}
291
292LJLIB_CF(ffi_copy)
293{
294 void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
295 void *sp = ffi_checkptr(L, 2, CTID_P_CVOID);
296 TValue *o = L->base+1;
297 CTSize sz;
298 if (tvisstr(o) && o+1 >= L->top) {
299 sz = strV(o)->len+1; /* Copy Lua string including trailing '\0'. */
300 } else {
301 sz = (CTSize)lj_lib_checkint(L, 3);
302 if (tvisstr(o) && sz > strV(o)->len+1)
303 sz = strV(o)->len+1; /* Max. copy length is string length. */
304 }
305 memcpy(dp, sp, sz);
306 return 0;
307}
308
309LJLIB_CF(ffi_fill)
310{
311 void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
312 CTSize sz = (CTSize)lj_lib_checkint(L, 2);
313 int32_t fill = lj_lib_optint(L, 3, 0);
314 memset(dp, fill, sz);
315 return 0;
316}
317
318#define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be)
319
320/* Test ABI string. */
321LJLIB_CF(ffi_abi)
322{
323 GCstr *s = lj_lib_checkstr(L, 1);
324 int b = 0;
325 switch (s->hash) {
326#if LJ_64
327 case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */
328#else
329 case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */
330#endif
331#if LJ_ARCH_HASFPU
332 case H_(e33ee463,e33ee463): b = 1; break; /* fpu */
333#endif
334#if LJ_ABI_SOFTFP
335 case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */
336#else
337 case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */
338#endif
339#if LJ_ABI_EABI
340 case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */
341#endif
342#if LJ_ABI_WIN
343 case H_(4ab624a8,4ab624a8): b = 1; break; /* win */
344#endif
345 case H_(3af93066,1f001464): b = 1; break; /* le/be */
346 default:
347 break;
348 }
349 setboolV(L->top-1, b);
350 return 1;
351}
352
353#undef H_
354
355LJLIB_PUSH(top-3) LJLIB_SET(os)
356LJLIB_PUSH(top-2) LJLIB_SET(arch)
357
358#include "lj_libdef.h"
359
360/* ------------------------------------------------------------------------ */
361
362LUALIB_API int luaopen_ffi(lua_State *L)
363{
364 lj_ctype_init(L);
365 LJ_LIB_REG_(L, NULL, ffi_meta);
366 /* NOBARRIER: basemt is a GC root. */
367 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
368 lua_pushliteral(L, LJ_OS_NAME);
369 lua_pushliteral(L, LJ_ARCH_NAME);
370 LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */
371 return 1;
372}
373
374#endif
diff --git a/src/lib_init.c b/src/lib_init.c
index dd3a29af..8501e21d 100644
--- a/src/lib_init.c
+++ b/src/lib_init.c
@@ -11,6 +11,8 @@
11#include "lauxlib.h" 11#include "lauxlib.h"
12#include "lualib.h" 12#include "lualib.h"
13 13
14#include "lj_arch.h"
15
14static const luaL_Reg lj_lib_load[] = { 16static const luaL_Reg lj_lib_load[] = {
15 { "", luaopen_base }, 17 { "", luaopen_base },
16 { LUA_LOADLIBNAME, luaopen_package }, 18 { LUA_LOADLIBNAME, luaopen_package },
@@ -26,6 +28,9 @@ static const luaL_Reg lj_lib_load[] = {
26}; 28};
27 29
28static const luaL_Reg lj_lib_preload[] = { 30static const luaL_Reg lj_lib_preload[] = {
31#if LJ_HASFFI
32 { LUA_FFILIBNAME, luaopen_ffi },
33#endif
29 { NULL, NULL } 34 { NULL, NULL }
30}; 35};
31 36
diff --git a/src/ljamalg.c b/src/ljamalg.c
index 9681d759..30547d3f 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -70,5 +70,6 @@
70#include "lib_debug.c" 70#include "lib_debug.c"
71#include "lib_bit.c" 71#include "lib_bit.c"
72#include "lib_jit.c" 72#include "lib_jit.c"
73#include "lib_ffi.c"
73#include "lib_init.c" 74#include "lib_init.c"
74 75
diff --git a/src/lualib.h b/src/lualib.h
index 9c473c88..fab30b11 100644
--- a/src/lualib.h
+++ b/src/lualib.h
@@ -20,6 +20,7 @@
20#define LUA_DBLIBNAME "debug" 20#define LUA_DBLIBNAME "debug"
21#define LUA_BITLIBNAME "bit" 21#define LUA_BITLIBNAME "bit"
22#define LUA_JITLIBNAME "jit" 22#define LUA_JITLIBNAME "jit"
23#define LUA_FFILIBNAME "ffi"
23 24
24LUALIB_API int luaopen_base(lua_State *L); 25LUALIB_API int luaopen_base(lua_State *L);
25LUALIB_API int luaopen_math(lua_State *L); 26LUALIB_API int luaopen_math(lua_State *L);
@@ -31,6 +32,7 @@ LUALIB_API int luaopen_package(lua_State *L);
31LUALIB_API int luaopen_debug(lua_State *L); 32LUALIB_API int luaopen_debug(lua_State *L);
32LUALIB_API int luaopen_bit(lua_State *L); 33LUALIB_API int luaopen_bit(lua_State *L);
33LUALIB_API int luaopen_jit(lua_State *L); 34LUALIB_API int luaopen_jit(lua_State *L);
35LUALIB_API int luaopen_ffi(lua_State *L);
34 36
35LUALIB_API void luaL_openlibs(lua_State *L); 37LUALIB_API void luaL_openlibs(lua_State *L);
36 38
diff --git a/src/msvcbuild.bat b/src/msvcbuild.bat
index 5a5e4ec8..899b876c 100644
--- a/src/msvcbuild.bat
+++ b/src/msvcbuild.bat
@@ -20,7 +20,7 @@
20@set LJLIB=lib /nologo 20@set LJLIB=lib /nologo
21@set DASMDIR=..\dynasm 21@set DASMDIR=..\dynasm
22@set DASM=lua %DASMDIR%\dynasm.lua 22@set DASM=lua %DASMDIR%\dynasm.lua
23@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c 23@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
24 24
25if not exist buildvm_x86.h^ 25if not exist buildvm_x86.h^
26 %DASM% -LN -o buildvm_x86.h buildvm_x86.dasc 26 %DASM% -LN -o buildvm_x86.h buildvm_x86.dasc