The following snippet generates a program that prints a message to stdout
, so
a classic "Hello World":
#!env stsh
#-gen:msg
messageLabel ← 'message'.
main ← '_main'.
framework:ObjSTNative load
arm := MPWARMAssemblyGenerator stream
arm global: main;
align:2;
label:main;
mov:0 value:1;
adr:1 address:messageLabel;
mov:2 value: msg length;
mov:16 value:4;
svc:128;
mov:0 value:0;
ret;
label:messageLabel;
asciiz:msg.
file:hello-main.s := arm target
One little twist is that the message to print gets passed to the generator. I like how Smalltalk's keyword syntax keeps the code uncluttered, and often pretty close to the actual assembly that will be generated.
Of particular help here is message cascading using the semicolon. This means I don't have to repeat the receiver of the message, but can just keep sending it messages. Cascading works well together with streams, because there are no return values to contend with, we just keep appending to the stream.
When invoked using ./genhello-main.st 'Hi Marcel, finish that blog post and get on your bike!'
, the generated code is as follows:
.global _main
.align 2
_main:
mov X0, #1
adr X1, message
mov X2, #54
mov X16, #4
svc #128
mov X0, #0
ret
message:
.asciz "Hi Marcel, finish that blog post and get on your bike!"
And now I am going to do what it says :-)
so basically this is using a high level language to output assembly files, as opposed to directly doing it by hand...?
ReplyDeleteif that is right, then theoretically, since you already have high level constructs (objects?) it should be easy to output to other things such as simulators or even other forms of code?
sorry if i missed the big picture
Yes, this is absolutely nothing spectacular, just the start of a backend for native code generation (i.e. a native compiler backend).
ReplyDeleteNext steps, apart from making it more complete, is to hook this up to the Objective-S compiler.