33 lines
1.2 KiB
Plaintext
33 lines
1.2 KiB
Plaintext
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();
|