Machine code: Difference between revisions
Content added Content deleted
(Added XPL0 example.) |
Not a robot (talk | contribs) (Add Draco) |
||
Line 401: | Line 401: | ||
{{out}} |
{{out}} |
||
19 |
19 |
||
=={{header|Draco}}== |
|||
It is possible to call any random area of memory as if it were a function by casting it |
|||
to a function of the right type, similar to C. The following example stores the code in |
|||
an array. The CP/M version of Draco passes the arguments on the stack in left-to-right |
|||
order (so they are popped off in right-to-left order). |
|||
<lang draco>/* 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</lang> |
|||
{{out}} |
|||
<pre>19</pre> |
|||
Draco also supports inline machine code directly, using the <code>code()</code> |
|||
construct. The machine code is emitted in place during compilation, and cannot |
|||
be changed at runtime. It is possible to refer to variables directly, whose |
|||
address will be emitted. The linker will even adjust these addresses as required. |
|||
<lang draco>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</lang> |
|||
{{out}} |
|||
<pre>19</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |