Machine code: Difference between revisions

Content added Content deleted
m (Reverted edits by LVrOk6FqRY (talk) to last revision by Thundergnat)
Line 991: Line 991:


Considered to be more harmful than useful.
Considered to be more harmful than useful.

=={{header|Smalltalk}}==
I agree that this is more harmful than useful. The only target audience are compiler writers and Smalltalk-core developers (of which I guess are not too many around).

Also, this is highly cpu specific, the task is for an x86 and also assuming a particular calling convention; both is probably (definitely) not the case (most, incl. myself are on 64bit machines these days).

Anyway, as a sketch, here is how to do it (I won't waste time in making an x86_64 version for the particular calling convention used on my machine; and yes: it is even different between Unix and Windows systems!):

First we need a way to allocate executable memory (btw. we should probably also care to flush any instruction caches, which I won't go into here);
This is very Smalltalk dialect specific, and probably not supported on other Smalltalks; in ST/X, we can define it as:
{{works with|Smalltalk/X}}
<lang smalltalk>!ExternalBytes class methods!

mapExecutableBytes:size
%{
# include <sys/mman.h>

void *mem;
OBJ retVal;
int nBytes = __intVal(size);

mem = mmap(nil, nBytes, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
if (mem != MAP_FAILED) {
RETURN( __MKEXTERNALBYTES_N(mem, nBytes));
}
%}.
self primitiveFailed
! !</lang>

next, we need the correct code; the following presents the x86 version (but do not expect this code to NOT crash the Smalltalk VM, as the calling convention is certainly wrong..)
<lang smalltalk>OperatingSystem getCPUType = #'x86' ifTrue:[
code := #[0x8B 0x44 0x24 0x04 0x03 0x44 0x24 0x08 0xC3].
] ifFalse:[
self error:'unsupported cpu'
].

handle := ExternalBytes mapExecutableBytes:100.
handle replaceFrom:1 with:code.

" dump it (debugging only)... "
e'code at {handle address hexPrintString} is:' printCR.
(handle copyFrom:1 to:50) asByteArray hexPrintString printCR.

" create an ExternalFunction for it "
func := ExternalLibraryFunction new code:handle address.
func name:'unnamed' module:nil returnType:#int argumentTypes:#(int int).
func beCallTypeC.
func printCR.

" now call it "
result := func invokeWithArguments:{10 . 20}
</lang>
With a few more tricks, it is even possible to install that function as a method in a class; but additional code needs to be generated, to assert that the passed data is correctly boxed/unboxed.


=={{header|Swift}}==
=={{header|Swift}}==