Monday, June 28, 2021

Generating ARM Assembly: First Steps

Finally took the plunge to start generating ARM64 assembly. As expected, the actual coding was much easier than overcoming the barrier to just start doing it.

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 :-)

2 comments:

カンドレ said...

so basically this is using a high level language to output assembly files, as opposed to directly doing it by hand...?

if 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

Marcel Weiher said...

Yes, this is absolutely nothing spectacular, just the start of a backend for native code generation (i.e. a native compiler backend).

Next steps, apart from making it more complete, is to hook this up to the Objective-S compiler.