Share your Programming Language Jam submissions here!

← Back to all posts
Aski: Assembly made easy.
h
pepsipu (35)

Hi, just as a pre note before we talk about the language and stuff. This is a programming language by Sophie Chen, Coco Gong, and Sammy Hajhamid. We used Rust for our compiler of this language, even though we aren't super familiar with it. We're all underclassmen in high school, so although it's not perfect and there is a LOT of room for improvement, we tried our best to spread our love for hardware!

Why Is Assembly So Gosh Dang Hard?

"Where are the variables?"

"Why is it so over complicated?"

"Why don't they use if statements?"

Just a few comments on our favorite programming language, Assembly. Assembly is different. It's unintuitive. It's not easy. We get it! At Troy High School's hardware club, we are trying to figure out how to spread Assembly to make it more accessible to everyone, even if it's a little different then what our fellow students are used to. A lot of the members understand concepts like pointers and memory, but feel the jump from C to Assembly is a leap far too large for anyone with a mild interest in learning the language. Even outside our club, people view Assembly as unintelligible text if not aided with a decompiler. That's why we decided to make a language to make this jump a little smaller.

Introducing Aski, also known as Assembly made easy! By providing key concepts in Assembly (like registers, the stack, jumps, system calls, the heap, and all sorts of fun stuff) in a non linear, non instruction-like fasion, learning the concepts of Assembly can be a lot easier than it used to be! By reintroducing if statements and expressions and keeping the code in a C-like syntax, the code is easier on the eyes as well as the mind. Take a look at two snippets of code, one written in Assembly, and another written in Aski.

cmp rax, 0
jne .ne
mov rsi, my_text
lea rsi, [rsi+8]
mov [rsi], 0
.ne:

(Oh how it burns my eyes!)

It takes a thorough effort to even understand what's going on here. What madness! With Aski, the program's intent becomes a lot clearer.

if $rax == 0 {
	$rsi = my_text + 8
	$*rsi = 0
}

Here we can clearly see my_text is getting null terminated at the 8th byte. So why was it so obscure in the Assembly code? Well, Assembly, due to its linear nature, makes it difficult to see the path code execution takes and why. In addition, simple tasks (like writing a null byte to the end of a string) can end up being way more instructions than what you'd expect. Although Aski compiles down to the same assembly code, people learning Assembly can get a feel and build an intuition for Assembly by matching Aski statements with their corresponding Assembly output.

Now let's go over the semantics of the language.

Syntax

All Aski code given to the compiler is converted to Assembly to allow Assembly newbies to read it.

Aski is aimed to resemble C syntax, while aimed to execute as Assembly instructions would. This means, like assembly, you manipulate the registers yourself!

$rax = 2

is fundamentally the same as

mov rax, 2

Though, to keep things easy for those new to Assembly, you can also do

$rax = $rax + $rsi * 4 * 2 + $rdi

which will expand into

lea rsi, [rsi*8]
add rax, rsi
add rax, rdi

or some equivalent.

Comments

Comments follow traditional assembly syntax, using semicolons.

; this is a comment!

Functions

Defining a function can be done like so.

fn foo {

}

Return instructions are automatically generated at the end of the function, so don't worry about having to add them yourself!

Calling a function is also very easy!

call(foo)

You can also expose a function to the linker by using the extern keyword. You'll want to do this for your _start function.

extern fn _start() {

}

Constants and Buffers

A constant string, number, or any other read-only data can be marked with the const keyword. For example,

const hello = "hello world!"

Strings are not null-terminated. If you'd like, you can terminate them yourselves.

Buffers are similar! use the let keyword.

let user_input: [byte, 32]

Woah, Woah, Woah! What's this [byte, 32] thing? Well, that's the integrated type system. Let's go over it really quickly.

Type System

Types specify the size of each unit as well as the number of units. For example, in the previous example, the size of the unit was a byte and the buffer was 32 bytes. But, if we change byte to qword, each unit will be 8 bytes long, so that'd mean the entire buffer would be 256 bytes!

let chunks: [qword, 32]
; that's 256 bytes!

To obtain the bytes occupied by a variable, just use the sizeof() function.

$rax = sizeof(chunks) - 1
; 255

Control Flow

Currently, if statements are the only implemented control flow structure, besides call. Our modular compiler will allow us to while and for loops with not much more effort, but due to time constraints we're only working with if statements. They are similar to Rust if statements.

if $rax * 2 + rsi != $rdx - 3 {
  ; code here
}

Inline Assembly

Something you need that Aski doesn't have? Use some inline assembly!

#syscall

Just prefix with a hashtag.

Example

Here's an example program that takes a file name and spits out it's contents!

const hello = "welcome to fs reader!"

const file_question = "what file would you like to read?"

const no_input_err = "no input given!"

let user_buf: [byte, 128]

; 64 chunks to store file data
let file_data: [qword, 64]

