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();