Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Machine-code/00-META.yaml
Normal file
2
Task/Machine-code/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Machine_code
|
||||
23
Task/Machine-code/00-TASK.txt
Normal file
23
Task/Machine-code/00-TASK.txt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
The task requires poking machine code directly into memory and executing it. The machine code is the architecture-specific opcodes which have the simple task of adding two unsigned bytes together and making the result available to the high-level language.
|
||||
|
||||
For example, the following assembly language program is given for x86 (32 bit) architectures:
|
||||
|
||||
<syntaxhighlight lang="asm">mov EAX, [ESP+4]
|
||||
add EAX, [ESP+8]
|
||||
ret</syntaxhighlight>
|
||||
|
||||
This would translate into the following opcode bytes:
|
||||
<syntaxhighlight lang="text">139 68 36 4 3 68 36 8 195</syntaxhighlight>
|
||||
|
||||
Or in hexadecimal:
|
||||
<syntaxhighlight lang="text">8B 44 24 04 03 44 24 08 C3</syntaxhighlight>
|
||||
|
||||
;Task:
|
||||
If different than 32-bit x86, specify the target architecture of the machine code for your example. It may be helpful to also include an assembly version of the machine code for others to reference and understand what is being executed. Then, implement the following in your favorite programming language:
|
||||
|
||||
* Poke the necessary opcodes into a memory location.
|
||||
* Provide a means to pass two values to the machine code.
|
||||
* Execute the machine code with the following arguments: unsigned-byte argument of value 7; unsigned-byte argument of value 12; The result would be 19.
|
||||
* Perform any clean up actions that are appropriate for your chosen language (free the pointer or memory allocations, etc.)
|
||||
|
||||
|
||||
4
Task/Machine-code/6502-Assembly/machine-code-1.6502
Normal file
4
Task/Machine-code/6502-Assembly/machine-code-1.6502
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
LDA #$07
|
||||
CLC
|
||||
ADC #$0C
|
||||
RTS
|
||||
33
Task/Machine-code/6502-Assembly/machine-code-2.6502
Normal file
33
Task/Machine-code/6502-Assembly/machine-code-2.6502
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
main:
|
||||
LDX #$00 ;initialize array offset to 0
|
||||
|
||||
LDA #$A9 ;LDA #immediate
|
||||
STA Array,x ;store at offset 0
|
||||
INX ;next offset
|
||||
|
||||
LDA #$07 ;first parameter
|
||||
STA Array,x ;store at offset 1
|
||||
INX ;next offset
|
||||
|
||||
LDA #$18 ;CLC
|
||||
STA Array,x ;store at offset 2
|
||||
INX ;next offset
|
||||
|
||||
LDA #$69 ;ADC #immediate
|
||||
STA Array,x ;store at offset 3
|
||||
INX ;next offset
|
||||
|
||||
LDA #$0C ;second parameter
|
||||
STA Array,x ;store at offset 4
|
||||
INX ;next offset
|
||||
|
||||
LDA #$60 ;RTS
|
||||
STA Array,x ;store at offset 5
|
||||
|
||||
|
||||
JMP Array ;assuming we used a JSR to get to main, the RTS at the end of this RAM will return us back to BASIC.
|
||||
;if array is directly underneath this statement, we can actually omit this JMP entirely
|
||||
;and execution will simply fall through to the array.
|
||||
|
||||
Array:
|
||||
byte 0,0,0,0,0,0
|
||||
3
Task/Machine-code/68000-Assembly/machine-code-1.68000
Normal file
3
Task/Machine-code/68000-Assembly/machine-code-1.68000
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
MOVE.B #7,D0
|
||||
ADD.B #12,D0
|
||||
RTS
|
||||
10
Task/Machine-code/68000-Assembly/machine-code-2.68000
Normal file
10
Task/Machine-code/68000-Assembly/machine-code-2.68000
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
LEA CodeArray,A0
|
||||
MOVE.L #$103C0007,(A0)+ ;MOVE.B #7,D0
|
||||
MOVE.L #$D03C000C,(A0)+ ;ADD.B #12,D0
|
||||
MOVE.W #$4E75,(A0)+ ;RTS
|
||||
JSR CodeArray
|
||||
|
||||
JMP $ ;halt the cpu, we're done.
|
||||
|
||||
CodeArray:
|
||||
DS.B 16 ;16 bytes of padding (this is assumed to be RAM)
|
||||
26
Task/Machine-code/Action-/machine-code.action
Normal file
26
Task/Machine-code/Action-/machine-code.action
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
DEFINE ADC="$6D"
|
||||
DEFINE CLC="$18"
|
||||
DEFINE JSR="$20"
|
||||
DEFINE LDA="$AD"
|
||||
DEFINE RTS="$60"
|
||||
DEFINE STA="$8D"
|
||||
|
||||
PROC Main()
|
||||
BYTE ARRAY buf(20)
|
||||
BYTE a=[19],b=[37],s
|
||||
CARD addr
|
||||
|
||||
addr=buf
|
||||
Poke(addr,CLC) addr==+1
|
||||
Poke(addr,LDA) addr==+1
|
||||
PokeC(addr,@a) addr==+2
|
||||
Poke(addr,ADC) addr==+1
|
||||
PokeC(addr,@b) addr==+2
|
||||
Poke(addr,STA) addr==+1
|
||||
PokeC(addr,@s) addr==+2
|
||||
Poke(addr,RTS) addr==+1
|
||||
|
||||
[JSR buf] ;run the machine code stored on buf
|
||||
|
||||
PrintF("%B+%B=%B%E",a,b,s)
|
||||
RETURN
|
||||
1
Task/Machine-code/Applesoft-BASIC/machine-code.basic
Normal file
1
Task/Machine-code/Applesoft-BASIC/machine-code.basic
Normal file
|
|
@ -0,0 +1 @@
|
|||
POKE768,169:POKE770,24:POKE771,105:POKE773,133:POKE775,96:POKE774,235:POKE769,7:POKE772,12:CALL768:?PEEK(235)
|
||||
11
Task/Machine-code/AutoHotkey/machine-code.ahk
Normal file
11
Task/Machine-code/AutoHotkey/machine-code.ahk
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
MCode(Var, "8B44240403442408C3")
|
||||
MsgBox, % DllCall(&Var, "Char",7, "Char",12)
|
||||
Var := ""
|
||||
return
|
||||
|
||||
; http://www.autohotkey.com/board/topic/19483-machine-code-functions-bit-wizardry/
|
||||
MCode(ByRef code, hex) { ; allocate memory and write Machine Code there
|
||||
VarSetCapacity(code, StrLen(hex) // 2)
|
||||
Loop % StrLen(hex) // 2
|
||||
NumPut("0x" . SubStr(hex, 2 * A_Index - 1, 2), code, A_Index - 1, "Char")
|
||||
}
|
||||
18
Task/Machine-code/BBC-BASIC/machine-code.basic
Normal file
18
Task/Machine-code/BBC-BASIC/machine-code.basic
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
REM Claim 9 bytes of memory
|
||||
SYS "GlobalAlloc",0,9 TO code%
|
||||
|
||||
REM Poke machine code into it
|
||||
P%=code%
|
||||
[OPT 0
|
||||
mov EAX, [ESP+4]
|
||||
add EAX, [ESP+8]
|
||||
ret
|
||||
]
|
||||
|
||||
REM Run code
|
||||
SYS code%,7,12 TO result%
|
||||
PRINT result%
|
||||
|
||||
REM Free memory
|
||||
SYS "GlobalFree",code%
|
||||
END
|
||||
31
Task/Machine-code/C/machine-code.c
Normal file
31
Task/Machine-code/C/machine-code.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
int test (int a, int b)
|
||||
{
|
||||
/*
|
||||
mov EAX, [ESP+4]
|
||||
add EAX, [ESP+8]
|
||||
ret
|
||||
*/
|
||||
char code[] = {0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0xC3};
|
||||
void *buf;
|
||||
int c;
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_ANON,-1,0);
|
||||
|
||||
memcpy (buf, code, sizeof(code));
|
||||
/* run code */
|
||||
c = ((int (*) (int, int))buf)(a, b);
|
||||
/* free buffer */
|
||||
munmap (buf, sizeof(code));
|
||||
return c;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
printf("%d\n", test(7,12));
|
||||
return 0;
|
||||
}
|
||||
10
Task/Machine-code/COBOL/machine-code-1.cobol
Normal file
10
Task/Machine-code/COBOL/machine-code-1.cobol
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
movl %edi, -0x4(%rbp)
|
||||
movl %esi, -0x8(%rbp)
|
||||
movl -0x4(%rbp), %esi
|
||||
addl -0x8(%rbp), %esi
|
||||
movl %esi, -0xc(%rbp)
|
||||
movl -0xc(%rbp), %eax
|
||||
popq %rbp
|
||||
retq
|
||||
71
Task/Machine-code/COBOL/machine-code-2.cobol
Normal file
71
Task/Machine-code/COBOL/machine-code-2.cobol
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
>>SOURCE FORMAT IS FIXED
|
||||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. MC.
|
||||
DATA DIVISION.
|
||||
WORKING-STORAGE SECTION.
|
||||
01 INSTRUCTIONS.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'55'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'48'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'89'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'E5'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'89'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'7D'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'FC'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'89'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'75'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'F8'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'8B'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'75'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'FC'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'03'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'75'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'F8'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'89'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'75'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'F4'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'8B'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'45'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'F4'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'5D'.
|
||||
03 USAGE BINARY-CHAR UNSIGNED VALUE H'C3'.
|
||||
01 MMAP.
|
||||
03 MMAP-ADDR USAGE POINTER VALUE NULL.
|
||||
03 MMAP-LEN USAGE BINARY-LONG UNSIGNED VALUE 24.
|
||||
03 MMAP-PROT USAGE BINARY-INT VALUE H'0007'.
|
||||
03 MMAP-FLAGS USAGE BINARY-INT VALUE H'1002'.
|
||||
03 MMAP-FD USAGE BINARY-INT VALUE -1.
|
||||
03 MMAP-OFFSET USAGE BINARY-LONG VALUE 0.
|
||||
03 CODE-PTR USAGE PROCEDURE-POINTER.
|
||||
01 ARG-A USAGE BINARY-INT VALUE 7.
|
||||
01 ARG-B USAGE BINARY-INT VALUE 12.
|
||||
01 RESULT USAGE BINARY-INT.
|
||||
LINKAGE SECTION.
|
||||
01 MACHINE-CODE PIC X(24).
|
||||
PROCEDURE DIVISION.
|
||||
MAIN SECTION.
|
||||
PERFORM SET-UP.
|
||||
CALL CODE-PTR USING
|
||||
BY VALUE ARG-A
|
||||
BY VALUE ARG-B
|
||||
RETURNING RESULT.
|
||||
DISPLAY RESULT.
|
||||
PERFORM TEAR-DOWN.
|
||||
STOP RUN.
|
||||
|
||||
SET-UP SECTION.
|
||||
CALL 'mmap' USING
|
||||
BY VALUE MMAP-ADDR
|
||||
BY VALUE MMAP-LEN
|
||||
BY VALUE MMAP-PROT
|
||||
BY VALUE MMAP-FLAGS
|
||||
BY VALUE MMAP-FD
|
||||
BY VALUE MMAP-OFFSET
|
||||
RETURNING CODE-PTR.
|
||||
SET ADDRESS OF MACHINE-CODE TO CODE-PTR.
|
||||
MOVE INSTRUCTIONS TO MACHINE-CODE.
|
||||
|
||||
TEAR-DOWN SECTION.
|
||||
SET ADDRESS OF MACHINE-CODE TO NULL.
|
||||
CALL 'munmap' USING
|
||||
BY VALUE CODE-PTR
|
||||
BY VALUE MMAP-LEN.
|
||||
7
Task/Machine-code/Commodore-BASIC/machine-code-1.basic
Normal file
7
Task/Machine-code/Commodore-BASIC/machine-code-1.basic
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Assembly Hexadecimal Decimal
|
||||
|
||||
CLC 18 24
|
||||
LDA $2000 AD 00 20 173 0 32
|
||||
ADC $2001 6D 01 20 109 1 32
|
||||
STA $2002 8D 02 20 141 2 32
|
||||
RTS 60 96
|
||||
20
Task/Machine-code/Commodore-BASIC/machine-code-2.basic
Normal file
20
Task/Machine-code/Commodore-BASIC/machine-code-2.basic
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
10 print chr$(147);
|
||||
15 ml=8192
|
||||
20 if peek(ml+3)<>173 and peek(ml+12)<>96 then gosub 100
|
||||
30 for ad=ml to ml+2:poke ad,0:next
|
||||
40 poke ml,7:poke ml+1,12
|
||||
50 print "before:";peek(ml+2)
|
||||
60 sys ml+3
|
||||
70 print "after:";peek(ml+2)
|
||||
80 end
|
||||
100 rem machine language loader
|
||||
105 for ad=ml+3 to ml+13
|
||||
110 read b
|
||||
115 poke ad,b
|
||||
120 next
|
||||
125 return
|
||||
8195 data 24 :rem clc
|
||||
8196 data 173,0,32 :rem lda $2000
|
||||
8199 data 109,1,32 :rem adc $2001
|
||||
8202 data 141,2,32 :rem sta $2002
|
||||
8205 data 96 :rem rts
|
||||
56
Task/Machine-code/Common-Lisp/machine-code.lisp
Normal file
56
Task/Machine-code/Common-Lisp/machine-code.lisp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
;;Note that by using the 'CFFI' library, one can apply this procedure portably in any lisp implementation;
|
||||
;; in this code however I chose to demonstrate only the implementation-dependent programs.
|
||||
|
||||
;;CCL
|
||||
;; Allocate a memory pointer and poke the opcode into it
|
||||
(defparameter ptr (ccl::malloc 9))
|
||||
|
||||
(loop for i in '(139 68 36 4 3 68 36 8 195)
|
||||
for j from 0 do
|
||||
(setf (ccl::%get-unsigned-byte ptr j) i))
|
||||
|
||||
;; Execute with the required arguments and return the result as an unsigned-byte
|
||||
(ccl::ff-call ptr :UNSIGNED-BYTE 7 :UNSIGNED-BYTE 12 :UNSIGNED-BYTE)
|
||||
|
||||
;; Output = 19
|
||||
|
||||
;; Free the pointer
|
||||
(ccl::free ptr)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;SBCL
|
||||
(defparameter mmap (list 139 68 36 4 3 68 36 8 195))
|
||||
|
||||
(defparameter pointer (sb-alien:make-alien sb-alien:unsigned-char (length mmap)))
|
||||
|
||||
(defparameter callp (loop for byte in mmap
|
||||
for i from 0
|
||||
do
|
||||
(setf (sb-alien:deref pointer i) byte)
|
||||
finally
|
||||
(return (sb-alien:cast pointer (function integer integer integer)))))
|
||||
|
||||
(sb-alien:alien-funcall callp 7 12)
|
||||
|
||||
(loop for i from 0 below 18 collect (sb-alien:deref ptr i))
|
||||
|
||||
(sb-alien:free-alien pointer)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;CLISP
|
||||
(defparameter mmap (list 139 68 36 4 3 68 36 8 195))
|
||||
|
||||
(defparameter POINTER (FFI:FOREIGN-ADDRESS (FFI:FOREIGN-ALLOCATE 'FFI:UINT8 :COUNT 9)))
|
||||
|
||||
(loop for i in mmap
|
||||
for j from 0 do
|
||||
(FUNCALL #'(SETF FFI:MEMORY-AS) i POINTER 'FFI:INT j))
|
||||
|
||||
(FUNCALL
|
||||
(FFI:FOREIGN-FUNCTION POINTER
|
||||
(LOAD-TIME-VALUE
|
||||
(FFI:PARSE-C-TYPE
|
||||
'(FFI:C-FUNCTION (:ARGUMENTS 'FFI:INT 'FFI:INT) (:RETURN-TYPE FFI:INT) (:LANGUAGE :STDC)))))
|
||||
7 12)
|
||||
|
||||
(FFI:FOREIGN-FREE POINTER)
|
||||
32
Task/Machine-code/Cowgol/machine-code.cowgol
Normal file
32
Task/Machine-code/Cowgol/machine-code.cowgol
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
include "cowgol.coh";
|
||||
|
||||
# Run machine code at cptr, given two 32-bit arguments,
|
||||
# return the value returned from EAX.
|
||||
sub RunCode(cptr: [uint8], arg1: uint32, arg2: uint32): (rslt: uint32) is
|
||||
# Inline assembly is supported, so this whole rigmarole
|
||||
# is not even necessary.
|
||||
# Though note that this (obviously) depends on the assembly back-end used.
|
||||
# Linux as uses AT&T syntax, so that's what I'm doing here.
|
||||
# Cowgol supports many processors but this will, obviously, only work
|
||||
# on x86.
|
||||
|
||||
@asm "pushl (",arg1,")"; # Push the two arguments on the stack
|
||||
@asm "pushl (",arg2,")";
|
||||
@asm "call *(",cptr,")"; # Call the code at the pointer
|
||||
@asm "movl %eax, (",rslt,")"; # Store the result in rslt
|
||||
@asm "popl %eax"; # Clean up the stack
|
||||
@asm "popl %eax";
|
||||
end sub;
|
||||
|
||||
# Store code in an array. This is enough to make it available.
|
||||
var code: uint8[] := {139, 68, 36, 4, 3, 68, 36, 8, 195};
|
||||
|
||||
# Use the function
|
||||
print_i32(RunCode(&code as [uint8], 7, 12)); # this prints 7+12 = 19
|
||||
print_nl();
|
||||
|
||||
# As a demonstration, this shows it can be patched at runtime to multiply instead
|
||||
code[4] := 247;
|
||||
code[5] := 100;
|
||||
print_i32(RunCode(&code as [uint8], 7, 12)); # this prints 7*12 = 84
|
||||
print_nl();
|
||||
17
Task/Machine-code/D/machine-code.d
Normal file
17
Task/Machine-code/D/machine-code.d
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
int test(in int a, in int b) pure nothrow @nogc {
|
||||
/*
|
||||
mov EAX, [ESP+4]
|
||||
add EAX, [ESP+8]
|
||||
ret
|
||||
*/
|
||||
immutable ubyte[9] code = [0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0xC3];
|
||||
alias F = extern(C) int function(int, int) pure nothrow @nogc;
|
||||
immutable f = cast(F)code.ptr;
|
||||
return f(a, b); // Run code.
|
||||
}
|
||||
|
||||
void main() {
|
||||
import std.stdio;
|
||||
|
||||
test(7, 12).writeln;
|
||||
}
|
||||
25
Task/Machine-code/Delphi/machine-code.delphi
Normal file
25
Task/Machine-code/Delphi/machine-code.delphi
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
function AddNumbers(Num1, Num2: integer): Integer;
|
||||
{Add two numbers in assembly language}
|
||||
asm
|
||||
PUSH EBX
|
||||
PUSH EDX
|
||||
MOV ECX,Num1
|
||||
MOV EDX,Num2
|
||||
ADD ECX,EDX
|
||||
MOV Result,ECX
|
||||
POP EDX
|
||||
POP EBX
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure TestAssembly(Memo: TMemo);
|
||||
var I,J,K: integer;
|
||||
begin
|
||||
for I:=1 to 5 do
|
||||
for J:=1 to 5 do
|
||||
begin
|
||||
K:=AddNumbers(I,J);
|
||||
Memo.Lines.Add(IntToStr(I)+' + '+IntToStr(J)+' = '+IntToStr(K));
|
||||
end;
|
||||
end;
|
||||
21
Task/Machine-code/Draco/machine-code-1.draco
Normal file
21
Task/Machine-code/Draco/machine-code-1.draco
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/* 8080 machine code in an array */
|
||||
[6] byte add_mc = (
|
||||
0xC1, /* POP B - get return address */
|
||||
0xD1, /* POP D - get second argument */
|
||||
0xE1, /* POP H - get first argument */
|
||||
0x19, /* DAD D - add arguments */
|
||||
0xC5, /* PUSH B - push return address back */
|
||||
0xC9 /* RET - return */
|
||||
);
|
||||
|
||||
proc nonrec main() void:
|
||||
/* Declare a function pointer */
|
||||
type fn = proc(word a, b) word;
|
||||
fn add;
|
||||
|
||||
/* Pretend the array is actually a function */
|
||||
add := pretend(add_mc, fn);
|
||||
|
||||
/* Call the function and print the result */
|
||||
writeln(add(12, 7))
|
||||
corp
|
||||
28
Task/Machine-code/Draco/machine-code-2.draco
Normal file
28
Task/Machine-code/Draco/machine-code-2.draco
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
proc nonrec main() void:
|
||||
word a, b, c;
|
||||
|
||||
/* assign values to the input variables */
|
||||
a := 12;
|
||||
b := 7;
|
||||
|
||||
/* inline machine code to add A and B
|
||||
*
|
||||
* Note that we have to cast each value to a byte,
|
||||
* because by default, numeric constants are assumed
|
||||
* to be 16-bit words, and would be emitted as two
|
||||
* bytes each.
|
||||
*
|
||||
* The intent is for the programmer to define byte
|
||||
* constants corresponding to opcodes, and write
|
||||
* "assembly", but that is beyond the scope here. */
|
||||
code(
|
||||
make(0x2A, byte), a, /* LHLD a - load var A into HL */
|
||||
make(0xEB, byte), /* XCHG - put it in DE */
|
||||
make(0x2A, byte), b, /* LHLD b - load var B into HL */
|
||||
make(0x19, byte), /* DAD D - add DE to HL */
|
||||
make(0x22, byte), c /* SHLD c - store the result in var C */
|
||||
);
|
||||
|
||||
/* print the result */
|
||||
writeln(c);
|
||||
corp
|
||||
11
Task/Machine-code/FreeBASIC/machine-code.basic
Normal file
11
Task/Machine-code/FreeBASIC/machine-code.basic
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
'' This is an example for the x86 architecture.
|
||||
Function test (Byval a As Long, Byval b As Long) As Long
|
||||
Asm
|
||||
mov eax, [a]
|
||||
Add eax, [b]
|
||||
mov [Function], eax
|
||||
End Asm
|
||||
End Function
|
||||
|
||||
Print test(12, 7)
|
||||
Sleep
|
||||
38
Task/Machine-code/Go/machine-code.go
Normal file
38
Task/Machine-code/Go/machine-code.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef byte (*mcfunc) (byte, byte);
|
||||
|
||||
void runMachineCode(void *buf, byte a, byte b) {
|
||||
mcfunc fp = (mcfunc)buf;
|
||||
printf("%d\n", fp(a, b));
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
code := []byte{
|
||||
0x55, 0x48, 0x89, 0xe5, 0x89, 0x7d,
|
||||
0xfc, 0x89, 0x75, 0xf8, 0x8b, 0x75,
|
||||
0xfc, 0x03, 0x75, 0xf8, 0x89, 0x75,
|
||||
0xf4, 0x8b, 0x45, 0xf4, 0x5d, 0xc3,
|
||||
}
|
||||
le := len(code)
|
||||
buf := C.mmap(nil, C.size_t(le), C.PROT_READ|C.PROT_WRITE|C.PROT_EXEC,
|
||||
C.MAP_PRIVATE|C.MAP_ANON, -1, 0)
|
||||
codePtr := C.CBytes(code)
|
||||
C.memcpy(buf, codePtr, C.size_t(le))
|
||||
var a, b byte = 7, 12
|
||||
fmt.Printf("%d + %d = ", a, b)
|
||||
C.runMachineCode(buf, C.byte(a), C.byte(b))
|
||||
C.munmap(buf, C.size_t(le))
|
||||
C.free(codePtr)
|
||||
}
|
||||
38
Task/Machine-code/Julia/machine-code.julia
Normal file
38
Task/Machine-code/Julia/machine-code.julia
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using Cxx
|
||||
|
||||
cxx"""
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
int test (int a, int b)
|
||||
{
|
||||
/*
|
||||
mov EAX, [ESP+4]
|
||||
add EAX, [ESP+8]
|
||||
ret
|
||||
*/
|
||||
char code[] = {0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0xC3};
|
||||
void *buf;
|
||||
int c;
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_ANON,-1,0);
|
||||
|
||||
memcpy (buf, code, sizeof(code));
|
||||
/* run code */
|
||||
c = ((int (*) (int, int))buf)(a, b);
|
||||
/* free buffer */
|
||||
munmap (buf, sizeof(code));
|
||||
return c;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
printf("%d\n", test(7,12));
|
||||
return 0;
|
||||
}
|
||||
"""
|
||||
|
||||
julia_function = @cxx main()
|
||||
julia_function()
|
||||
6
Task/Machine-code/Kotlin/machine-code-1.kotlin
Normal file
6
Task/Machine-code/Kotlin/machine-code-1.kotlin
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// mcode.def
|
||||
---
|
||||
|
||||
static inline unsigned char runMachineCode(void *code, unsigned char a, unsigned char b) {
|
||||
return ((unsigned char (*) (unsigned char, unsigned char))code)(a, b);
|
||||
}
|
||||
37
Task/Machine-code/Kotlin/machine-code-2.kotlin
Normal file
37
Task/Machine-code/Kotlin/machine-code-2.kotlin
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Kotlin Native version 0.3
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import string.*
|
||||
import mman.*
|
||||
import mcode.*
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
memScoped {
|
||||
val bytes = byteArrayOf(
|
||||
144 - 256, // Align
|
||||
144 - 256,
|
||||
106, 12, // Prepare stack
|
||||
184 - 256, 7, 0, 0, 0,
|
||||
72, 193 - 256, 224 - 256, 32,
|
||||
80,
|
||||
139 - 256, 68, 36, 4, 3, 68, 36, 8, // Rosetta task code
|
||||
76, 137 - 256, 227 - 256, // Get result
|
||||
137 - 256, 195 - 256,
|
||||
72, 193 - 256, 227 - 256, 4,
|
||||
128 - 256, 203 - 256, 2,
|
||||
72, 131 - 256, 196 - 256, 16, // Clean up stack
|
||||
195 - 256 // Return
|
||||
)
|
||||
val len = bytes.size
|
||||
val code = allocArray<ByteVar>(len)
|
||||
for (i in 0 until len) code[i] = bytes[i]
|
||||
val buf = mmap(null, len.toLong(), PROT_READ or PROT_WRITE or PROT_EXEC,
|
||||
MAP_PRIVATE or MAP_ANON, -1, 0)
|
||||
memcpy(buf, code, len.toLong())
|
||||
val a: Byte = 7
|
||||
val b: Byte = 12
|
||||
val c = runMachineCode(buf, a, b)
|
||||
munmap(buf, len.toLong())
|
||||
println("$a + $b = ${if(c >= 0) c.toInt() else c + 256}")
|
||||
}
|
||||
}
|
||||
51
Task/Machine-code/M2000-Interpreter/machine-code-1.m2000
Normal file
51
Task/Machine-code/M2000-Interpreter/machine-code-1.m2000
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
Module Checkit {
|
||||
Buffer DataMem as Long*10
|
||||
Return DataMem, 1:=500 ' second Long
|
||||
Print Eval(DataMem, 1)+5100+5=5605
|
||||
\\ Now we do math executing machine code
|
||||
Buffer Code ExecMem as byte*1024
|
||||
Address=0
|
||||
EmbLong(0xb8, 5100) ' mov eax,5100
|
||||
EmbByteByte(0x83, 0xC0, 5) ' add eax,0x5
|
||||
EmbByteLong(0x3,0x5, DataMem(1)) ' add eax, [DataMem(1)]
|
||||
EmbLong(0xa3, DataMem(0)) ' mov [DataMem(0)], eax
|
||||
\\ split rem to execute xor eax eax (eax=0)
|
||||
Rem : EmbByte(0x31, 0xC0) ' xor eax, eax
|
||||
Ret() ' Return
|
||||
\\
|
||||
Try ok {
|
||||
Execute Code ExecMem, 0
|
||||
}
|
||||
\\If Eax <>0 then we get error, so we read error as Uint()
|
||||
\\ Error read once then change to zero
|
||||
m=Uint(Error)
|
||||
\\ Hex is Print Hexadecimal for unsigned numbers
|
||||
Hex m
|
||||
Print m=5605
|
||||
Print Error=0, ok=False
|
||||
|
||||
Print Eval(DataMem, 0)=5605, Eval(DataMem, 0)
|
||||
\\ sub used as Exit here
|
||||
Sub Ret()
|
||||
Return ExecMem, Address:=0xC3
|
||||
Address++
|
||||
End Sub
|
||||
Sub EmbByteByte()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number, Address+2:=Number
|
||||
Address+=3
|
||||
End Sub
|
||||
Sub EmbByte()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number
|
||||
Address+=2
|
||||
End Sub
|
||||
Sub EmbLong()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number as Long
|
||||
Address+=5
|
||||
End Sub
|
||||
Sub EmbByteLong()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number, Address+2:=Number as Long
|
||||
Address+=6
|
||||
End Sub
|
||||
|
||||
}
|
||||
CheckIt
|
||||
42
Task/Machine-code/M2000-Interpreter/machine-code-2.m2000
Normal file
42
Task/Machine-code/M2000-Interpreter/machine-code-2.m2000
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
Function MyAdd {
|
||||
Buffer DataMem as Long*2
|
||||
Buffer Code ExecMem as byte*32
|
||||
Address=0
|
||||
EmbByte(0x31, 0xC0)
|
||||
EmbByteLong(0x3,0x5, DataMem(0)) ' add eax, [DataMem(0)]
|
||||
EmbByteLong(0x3,0x5, DataMem(1)) ' add eax, [DataMem(1)]
|
||||
EmbLong(0xa3, DataMem(0)) ' mov [DataMem(0)], eax
|
||||
Rem :
|
||||
EmbByte(0x31, 0xC0) ' xor eax, eax
|
||||
Ret() ' Return
|
||||
=lambda ExecMem, DataMem (a as double, b as double)-> {
|
||||
Return DataMem, 0:=a, 1:=b
|
||||
Try ok {
|
||||
Execute Code ExecMem, 0
|
||||
}
|
||||
If not ok then {
|
||||
=Uint(Error)
|
||||
} Else {
|
||||
=Eval(DataMem, 0)
|
||||
}
|
||||
}
|
||||
Sub Ret()
|
||||
Return ExecMem, Address:=0xC3
|
||||
Address++
|
||||
End Sub
|
||||
Sub EmbByte()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number
|
||||
Address+=2
|
||||
End Sub
|
||||
Sub EmbLong()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number as Long
|
||||
Address+=5
|
||||
End Sub
|
||||
Sub EmbByteLong()
|
||||
Return ExecMem, Address:=Number, Address+1:=Number, Address+2:=Number as Long
|
||||
Address+=6
|
||||
End Sub
|
||||
}
|
||||
\\ Produce a lambda function with machine code inside
|
||||
UnsingedAdd=MyAdd()
|
||||
Print UnsingedAdd(12, 7), UnsingedAdd(500, 100)
|
||||
22
Task/Machine-code/Nim/machine-code.nim
Normal file
22
Task/Machine-code/Nim/machine-code.nim
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import posix
|
||||
|
||||
let MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
|
||||
|
||||
proc test(a, b: cint): cint =
|
||||
# mov EAX, [ESP+4]
|
||||
# add EAX, [ESP+8]
|
||||
# ret
|
||||
var code = [0x8B'u8, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0xC3]
|
||||
|
||||
# create an executable buffer
|
||||
var buf = mmap(nil, sizeof(code), PROT_READ or PROT_WRITE or PROT_EXEC,
|
||||
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
|
||||
|
||||
# copy code to the buffer
|
||||
copyMem(buf, addr code[0], sizeof(code))
|
||||
# run code
|
||||
result = cast[proc(a, b: cint): cint {.nimcall.}](buf)(a, b)
|
||||
# free buffer
|
||||
discard munmap(buf, sizeof(code))
|
||||
|
||||
echo test(7, 12)
|
||||
29
Task/Machine-code/PARI-GP/machine-code.parigp
Normal file
29
Task/Machine-code/PARI-GP/machine-code.parigp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <pari/pari.h>
|
||||
|
||||
int
|
||||
test(int a, int b)
|
||||
{
|
||||
char code[] = {0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0xC3};
|
||||
void *buf;
|
||||
int c;
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_ANON,-1,0);
|
||||
|
||||
memcpy (buf, code, sizeof(code));
|
||||
/* run code */
|
||||
c = ((int (*) (int, int))buf)(a, b);
|
||||
/* free buffer */
|
||||
munmap (buf, sizeof(code));
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
init_auto(void)
|
||||
{
|
||||
pari_printf("%d\n", test(7,12));
|
||||
return 0;
|
||||
}
|
||||
68
Task/Machine-code/PL-M/machine-code.plm
Normal file
68
Task/Machine-code/PL-M/machine-code.plm
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
100H:
|
||||
|
||||
/* 8080 MACHINE CODE TO ADD TWO BYTES:
|
||||
79 MOV A,C ; LOAD FIRST ARG INTO ACCUMULATOR
|
||||
83 ADD E ; ADD SECOND ARG TO ACCUMULATOR
|
||||
C9 RET ; RETURN */
|
||||
|
||||
DECLARE ADD$8080 DATA (79H, 83H, 0C9H);
|
||||
|
||||
/* THE 8080 PL/M CALLING CONVENTION IS THAT THE
|
||||
NEXT-TO-LAST ARG IS PUT IN (B)C, THE LAST ARG IN (D)E.
|
||||
(THE REST ARE IN MEMORY BUT WE DO NOT NEED ANY MORE.)
|
||||
THE RETURN ARGUMENT SHOULD BE IN THE ACCUMULATOR.
|
||||
WE CAN DEFINE A WRAPPER PROCEDURE TO DECLARE THE
|
||||
TYPES OF THE ARGUMENTS. */
|
||||
|
||||
EXEC$ADD: PROCEDURE (A,B) BYTE;
|
||||
DECLARE (A,B) BYTE;
|
||||
/* WE CAN 'GO TO' CONSTANTS OR VARIABLES, BUT NOT TO
|
||||
EXPRESSIONS. SO WE HAVE TO FETCH THE ADDRESS FIRST. */
|
||||
DECLARE LOC ADDRESS;
|
||||
LOC = .ADD$8080;
|
||||
GO TO LOC;
|
||||
END EXEC$ADD;
|
||||
|
||||
/* IN FACT, PL/M DOES NOT COME WITH ANY STANDARD LIBARIES.
|
||||
IT IS FROM BEFORE THE TIME THAT YOU COULD ASSUME THERE
|
||||
WOULD EVEN BE AN OPERATING SYSTEM, THOUGH CP/M
|
||||
(THE PREDECESSOR TO DOS) WOULD QUICKLY BECOME STANDARD.
|
||||
|
||||
WE NEED TO USE THIS EXACT TRICK TO GET CP/M TO PRINT THE
|
||||
RESULT TO THE OUTPUT. LUCKILY (AND NOT COINCIDENTALLY),
|
||||
THE CP/M SYSCALL ENTRY POINT IS COMPATIBLE WITH THE
|
||||
PL/M CALLING CONVENTION. */
|
||||
|
||||
BDOS: PROCEDURE (FUNC, ARG);
|
||||
DECLARE FUNC BYTE;
|
||||
DECLARE ARG ADDRESS;
|
||||
/* 5 IS THE CP/M BDOS ENTRY POINT */
|
||||
GO TO 5;
|
||||
END BDOS;
|
||||
|
||||
/* WE ALSO NEED OUR OWN NUMBER OUTPUT ROUTINE. WE CAN WRITE
|
||||
IT IN PL/M, THEN USE THE ABOVE ROUTINE TO TELL CP/M
|
||||
TO PRINT THE RESULT. */
|
||||
|
||||
PRINT$NUMBER: PROCEDURE(N);
|
||||
DECLARE S (4) BYTE INITIAL ('...$');
|
||||
DECLARE P ADDRESS;
|
||||
DECLARE (N, C BASED P) BYTE;
|
||||
|
||||
/* EXTRACT EACH DIGIT AND WRITE THEM BACKWARDS TO A STRING */
|
||||
P = .S(3);
|
||||
DIGIT:
|
||||
P = P-1;
|
||||
C = (N MOD 10) + '0';
|
||||
N = N/10;
|
||||
IF N > 0 THEN GO TO DIGIT;
|
||||
|
||||
/* TELL CP/M TO PRINT THE RESULTING STRING */
|
||||
CALL BDOS(9, P);
|
||||
END PRINT$NUMBER;
|
||||
|
||||
/* USING OUR OWN MACHINE CODE WORKS IN THE SAME WAY */
|
||||
CALL PRINT$NUMBER( EXEC$ADD( 7, 12) ); /* THIS PRINTS 19 */
|
||||
|
||||
CALL BDOS(0,0); /* EXIT */
|
||||
EOF
|
||||
35
Task/Machine-code/Pascal/machine-code.pas
Normal file
35
Task/Machine-code/Pascal/machine-code.pas
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
Program Example66;
|
||||
{Inspired... program to demonstrate the MMap function. Freepascal docs }
|
||||
Uses
|
||||
BaseUnix,Unix;
|
||||
|
||||
const
|
||||
code : array[0..9] of byte = ($8B, $44, $24, $4, $3, $44, $24, $8, $C3, $00);
|
||||
a :longInt= 12;
|
||||
b :longInt= 7;
|
||||
type
|
||||
tDummyFunc = function(a,b:LongInt):LongInt;cdecl;
|
||||
Var
|
||||
Len,k : cint;
|
||||
P : Pointer;
|
||||
|
||||
begin
|
||||
len := sizeof(code);
|
||||
P:= fpmmap(nil,
|
||||
len+1 ,
|
||||
PROT_READ OR PROT_WRITE OR PROT_EXEC,
|
||||
MAP_ANONYMOUS OR MAP_PRIVATE,
|
||||
-1, // for MAP_ANONYMOUS
|
||||
0);
|
||||
If P = Pointer(-1) then
|
||||
Halt(4);
|
||||
|
||||
for k := 0 to len-1 do
|
||||
pChar(p)[k] := char(code[k]);
|
||||
|
||||
k := tDummyFunc(P)(a,b);
|
||||
|
||||
Writeln(a,'+',b,' = ',k);
|
||||
if fpMUnMap(P,Len)<>0 Then
|
||||
Halt(fpgeterrno);
|
||||
end.
|
||||
7
Task/Machine-code/Phix/machine-code-1.phix
Normal file
7
Task/Machine-code/Phix/machine-code-1.phix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
(notonline)-->
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">mem</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">poke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mem</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">#8B</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#44</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#04</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#03</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#44</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#08</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#C3</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">mfunc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">define_c_func</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">mem</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">C_INT</span><span style="color: #0000FF;">,</span><span style="color: #000000;">C_INT</span><span style="color: #0000FF;">},</span><span style="color: #000000;">C_INT</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">c_func</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mfunc</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mem</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
14
Task/Machine-code/Phix/machine-code-2.phix
Normal file
14
Task/Machine-code/Phix/machine-code-2.phix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-->
|
||||
<span style="color: #004080;">atom</span> <span style="color: #000000;">mem</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">poke</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mem</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">#8B</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#44</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#04</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#03</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#44</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#24</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#08</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#C3</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span>
|
||||
#ilASM{ mov eax,[mem]
|
||||
call :%pLoadMint -- eax:=(int32)eax, in case mem>#3FFFFFFF
|
||||
push 12
|
||||
push 7
|
||||
call eax
|
||||
add esp,8
|
||||
mov [res],eax }
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">res</span>
|
||||
<span style="color: #000000;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mem</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
26
Task/Machine-code/Phix/machine-code-3.phix
Normal file
26
Task/Machine-code/Phix/machine-code-3.phix
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
-->
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span>
|
||||
#ilASM{ jmp @f
|
||||
::add
|
||||
[32]
|
||||
mov eax,[esp+4]
|
||||
add eax,[esp+8]
|
||||
[64]
|
||||
mov rax,[rsp+8]
|
||||
add rax,[rsp+16]
|
||||
[]
|
||||
ret
|
||||
@@:
|
||||
push 12
|
||||
push 7
|
||||
call :add
|
||||
[32]
|
||||
add esp,8
|
||||
mov [res],eax
|
||||
[64]
|
||||
add rsp,16
|
||||
mov [res],rax
|
||||
[]
|
||||
}
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">res</span>
|
||||
<!--
|
||||
17
Task/Machine-code/Phix/machine-code-4.phix
Normal file
17
Task/Machine-code/Phix/machine-code-4.phix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-->
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span>
|
||||
#ilASM{
|
||||
[32]
|
||||
mov eax,12
|
||||
mov edx,7
|
||||
add eax,edx
|
||||
mov [res],eax
|
||||
[64]
|
||||
mov rax,12
|
||||
mov rdx,7
|
||||
add rax,rdx
|
||||
mov [res],rax
|
||||
[]
|
||||
}
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">res</span>
|
||||
<!--
|
||||
33
Task/Machine-code/PicoLisp/machine-code.l
Normal file
33
Task/Machine-code/PicoLisp/machine-code.l
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
(setq P
|
||||
(struct (native "@" "malloc" 'N 39) 'N
|
||||
# Align
|
||||
144 # nop
|
||||
144 # nop
|
||||
|
||||
# Prepare stack
|
||||
106 12 # pushq $12
|
||||
184 7 0 0 0 # mov $7, %eax
|
||||
72 193 224 32 # shl $32, %rax
|
||||
80 # pushq %rax
|
||||
|
||||
# Rosetta task code
|
||||
139 68 36 4 3 68 36 8
|
||||
|
||||
# Get result
|
||||
76 137 227 # mov %r12, %rbx
|
||||
137 195 # mov %eax, %ebx
|
||||
72 193 227 4 # shl $4, %rbx
|
||||
128 203 2 # orb $2, %bl
|
||||
|
||||
# Clean up stack
|
||||
72 131 196 16 # add $16, %rsp
|
||||
|
||||
# Return
|
||||
195 ) # ret
|
||||
foo (>> 4 P) )
|
||||
|
||||
# Execute
|
||||
(println (foo))
|
||||
|
||||
# Free memory
|
||||
(native "@" "free" NIL P)
|
||||
45
Task/Machine-code/PureBasic/machine-code.basic
Normal file
45
Task/Machine-code/PureBasic/machine-code.basic
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
CompilerIf #PB_Compiler_Processor <> #PB_Processor_x86
|
||||
CompilerError "Code requires a 32-bit processor."
|
||||
CompilerEndIf
|
||||
|
||||
|
||||
; Machine code using the Windows API
|
||||
|
||||
Procedure MachineCodeVirtualAlloc(a,b)
|
||||
*vm = VirtualAlloc_(#Null,?ecode-?scode,#MEM_COMMIT,#PAGE_EXECUTE_READWRITE)
|
||||
If(*vm)
|
||||
CopyMemory(?scode, *vm, ?ecode-?scode)
|
||||
eax_result=CallFunctionFast(*vm,a,b)
|
||||
VirtualFree_(*vm,0,#MEM_RELEASE)
|
||||
ProcedureReturn eax_result
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
rv=MachineCodeVirtualAlloc( 7, 12)
|
||||
MessageRequester("MachineCodeVirtualAlloc",Str(rv)+Space(50),#PB_MessageRequester_Ok)
|
||||
|
||||
#HEAP_CREATE_ENABLE_EXECUTE=$00040000
|
||||
|
||||
Procedure MachineCodeHeapCreate(a,b)
|
||||
hHeap=HeapCreate_(#HEAP_CREATE_ENABLE_EXECUTE,?ecode-?scode,?ecode-?scode)
|
||||
If(hHeap)
|
||||
CopyMemory(?scode, hHeap, ?ecode-?scode)
|
||||
eax_result=CallFunctionFast(hHeap,a,b)
|
||||
HeapDestroy_(hHeap)
|
||||
ProcedureReturn eax_result
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
||||
rv=MachineCodeHeapCreate(7,12)
|
||||
MessageRequester("MachineCodeHeapCreate",Str(rv)+Space(50),#PB_MessageRequester_Ok)
|
||||
End
|
||||
|
||||
; 8B442404 mov eax,[esp+4]
|
||||
; 03442408 add eax,[esp+8]
|
||||
; C20800 ret 8
|
||||
|
||||
DataSection
|
||||
scode:
|
||||
Data.a $8B,$44,$24,$04,$03,$44,$24,$08,$C2,$08,$00
|
||||
ecode:
|
||||
EndDataSection
|
||||
37
Task/Machine-code/Python/machine-code.py
Normal file
37
Task/Machine-code/Python/machine-code.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import ctypes
|
||||
import os
|
||||
from ctypes import c_ubyte, c_int
|
||||
|
||||
code = bytes([0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3])
|
||||
|
||||
code_size = len(code)
|
||||
# copy code into an executable buffer
|
||||
if (os.name == 'posix'):
|
||||
import mmap
|
||||
executable_map = mmap.mmap(-1, code_size, mmap.MAP_PRIVATE | mmap.MAP_ANON, mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC)
|
||||
# we must keep a reference to executable_map until the call, to avoid freeing the mapped memory
|
||||
executable_map.write(code)
|
||||
# the mmap object won't tell us the actual address of the mapping, but we can fish it out by allocating
|
||||
# some ctypes object over its buffer, then asking the address of that
|
||||
func_address = ctypes.addressof(c_ubyte.from_buffer(executable_map))
|
||||
elif (os.name == 'nt'):
|
||||
# the mmap module doesn't support protection flags on Windows, so execute VirtualAlloc instead
|
||||
code_buffer = ctypes.create_string_buffer(code)
|
||||
PAGE_EXECUTE_READWRITE = 0x40 # Windows constants that would usually come from header files
|
||||
MEM_COMMIT = 0x1000
|
||||
executable_buffer_address = ctypes.windll.kernel32.VirtualAlloc(0, code_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
|
||||
if (executable_buffer_address == 0):
|
||||
print('Warning: Failed to enable code execution, call will likely cause a protection fault.')
|
||||
func_address = ctypes.addressof(code_buffer)
|
||||
else:
|
||||
ctypes.memmove(executable_buffer_address, code_buffer, code_size)
|
||||
func_address = executable_buffer_address
|
||||
else:
|
||||
# for other platforms, we just hope DEP isn't enabled
|
||||
code_buffer = ctypes.create_string_buffer(code)
|
||||
func_address = ctypes.addressof(code_buffer)
|
||||
|
||||
prototype = ctypes.CFUNCTYPE(c_int, c_ubyte, c_ubyte) # build a function prototype from return type and argument types
|
||||
func = prototype(func_address) # build an actual function from the prototype by specifying the address
|
||||
res = func(7,12)
|
||||
print(res)
|
||||
23
Task/Machine-code/Racket/machine-code.rkt
Normal file
23
Task/Machine-code/Racket/machine-code.rkt
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#lang racket/base
|
||||
|
||||
(require ffi/unsafe)
|
||||
|
||||
; set up access to racket internals
|
||||
(define scheme-malloc-code
|
||||
(get-ffi-obj 'scheme_malloc_code #f (_fun (len : _intptr) -> _pointer)))
|
||||
(define scheme-free-code
|
||||
(get-ffi-obj 'scheme_free_code #f (_fun _pointer -> _void)))
|
||||
|
||||
(define opcodes '(139 68 36 4 3 68 36 8 195))
|
||||
|
||||
(define code (scheme-malloc-code 64))
|
||||
|
||||
(for ([byte opcodes]
|
||||
[i (in-naturals)])
|
||||
(ptr-set! code _ubyte i byte))
|
||||
|
||||
(define function (cast code _pointer (_fun _ubyte _ubyte -> _ubyte)))
|
||||
|
||||
(function 7 12)
|
||||
|
||||
(scheme-free-code code)
|
||||
1
Task/Machine-code/Raku/machine-code-1.raku
Normal file
1
Task/Machine-code/Raku/machine-code-1.raku
Normal file
|
|
@ -0,0 +1 @@
|
|||
c = ((int (*) (int, int))buf)(a, b);
|
||||
33
Task/Machine-code/Raku/machine-code-2.raku
Normal file
33
Task/Machine-code/Raku/machine-code-2.raku
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
use NativeCall;
|
||||
|
||||
constant PROT_READ = 0x1; #
|
||||
constant PROT_WRITE = 0x2; #
|
||||
constant PROT_EXEC = 0x4; # from local /usr/include/bits/mman.h
|
||||
constant MAP_PRIVATE = 0x02; #
|
||||
constant MAP_ANON = 0x20; #
|
||||
|
||||
sub mmap(Pointer $addr, size_t $length, int32 $prot, int32 $flags,
|
||||
int32 $fd, size_t $offset --> Pointer) is native { * };
|
||||
sub memcpy(Pointer $dest, Pointer $src, size_t $size --> Pointer) is native {*}
|
||||
sub munmap(Pointer $addr, size_t $length) is native { * };
|
||||
|
||||
sub test (uint8 $a, uint8 $b) {
|
||||
my $code = CArray[uint8].new(
|
||||
0x90, 0x90, 0x6A, 0xC, 0xB8, 0x7, 0x0, 0x0, 0x0, 0x48, 0xC1, 0xE0, 0x20,
|
||||
0x50, 0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0x4C, 0x89, 0xE3, 0x89,
|
||||
0xC3, 0x48, 0xC1, 0xE3, 0x4, 0x80, 0xCB, 0x2, 0x48, 0x83, 0xC4, 0x10, 0xC3
|
||||
);
|
||||
my $buf =
|
||||
mmap(Pointer, nativesizeof($code), PROT_READ +| PROT_WRITE +| PROT_EXEC,
|
||||
MAP_PRIVATE +| MAP_ANON, -1, 0);
|
||||
|
||||
memcpy($buf, nativecast(Pointer,$code), nativesizeof($code));
|
||||
|
||||
my $c; # = ((int (*) (int, int))buf)(a, b);
|
||||
|
||||
munmap($buf, nativesizeof($code));
|
||||
|
||||
return $c = "Incomplete Attempt";
|
||||
}
|
||||
|
||||
say test 7, 12;
|
||||
25
Task/Machine-code/Raku/machine-code-3.raku
Normal file
25
Task/Machine-code/Raku/machine-code-3.raku
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
|
||||
int test (int a, int b)
|
||||
{
|
||||
char code[] = {
|
||||
0x90, 0x90, 0x6A, 0xC, 0xB8, 0x7, 0x0, 0x0, 0x0, 0x48, 0xC1, 0xE0, 0x20,
|
||||
0x50, 0x8B, 0x44, 0x24, 0x4, 0x3, 0x44, 0x24, 0x8, 0x4C, 0x89, 0xE3, 0x89,
|
||||
0xC3, 0x48, 0xC1, 0xE3, 0x4, 0x80, 0xCB, 0x2, 0x48, 0x83, 0xC4, 0x10, 0xC3
|
||||
};
|
||||
|
||||
void *buf;
|
||||
int c;
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_ANON,-1,0);
|
||||
memcpy (buf, code, sizeof(code));
|
||||
/* run code */
|
||||
c = ((int (*) (int, int))buf)(a, b);
|
||||
/* free buffer */
|
||||
munmap (buf, sizeof(code));
|
||||
return c;
|
||||
}
|
||||
11
Task/Machine-code/Raku/machine-code-4.raku
Normal file
11
Task/Machine-code/Raku/machine-code-4.raku
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env raku
|
||||
|
||||
# 20200501 Raku programming solution
|
||||
|
||||
use NativeCall;
|
||||
|
||||
constant LIBTEST = '/home/user/LibTest.so';
|
||||
|
||||
sub test(uint8 $a, uint8 $b) returns uint8 is native(LIBTEST) { * };
|
||||
|
||||
say test 7, 12;
|
||||
44
Task/Machine-code/Rust/machine-code.rust
Normal file
44
Task/Machine-code/Rust/machine-code.rust
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
extern crate libc;
|
||||
|
||||
#[cfg(all(
|
||||
target_os = "linux",
|
||||
any(target_pointer_width = "32", target_pointer_width = "64")
|
||||
))]
|
||||
fn main() {
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
let page_size: usize = 4096;
|
||||
let (bytes, size): (Vec<u8>, usize) = if cfg!(target_pointer_width = "32") {
|
||||
(
|
||||
vec![0x8b, 0x44, 0x24, 0x04, 0x03, 0x44, 0x24, 0x08, 0xc3],
|
||||
9,
|
||||
)
|
||||
} else {
|
||||
(vec![0x48, 0x89, 0xf8, 0x48, 0x01, 0xf0, 0xc3], 7)
|
||||
};
|
||||
let f: fn(u8, u8) -> u8 = unsafe {
|
||||
let mut page: *mut libc::c_void = ptr::null_mut();
|
||||
libc::posix_memalign(&mut page, page_size, size);
|
||||
libc::mprotect(
|
||||
page,
|
||||
size,
|
||||
libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE,
|
||||
);
|
||||
let contents: *mut u8 = page as *mut u8;
|
||||
ptr::copy(bytes.as_ptr(), contents, 9);
|
||||
mem::transmute(contents)
|
||||
};
|
||||
|
||||
let return_value = f(7, 12);
|
||||
println!("Returned value: {}", return_value);
|
||||
assert_eq!(return_value, 19);
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_os = "linux"),
|
||||
not(any(target_pointer_width = "32", target_pointer_width = "64"))
|
||||
))]
|
||||
fn main() {
|
||||
println!("Not supported on this platform.");
|
||||
}
|
||||
17
Task/Machine-code/Smalltalk/machine-code-1.st
Normal file
17
Task/Machine-code/Smalltalk/machine-code-1.st
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
!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
|
||||
! !
|
||||
21
Task/Machine-code/Smalltalk/machine-code-2.st
Normal file
21
Task/Machine-code/Smalltalk/machine-code-2.st
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
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}
|
||||
34
Task/Machine-code/Swift/machine-code.swift
Normal file
34
Task/Machine-code/Swift/machine-code.swift
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import Foundation
|
||||
|
||||
typealias TwoIntsOneInt = @convention(c) (Int, Int) -> Int
|
||||
|
||||
let code = [
|
||||
144, // Align
|
||||
144,
|
||||
106, 12, // Prepare stack
|
||||
184, 7, 0, 0, 0,
|
||||
72, 193, 224, 32,
|
||||
80,
|
||||
139, 68, 36, 4, 3, 68, 36, 8, // Rosetta task code
|
||||
76, 137, 227, // Get result
|
||||
137, 195,
|
||||
72, 193, 227, 4,
|
||||
128, 203, 2,
|
||||
72, 131, 196, 16, // Clean up stack
|
||||
195, // Return
|
||||
] as [UInt8]
|
||||
|
||||
func fudge(x: Int, y: Int) -> Int {
|
||||
let buf = mmap(nil, code.count, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0)
|
||||
|
||||
memcpy(buf, code, code.count)
|
||||
|
||||
let fun = unsafeBitCast(buf, to: TwoIntsOneInt.self)
|
||||
let ret = fun(x, y)
|
||||
|
||||
munmap(buf, code.count)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
print(fudge(x: 7, y: 12))
|
||||
30
Task/Machine-code/Tcl/machine-code-1.tcl
Normal file
30
Task/Machine-code/Tcl/machine-code-1.tcl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package require critcl
|
||||
|
||||
critcl::ccode {
|
||||
#include <sys/mman.h>
|
||||
}
|
||||
|
||||
# Define a command using C. The C is embedded in Tcl, and will be
|
||||
# built into a shared library at runtime. Note that Tcl does not
|
||||
# provide a native way of doing this sort of thing; this thunk is
|
||||
# mandatory.
|
||||
critcl::cproc runMachineCode {Tcl_Obj* codeObj int a int b} int {
|
||||
int size, result;
|
||||
unsigned char *code = Tcl_GetByteArrayFromObj(codeObj, &size);
|
||||
void *buf;
|
||||
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap(0, (size_t) size, PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
memcpy(buf, code, (size_t) size);
|
||||
/* run code */
|
||||
result = ((int (*) (int, int)) buf)(a, b);
|
||||
/* dispose buffer */
|
||||
munmap(buf, (size_t) size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
# But now we have our thunk, we can execute arbitrary binary blobs
|
||||
set code [binary format c* {0x8B 0x44 0x24 0x4 0x3 0x44 0x24 0x8 0xC3}]
|
||||
puts [runMachineCode $code 7 12]
|
||||
4
Task/Machine-code/Tcl/machine-code-2.tcl
Normal file
4
Task/Machine-code/Tcl/machine-code-2.tcl
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
package require machineCodeThunk 1.0
|
||||
|
||||
set code [binary format c* {0x8B 0x44 0x24 0x4 0x3 0x44 0x24 0x8 0xC3}]
|
||||
puts [runMachineCode $code 7 12]
|
||||
20
Task/Machine-code/Wren/machine-code-1.wren
Normal file
20
Task/Machine-code/Wren/machine-code-1.wren
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* machine_code.wren */
|
||||
|
||||
class C {
|
||||
// pass the machine code in string form to the host
|
||||
foreign static runMachineCode(s, a, b)
|
||||
}
|
||||
|
||||
var a = 7
|
||||
var b = 12
|
||||
|
||||
// x64 opcodes for this task
|
||||
var m = [
|
||||
0x55, 0x48, 0x89, 0xe5, 0x89, 0x7d,
|
||||
0xfc, 0x89, 0x75, 0xf8, 0x8b, 0x75,
|
||||
0xfc, 0x03, 0x75, 0xf8, 0x89, 0x75,
|
||||
0xf4, 0x8b, 0x45, 0xf4, 0x5d, 0xc3
|
||||
]
|
||||
|
||||
var s = m.map { |byte| String.fromByte(byte) }.join()
|
||||
System.print("%(a) + %(b) = %(C.runMachineCode(s, a, b))")
|
||||
109
Task/Machine-code/Wren/machine-code-2.wren
Normal file
109
Task/Machine-code/Wren/machine-code-2.wren
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include "wren.h"
|
||||
|
||||
unsigned char rmc_helper(const char *code, unsigned char a, unsigned char b, int l) {
|
||||
void *buf;
|
||||
unsigned char c;
|
||||
|
||||
/* copy code to executable buffer */
|
||||
buf = mmap (0, l, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
memcpy(buf, code, l);
|
||||
|
||||
/* run code */
|
||||
c = ((unsigned char (*) (unsigned char, unsigned char))buf)(a, b);
|
||||
|
||||
/* free buffer */
|
||||
munmap(buf, l);
|
||||
|
||||
/* return result to caller */
|
||||
return c;
|
||||
}
|
||||
|
||||
void C_runMachineCode(WrenVM* vm) {
|
||||
/* unpack arguments passed from Wren */
|
||||
int *len;
|
||||
const char *code = wrenGetSlotBytes(vm, 1, len);
|
||||
unsigned char a = (unsigned char)wrenGetSlotDouble(vm, 2);
|
||||
unsigned char b = (unsigned char)wrenGetSlotDouble(vm, 3);
|
||||
|
||||
/* obtain result */
|
||||
unsigned char c = rmc_helper(code, a, b, *len);
|
||||
|
||||
/* return result to Wren */
|
||||
wrenSetSlotDouble(vm, 0, (double)c);
|
||||
}
|
||||
|
||||
WrenForeignMethodFn bindForeignMethod(
|
||||
WrenVM* vm,
|
||||
const char* module,
|
||||
const char* className,
|
||||
bool isStatic,
|
||||
const char* signature) {
|
||||
if (strcmp(module, "main") == 0) {
|
||||
if (strcmp(className, "C") == 0) {
|
||||
if (isStatic && strcmp(signature, "runMachineCode(_,_,_)") == 0) {
|
||||
return C_runMachineCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void writeFn(WrenVM* vm, const char* text) {
|
||||
printf("%s", text);
|
||||
}
|
||||
|
||||
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
|
||||
switch (errorType) {
|
||||
case WREN_ERROR_COMPILE:
|
||||
printf("[%s line %d] [Error] %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_STACK_TRACE:
|
||||
printf("[%s line %d] in %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_RUNTIME:
|
||||
printf("[Runtime Error] %s\n", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *readFile(const char *fileName) {
|
||||
FILE *f = fopen(fileName, "r");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
rewind(f);
|
||||
char *script = malloc(fsize + 1);
|
||||
fread(script, 1, fsize, f);
|
||||
fclose(f);
|
||||
script[fsize] = 0;
|
||||
return script;
|
||||
}
|
||||
|
||||
int main() {
|
||||
WrenConfiguration config;
|
||||
wrenInitConfiguration(&config);
|
||||
config.writeFn = &writeFn;
|
||||
config.errorFn = &errorFn;
|
||||
config.bindForeignMethodFn = &bindForeignMethod;
|
||||
WrenVM* vm = wrenNewVM(&config);
|
||||
const char* module = "main";
|
||||
const char* fileName = "machine_code.wren";
|
||||
char *script = readFile(fileName);
|
||||
WrenInterpretResult result = wrenInterpret(vm, module, script);
|
||||
switch (result) {
|
||||
case WREN_RESULT_COMPILE_ERROR:
|
||||
printf("Compile Error!\n");
|
||||
break;
|
||||
case WREN_RESULT_RUNTIME_ERROR:
|
||||
printf("Runtime Error!\n");
|
||||
break;
|
||||
case WREN_RESULT_SUCCESS:
|
||||
break;
|
||||
}
|
||||
wrenFreeVM(vm);
|
||||
free(script);
|
||||
return 0;
|
||||
}
|
||||
141
Task/Machine-code/X86-64-Assembly/machine-code.x86-64
Normal file
141
Task/Machine-code/X86-64-Assembly/machine-code.x86-64
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Linux Build:
|
||||
;; $ uasm -elf64 mexec.asm
|
||||
;; $ gcc -o mexec mexec.o -no-pie
|
||||
;; With MUSL libc
|
||||
;; $ musl-gcc -o mexec mexec.o -e main -nostartfiles -no-pie
|
||||
;;
|
||||
;; Windows Build:
|
||||
;; $ uasm64 -win64 mexec.asm
|
||||
;; $ link /machine:x64 /subsystem:console /release mexec.obj
|
||||
;; kernel32.lib msvcrt.lib
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
option casemap:none
|
||||
option literals:on
|
||||
|
||||
WIN64 equ 1
|
||||
LIN64 equ 3
|
||||
|
||||
ifndef __MEMEXEC_CLASS__
|
||||
__MEMEXEC_CLASS__ equ 1
|
||||
|
||||
if @Platform eq WIN64
|
||||
option dllimport:<kernel32>
|
||||
HeapAlloc proto fd:qword, flgs:dword, hlen:qword
|
||||
HeapFree proto fd:qword, flgs:dword, lpmem:qword
|
||||
GetProcessHeap proto
|
||||
ExitProcess proto uexit:word
|
||||
option dllimport:<msvcrt>
|
||||
printf proto fmt:qword, args:VARARG
|
||||
memcpy proto d:qword, s:qword, mlen:qword
|
||||
option dllimport:none
|
||||
exit equ ExitProcess
|
||||
elseif @Platform eq LIN64
|
||||
malloc proto SYSTEMV len:qword
|
||||
free proto SYSTEMV m:qword
|
||||
printf proto SYSTEMV fmt:qword, args:VARARG
|
||||
mprotect proto SYSTEMV m:qword, s:qword, flgs:dword
|
||||
memcpy proto SYSTEMV d:qword, s:qword, mlen:qword
|
||||
exit proto SYSTEMV uexit:word
|
||||
|
||||
PROT_READ equ 01h
|
||||
PROT_WRITE equ 02h
|
||||
PROT_EXEC equ 04h
|
||||
PROT_NONE equ 00h
|
||||
PROT_ALL equ PROT_READ + PROT_WRITE + PROT_EXEC
|
||||
endif
|
||||
|
||||
CLASS memexec
|
||||
CMETHOD run
|
||||
ENDMETHODS
|
||||
buff db 048h, 089h, 0F8h ;; mov rax, rdi
|
||||
db 048h, 001h, 0F0h ;; add rax, rsi
|
||||
db 0C3h ;; ret
|
||||
mem dq ? ;; Memory address
|
||||
mlen dq 0 ;; Memory size allocated?
|
||||
ENDCLASS
|
||||
|
||||
pmemexec typedef ptr memexec
|
||||
|
||||
METHOD memexec, Init, <VOIDARG>, <uses rcx>
|
||||
local tmp:qword
|
||||
|
||||
mov rbx, thisPtr
|
||||
assume rbx:ptr memexec
|
||||
lea rdx, [rbx].buff
|
||||
invoke printf, CSTR("[mexec->Init] - bytecode addr: 0x%X",10), rdx
|
||||
mov tmp, rdx
|
||||
mov [rbx].mlen, sizeof(tmp)
|
||||
invoke printf, CSTR("[mexec->Init] - bytecode len: %i",10), [rbx].mlen
|
||||
;; In Built memory allocator, used by the Class extention
|
||||
;; Uses either HeapAlloc for windows or malloc for everything else.
|
||||
;; Which is why I didn't use mmap in the first place.
|
||||
MEMALLOC([rbx].mlen)
|
||||
.if rax == -1
|
||||
invoke printf, CSTR("[exec->Init->Error] - Malloc failed with -1",10)
|
||||
mov rax, rbx
|
||||
ret
|
||||
.endif
|
||||
mov [rbx].mem, rax
|
||||
invoke printf, CSTR("[mexec->Init] - [rbx].mem addr: 0x%X",10), [rbx].mem
|
||||
;; Memory wont be executable by default from Malloc, So we make it
|
||||
;; so with mprotect. Not sure about windows, Might need to use a VirtualProtect
|
||||
;; call..
|
||||
if @Platform eq LIN64
|
||||
invoke mprotect, [rbx].mem, [rbx].mlen, PROT_ALL
|
||||
.if rax == -1
|
||||
invoke printf, CSTR("[exec]-Init->Error] - mprotect failed with -1",10)
|
||||
mov rax, rbx
|
||||
ret
|
||||
.endif
|
||||
endif
|
||||
invoke printf, CSTR("[mexec->Init] Copying [rbx].buff bytecode to 0x%X",10), [rbx].mem
|
||||
invoke memcpy, [rbx].mem, addr [rbx].buff, [rbx].mlen
|
||||
.if rax == -1
|
||||
invoke printf, CSTR("[mexec->Init->Error] - memcpy failed with -l",10)
|
||||
mov rax, rbx
|
||||
ret
|
||||
.endif
|
||||
mov rcx, [rbx].mem
|
||||
mov rax, rbx
|
||||
assume rbx:nothing
|
||||
ret
|
||||
ENDMETHOD
|
||||
|
||||
METHOD memexec, run, <VOIDARG>, <>, arg1:qword, arg2:qword
|
||||
mov rbx, thisPtr
|
||||
assume rbx:ptr memexec
|
||||
mov rdi, arg1
|
||||
mov rsi, arg2
|
||||
call [rbx].mem
|
||||
assume rbx:nothing
|
||||
ret
|
||||
ENDMETHOD
|
||||
|
||||
METHOD memexec, Destroy, <VOIDARG>, <>
|
||||
mov rbx, thisPtr
|
||||
assume rbx:ptr memexec
|
||||
mov [rbx].mlen, 0
|
||||
MEMFREE([rbx].mem)
|
||||
assume rbx:nothing
|
||||
ret
|
||||
ENDMETHOD
|
||||
|
||||
endif ;; __MEMEXEC_CLASS__
|
||||
.data
|
||||
a1 dq 7
|
||||
a2 dq 12
|
||||
|
||||
.code
|
||||
main proc
|
||||
local pmem:ptr memexec
|
||||
|
||||
mov pmem, _NEW(memexec)
|
||||
pmem->run(a1,a2)
|
||||
invoke printf, CSTR("[pmem->run(%i, %i)] - returned: %i",10), a1, a2, rax
|
||||
_DELETE(pmem)
|
||||
invoke exit, 0
|
||||
ret
|
||||
main endp
|
||||
|
||||
end
|
||||
11
Task/Machine-code/XPL0/machine-code.xpl0
Normal file
11
Task/Machine-code/XPL0/machine-code.xpl0
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
func Sum(A, B); \Return sum of A+B
|
||||
char A, B;
|
||||
[asm { ldrb r0, A
|
||||
ldrb r1, B
|
||||
add r0, r1
|
||||
strb r0, A
|
||||
}
|
||||
return A;
|
||||
];
|
||||
|
||||
IntOut(0, Sum(7, 12))
|
||||
49
Task/Machine-code/Z80-Assembly/machine-code.z80
Normal file
49
Task/Machine-code/Z80-Assembly/machine-code.z80
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
;;;;;;;;;;;;;;;;;;; HEADER ;;;;;;;;;;;;;;;;;;;
|
||||
read "\SrcCPC\winape_macros.asm"
|
||||
read "\SrcCPC\MemoryMap.asm"
|
||||
read "\SrcALL\winapeBuildCompat.asm"
|
||||
read "\SrcALL\lib\z80_opcode_chart.asm"
|
||||
;;;;;;;;;;;;;;;;;;; PROGRAM ;;;;;;;;;;;;;;;;;;;
|
||||
org &1000
|
||||
ld hl,machine_code_area
|
||||
|
||||
;assembles the following:
|
||||
;LD A,7
|
||||
;ADD 12
|
||||
;DAA
|
||||
;CALL SHOWHEX
|
||||
;RET
|
||||
|
||||
ld (hl),&3E ;LD A,nn
|
||||
inc hl
|
||||
ld (hl),7
|
||||
inc hl
|
||||
ld (hl),&C6 ;ADD nn
|
||||
inc hl
|
||||
ld (hl),12
|
||||
inc hl
|
||||
ld (hl),&27 ;DAA
|
||||
inc hl
|
||||
ld (hl),&CD ;call
|
||||
inc hl
|
||||
ld (hl),&00 ;low byte of address of showhex
|
||||
inc hl
|
||||
ld (hl),&11 ;high byte of address of showhex
|
||||
inc hl
|
||||
ld (hl),&C9 ;RET
|
||||
|
||||
;FALLTHROUGH IS INTENTIONAL
|
||||
machine_code_area:
|
||||
;0 = nop
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
byte 0,0,0,0,0,0,0,0
|
||||
|
||||
org &1100
|
||||
read "\SrcCPC\winape_showhex.asm" ;showhex is at &1100 thanks to the org.
|
||||
read "\SrcCPC\winape_stringop.asm"
|
||||
Loading…
Add table
Add a link
Reference in a new issue