extern fn _start {
    $rsi = hello
    $rdx = sizeof(hello)
    call(print)

    call(menu)
}

fn menu {
    $rsi = file_question
    $rdx = sizeof(file_question)
    call(print)

    $rsi = user_buf
    $rdx = sizeof(user_buf)
    call(read_input)

    ; account for newline
    if $rax == 1 {
        $rsi = no_input_err
        $rdx = sizeof(no_input_err)
        call(print)
        call(exit)
    }

    ; null terminate input & remove newline
    $rsi = user_buf
    $rdi = $rsi + $rax - 1
    $*rdi = 0

    $rdi = user_buf
    call(open)

    ; give fd of file to rdi
    $rdi = $rax
    $rax = 0
    $rsi = file_data
    $rdx = sizeof(file_data)
    #syscall

    $rdx = $rax
    $rsi = file_data
    call(print)

    call(menu)
}

fn read_input {
    $rax = 0
    $rdi = 0
    #syscall
}

; prints the string in rsi and size in rdx
fn print {
    ; sys_write
    $rax = 1
    ; stdout
    $rdi = 1
    #syscall
}

fn exit {
    $rax = 60
    $rdi = 0
    #syscall
}

fn open {
    $rax = 2
    $rsi = 0
    $rdx = 0
    #syscall
}

https://repl.it/@aski/aski

Commentshotnewtop
alvinneocom (4)

this is 10/10, would write bootloader in it

mamcx (11)

Cool. Probably you know but LLVM ir is like this idea too. Some stuff that could be very cool is create in-built SIMD code:

$sval = 1, 2, 3
$sadd = $sval  + 1
$smap =  call(print, $sval) //do map, filter, fold and suddenly this can do all!
DynamicSquid (4373)

@mamcx I heard llvm is super complicated

pepsipu (35)

@mamcx llvm is great! unfortunately, since llvm uses standard calling conventions and does not provide as much control over the registers, we opted for making assembly by hand.

CSharpIsGud (643)

@sugarfi not that simple, for facilis we were going to use llvm but decided to just transpile because we didn't feel like wasting the time trying to read their awful documentation.

sugarfi (587)

@CSharpIsGud their documentation is great, what are you talking about?

xxpertHacker (499)

@sugarfi Sorry for being 25 days late, but link the "good" documentation. I just didn't have time to try LLVM's setup programs and try to learn it.

sugarfi (587)

@xxpertHacker

I just didn't have time to try LLVM's setup programs and try to learn it.

there's your problem...

DungeonMaster00 (149)

@sugarfi gimme the good documentation

Vandesm14 (2431)

This is amazing! This is definitely underrated. I will totally use this in the near future. It'd be cool if you could input assembly code and have it turned into Aski code.

pepsipu (35)

@Vandesm14 Thank you! The hardware club worked very hard on it :)

xxpertHacker (499)

This seems nice, but... it doesn't seem like an assembly language anymore. It genuinely seems more like a C family language than an Asm language.

systemctl (18)

This is pretty cool and useful

CodeLongAndPros (1467)

Return instructions are automatically generated at the end of the function, so don't worry about having to add them yourself!

Uh Explicit is better than implicit....

pepsipu (35)

@CodeLongAndPros thanks for your feedback! if you'd like to see something about the language changed, submit a pull request at https://github.com/pepsipu/aski.

PatrikBaso (0)

definitely best idea in here!

PatrikBaso (0)

but.. does it work for different assembler languages?

pepsipu (35)

@PatrikBaso aski produces intel syntax assembly. because one of aski's primary purposes is to teach, we chose intel's clear and concise syntax over at&t's messy and unwieldy syntax.

AmazingMech2418 (943)

Nice! Though, I do have one question. Are there loops using the jump keywords (jmp, jne/jnz, je/jz, jle, jge, jg, jl, etc.)?

pepsipu (35)

@AmazingMech2418 They can be used with #, but for loops and while loops can be implemented with if statements and tail recursion.

TheDrone7 (1436)

Hey there! This jam required you to create a repl.it team and it was heavily emphasized as well. But I see that you submitted a personal repl. Can I enquire as to why you did not submit a team repl?

pepsipu (35)

@TheDrone7 We created a repl team called aski, but the repl from the git repo was made on mine on accident. Is it too late to fix this?

TheDrone7 (1436)

@pepsipu It is not. You can still make a team repl and provide a link to it in the post. As long as you have made no changes to the language after the deadline.

pepsipu (35)

@TheDrone7 the new repl is https://repl.it/@aski/aski. I can't find out how to edit the post though?

TheDrone7 (1436)

@pepsipu you can edit the post by clicking the small "Edit" text between the post description and the embedded repl.

pepsipu (35)

@TheDrone7 Everything should be good now, thank you for your help :D

snowysunbeam (0)

the most beautiful assembly I've ever seen

ZeenWan (0)

:00 love this!! the idea is fantastic and the code looks great, it's definitely a language I want to learn