FIRST STUFF

canary
Neon 2022-02-22 03:39:07 -05:00
commit 8adccb7b65
6 changed files with 242 additions and 0 deletions

3
.gitignore vendored 100644
View File

@ -0,0 +1,3 @@
disco
out
*.o

52
disco.asm 100644
View File

@ -0,0 +1,52 @@
section .data
text db "abc",10,0
section .bss
stackArguments resb 64
trip resb 8 ; temporary return instruction pointer (for stack manipulation)
; tem resb 64
section .text
global _start
_start:
push text
call _print
call _exit
_print:
; first we remove the params from the stack
; remembering to not fuck up our return pointer
pop qword [trip] ; pop old instruction pointer, save for later.
pop rax ; pop first argument
push qword [trip] ; push the old execution pointer back
; reset base stack to here.
push rbp
mov rbp, rsp
; push in our arguments
push rax
; rbp+0 => old base pointer
; rbp+8 => old instruction pointer
; rbp+16 => last param
; rbp+24 => first param
mov rax, 1
mov rdi, 1
mov rsi, [rbp - 8]
mov rdx, 4
syscall
; pop variables (arguments) off stack
add rsp, 8
pop rbp
ret
_exit:
mov rax, 60
mov rdi, 0
syscall
ret

3
disco.disco 100644
View File

@ -0,0 +1,3 @@
link log
log("hello\n")

140
disco.js 100755
View File

@ -0,0 +1,140 @@
#!/usr/bin/env node
const AST = {
Body(statements) { return { type: 'body', value: statements } },
Identifier(name) { return { type: 'iden', value: name } },
Link(identifier) { return { type: 'link', value: identifier } },
Const(name, value) { return { type: 'const', name, value } },
Int(n) { return { type: 'int', value: n } },
String(s) { return { type: 'string', value: s } },
Invocation(identifier, ...args) { return { type: 'invo', value: identifier, args } }
}
const linkables = {
log: {
asmName: '_log',
asm: `\
push rax
mov rbx, 0
_log_loop:
mov cl, [rax]
cmp cl, 0
je _log_loop_end
inc rax
inc rbx
jmp _log_loop
_log_loop_end:
mov rdx, rbx
mov rax, 1
mov rdi, 1
pop rsi
syscall
ret`
}
}
function compile(body) {
const linkedFunctions = {}
// add linked functions
// add static literals
// add main statments
const rname = () => (new Array(8).fill('')).map(() => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[Math.floor(Math.random() * 26)]).join('');
const literals = {
}
let mainStatements = '';
const parseLink = (identifier) => {
console.assert(identifier.type === 'iden', 'EXPECTED IDENTIFIER AFTER LINK');
console.assert(identifier.value in linkables, 'CANNOT FIND LINK ' + identifier.value);
linkedFunctions[identifier.value] = linkables[identifier.value];
}
const parseString = (string) => {
const name = rname();
literals[name] = string.value
return name;
}
const parseInvocation = (invocation) => {
console.assert(invocation.value.value in linkedFunctions, 'UNKNOWN FUNCTION ' + invocation.value);
const stuffIdk = [];
for(const arg of invocation.args) {
switch(arg.type) {
case 'string': {
const asmName = parseString(arg);
stuffIdk.push(asmName);
break;
}
}
}
mainStatements += `\
mov rax, ${stuffIdk[0]}
call ${linkedFunctions[invocation.value.value].asmName}
`
}
const parseBody = (body) => {
for(const node of body.value) {
switch(node.type) {
case 'link': {
parseLink(node.value);
break;
}
case 'invo': {
parseInvocation(node);
break;
}
}
}
}
parseBody(body);
return `\
section .data
${Object.entries(literals).map(([name, string]) => {
return " " + name + " db \"" + string + "\",10,0";
})}
section .text
global _start
_start:
${mainStatements}
call _exit
_exit:
mov rax, 60
mov rdi, 0
syscall
${Object.values(linkedFunctions).map(({asmName, asm}) => {
return `${asmName}:\n${asm}`
}).join('\n\n')}`
}
require('fs').writeFileSync('out.asm', compile(AST.Body([
AST.Link(AST.Identifier('log')),
AST.Invocation(
AST.Identifier('log'),
AST.String('Hello World')
)
])));
try {
require('child_process').execSync('nasm -f elf64 out.asm -o out.o');
require('child_process').execSync('ld out.o -o out');
require('child_process').execSync('./out', { stdio: 'inherit' });
} catch (e) {
}

33
out.asm 100644
View File

@ -0,0 +1,33 @@
section .data
YMYJYNCD db "Hello World",10,0
section .text
global _start
_start:
mov rax, YMYJYNCD
call _log
call _exit
_exit:
mov rax, 60
mov rdi, 0
syscall
_log:
push rax
mov rbx, 0
_log_loop:
mov cl, [rax]
cmp cl, 0
je _log_loop_end
inc rax
inc rbx
jmp _log_loop
_log_loop_end:
mov rdx, rbx
mov rax, 1
mov rdi, 1
pop rsi
syscall
ret

11
package.json 100644
View File

@ -0,0 +1,11 @@
{
"name": "disco",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "nasm -f elf64 disco.asm -o disco.o && ld disco.o -o disco",
"start": "./disco",
"dev": "yarn build && yarn start"
}
}