From: Mike Lowis Date: Wed, 17 Jul 2024 20:45:06 +0000 (-0400) Subject: implemented variable, code, and end-code words X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=87e2ac7f359c0df011a88ca0f1baf3883f78a07d;p=proto%2Fforth.git implemented variable, code, and end-code words --- diff --git a/asm.rb b/asm.rb index 8ad54ef..06ac54b 100755 --- a/asm.rb +++ b/asm.rb @@ -25,6 +25,12 @@ PROG = [ Word = Struct.new(:name, :flags, :code) IMM = 1 +class Integer + def between(a,b) + (self >= a) and (self <= b) + end +end + def push(arg); $stack.push(arg); end def pop(); $stack.pop(); end def do_word(code); code.each{|w| w.call() }; end @@ -37,6 +43,110 @@ def builtin(name, &code) $words[name] = Word.new(name, 0, code) end +def call(word) + $words[word].code.call() +end + +def pack8(val, off = nil) + PROG[off || PROG.length] = (val & 0xff) +end + +def pack16(val, off = nil) + off ||= PROG.length + PROG[off + 0] = ((val >> 0) & 0xff) + PROG[off + 1] = ((val >> 8) & 0xff) +end + +def pack32(val, off = nil) + off ||= PROG.length + PROG[off + 0] = ((val >> 0) & 0xff) + PROG[off + 1] = ((val >> 8) & 0xff) + PROG[off + 2] = ((val >> 16) & 0xff) + PROG[off + 3] = ((val >> 24) & 0xff) +end + +def pack64(val, off = nil) + off ||= PROG.length + PROG[off + 0] = ((val >> 0) & 0xff) + PROG[off + 1] = ((val >> 8) & 0xff) + PROG[off + 2] = ((val >> 16) & 0xff) + PROG[off + 3] = ((val >> 24) & 0xff) + PROG[off + 4] = ((val >> 32) & 0xff) + PROG[off + 5] = ((val >> 40) & 0xff) + PROG[off + 6] = ((val >> 48) & 0xff) + PROG[off + 7] = ((val >> 56) & 0xff) +end + +def packBytes(bytes) + PROG.append(*bytes) +end + +def packPadding(overflow) + padding = (8 - overflow) + padding.times{ pack8(0) } if padding < 8 +end + +def unpack8(off) + PROG[off] +end + +def unpack16(off) + return ( + PROG[off] | + (PROG[off] << 8) + ) +end + +def unpack32(off) + ( + (PROG[off]) | + (PROG[off] << 8) | + (PROG[off] << 16) | + (PROG[off] << 24) + ) +end + +def unpack64(off) + ( + (PROG[off + 0]) | + (PROG[off + 1] << 8) | + (PROG[off + 2] << 16) | + (PROG[off + 3] << 24) | + (PROG[off + 4] << 32) | + (PROG[off + 5] << 40) | + (PROG[off + 6] << 48) | + (PROG[off + 7] << 56) + ) +end + +def base_offset() + unpack64(24) +end + +def mov_imm(val, reg) + if val == 0 then + if reg <= 7 then + packBytes([0x48, 0x31, 0xc0 + (reg * 9)]) + else + packBytes([0x4d, 0x31, 0xc0 + ((reg - 8) * 9)]) + end + elsif val.between(-2147483648,2147483647) + if reg <= 7 then + packBytes([0x48, 0xC7, 0xc0 | reg]) + else + packBytes([0x49, 0xC7, 0xc0 | (reg - 8)]) + end + pack32(val) + else + if reg <= 7 then + packBytes([0x48, 0xB8 + reg]) + else + packBytes([0x49, 0xB8 + (reg - 8)]) + end + pack64(val) + end +end + #------------------------------------------ # Interpreter/Compiler State #------------------------------------------ @@ -189,7 +299,6 @@ builtin('bin') { builtin('#') { $buffer = $input.gets -# puts " #{$buffer.inspect}" } builtin('.') { @@ -201,122 +310,99 @@ builtin('.') { } builtin('word') do -# puts " word" word = nil while word.nil? if $buffer.length == 0 then $buffer = $input.gets -# puts " #{$buffer.inspect}" break if $buffer.nil? end $buffer.slice!(/^\s*/) word = $buffer.slice!(/^[^\s]+/) end -# puts " word: #{word}" -# puts " end word" push word end -builtin('create') do - $curr = Word.new(pop(), 0, []) +builtin('variable') do + offset = base_offset() + call('word') + name = pop() + + allocation = (3 + ((name.length + 1) / 8.0).ceil) * 8 + value_addr = (offset + PROG.length) + code_addr = offset + (allocation * 8) + + pack64(0) # VALUE + pack64(code_addr) # CODE ADDR + pack64(0) # LINK - TODO: actually link to latest + pack8(name.length) # NAME LEN + packBytes(name.bytes) # NAME + packPadding(PROG.length % 8) + + mov_imm(value_addr, 0) # load address + packBytes([0x48, 0x8D, 0x6D, 0x08]) # lea 0x8(%rbp),%rbp + packBytes([0x48, 0x89, 0x45, 0x00]) # mov %rax,(%rbp) + packPadding(PROG.length % 8) end -builtin('[') do - $state = 1 -end +builtin('code') do + offset = base_offset() + call('word') + name = pop() + + allocation = (2 + ((name.length + 1) / 8.0).ceil) * 8 + code_addr = offset + (allocation * 8) -builtin(']') do - $state = 0 + pack64(code_addr) # CODE ADDR + pack64(0) # LINK - TODO: actually link to latest + pack8(name.length) # NAME LEN + packBytes(name.bytes) # NAME + packPadding(PROG.length % 8) end -builtin('register') do - code = $curr.code - $curr.code = lambda { do_word(code) } - $words[$curr.name] = $curr - pp $words +builtin('end-code') do + call('ret') + packPadding(PROG.length % 8) end -word(':', IMM, [ 'word', 'create', '[' ]) -word(';', IMM, [ ']', 'register' ]) + +#builtin('create') do +# $curr = Word.new(pop(), 0, []) +#end +# +#builtin('[') do +# $state = 1 +#end +# +#builtin(']') do +# $state = 0 +#end +# +#builtin('register') do +# code = $curr.code +# $curr.code = lambda { do_word(code) } +# $words[$curr.name] = $curr +# pp $words +#end +# +#word(':', IMM, [ 'word', 'create', '[' ]) +# +#word(';', IMM, [ ']', 'register' ]) #------------------------------------------ # Assembler Words #------------------------------------------ -def pack8(val, off = nil) - PROG[off || PROG.length] = (val & 0xff) -end - -def pack16(val, off = nil) - off ||= PROG.length - PROG[off + 0] = ((val >> 0) & 0xff) - PROG[off + 1] = ((val >> 8) & 0xff) -end - -def pack32(val, off = nil) - off ||= PROG.length - PROG[off + 0] = ((val >> 0) & 0xff) - PROG[off + 1] = ((val >> 8) & 0xff) - PROG[off + 2] = ((val >> 16) & 0xff) - PROG[off + 3] = ((val >> 24) & 0xff) -end - -def pack64(val, off = nil) - off ||= PROG.length - PROG[off + 0] = ((val >> 0) & 0xff) - PROG[off + 1] = ((val >> 8) & 0xff) - PROG[off + 2] = ((val >> 16) & 0xff) - PROG[off + 3] = ((val >> 24) & 0xff) - PROG[off + 4] = ((val >> 32) & 0xff) - PROG[off + 5] = ((val >> 40) & 0xff) - PROG[off + 6] = ((val >> 48) & 0xff) - PROG[off + 7] = ((val >> 56) & 0xff) -end - -def packBytes(bytes) - PROG.append(*bytes) -end - -def unpack8(off) - PROG[off] -end - -def unpack16(off) - return ( - PROG[off] | - (PROG[off] << 8) - ) -end - -def unpack32(off) - ( - (PROG[off]) | - (PROG[off] << 8) | - (PROG[off] << 16) | - (PROG[off] << 24) - ) -end - -def unpack64(off) - ( - (PROG[off + 0]) | - (PROG[off + 1] << 8) | - (PROG[off + 2] << 16) | - (PROG[off + 3] << 24) | - (PROG[off + 4] << 32) | - (PROG[off + 5] << 40) | - (PROG[off + 6] << 48) | - (PROG[off + 7] << 56) - ) -end - - builtin("here") { push PROG.length } +#builtin("allot") { +# packBytes(Array.new(pop()*8, 0)) +#} + + builtin("@") { push unpack64(pop()) } @@ -340,24 +426,11 @@ builtin("-!") { } +builtin("set-entry-address") { + prev = unpack64(24) + pack64(prev + (PROG.length - 0x78), 24) +} -# -# 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, # 00 -# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 08 -# 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, # 16 -# 0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 24 e_entry: 0x0x00400078, (virtual memory address of entry point) -# 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 32 -# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 40 -# 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, # 48 -# 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 56 -# 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, # 64 -# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 72 -# 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, # 78 p_vaddr: 0x00400000, (virtual address of segment in memory) -# 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 86 -# 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 94 p_filesz: 0x00011E02, (size in bytes of the segment in the file) -# 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, # 102 p_memsz: 0x7FC00000, (siz - -builtin("entry-address") { push 24 } builtin("virt-address") { push 78 } builtin("segment-size") { push 102 } @@ -404,20 +477,7 @@ builtin('pop-reg') { builtin('load-imm') { reg = pop() val = pop() - if val == 0 then - if reg <= 7 then - packBytes([0x48, 0x31, 0xc0 + (reg * 9)]) - else - packBytes([0x4d, 0x31, 0xc0 + ((reg - 8) * 9)]) - end - else - if reg <= 7 then - packBytes([0x48, 0xC7, 0xc0 | reg]) - else - packBytes([0x49, 0xC7, 0xc0 | (reg - 8)]) - end - pack32(val) - end + mov_imm(val, reg) } builtin('syscall') { diff --git a/asm.s b/asm.s index f0bcc34..c848cac 100644 --- a/asm.s +++ b/asm.s @@ -1,16 +1,29 @@ -# record our current offset for later use -here +# WORD DEFINITION STRUCTURE +# +# +----------------------+ +# | FLAGS | CODE ADDRESS | +# +----------------------+ +# | LINK | +# +----------------------+ +# | NAME LEN | NAME .... | +# | .................... | +# +----------------------+ +# | CODE ............... | +# +----------------------+ + +# ---------------------------------------- +# SYSTEM CONSTANTS +# ---------------------------------------- # ---------------------------------------- # SYSTEM VARIABLES # ---------------------------------------- -# Allocate space for variables -0 pack64 # LATEST -0 pack64 # STATE -0 pack64 # HERE -0 pack64 # S0 -0 pack64 # R0 +variable latest +variable state +variable here +variable S0 +variable R0 # ---------------------------------------- # DEFINE BUILTIN WORDS @@ -23,12 +36,31 @@ here # interpret # end +# : ] +# begin +# bl find dup if +# -1 = if +# execute ?stack abort " Stack empty" +# else +# , +# then +# else +# drop (number) postpone literal +# then +# again ; + +# : interpret +# begin +# bl find if execute +# ?stack abort " Stack empty" +# else number then +# again ; + # ---------------------------------------- # ENTRY CODE STARTS HERE # ---------------------------------------- -# update our entry address to here -here swap - entry-address +! +set-entry-address 60 rax load-imm 42 rdi load-imm diff --git a/test.c b/test.c index ad59538..dd07d77 100644 --- a/test.c +++ b/test.c @@ -1,5 +1,13 @@ void test(void) { +// leaq -8(%rbp),%rbp /* push reg on to return stack */ +// movq \reg,(%rbp) + + + asm("lea 8(%rbp), %rbp"); + asm("mov %rax, (%rbp)"); + + // asm("mov $60, %eax"); // asm("xor %rdi, %rdi"); // asm("syscall"); @@ -13,9 +21,10 @@ void test(void) // asm("push %rbx"); // asm("mov $0x01020304, %rcx"); // asm("push %rcx"); -// asm("mov $0x0123456789, %rdx"); // asm("push %rdx"); + + asm("xor %rax,%rax"); asm("xor %rcx,%rcx"); asm("xor %rdx,%rdx"); @@ -33,40 +42,22 @@ void test(void) asm("xor %r14,%r14"); asm("xor %r15,%r15"); - asm("pop %rax"); - asm("pop %rcx"); - asm("pop %rdx"); - asm("pop %rbx"); - asm("pop %rsp"); - asm("pop %rbp"); - asm("pop %rsi"); - asm("pop %rdi"); - asm("pop %r8"); - asm("pop %r9"); - asm("pop %r10"); - asm("pop %r11"); - asm("pop %r12"); - asm("pop %r13"); - asm("pop %r14"); - asm("pop %r15"); - - - asm("mov $0x2A, %rax"); - asm("mov $0x2A, %rcx"); - asm("mov $0x2A, %rdx"); - asm("mov $0x2A, %rbx"); - asm("mov $0x2A, %rsp"); - asm("mov $0x2A, %rbp"); - asm("mov $0x2A, %rsi"); - asm("mov $0x2A, %rdi"); - asm("mov $0x2A, %r8"); - asm("mov $0x2A, %r9"); - asm("mov $0x2A, %r10"); - asm("mov $0x2A, %r11"); - asm("mov $0x2A, %r12"); - asm("mov $0x2A, %r13"); - asm("mov $0x2A, %r14"); - asm("mov $0x2A, %r15"); + asm("mov $0x01, %rax"); + asm("mov $0x01, %rcx"); + asm("mov $0x01, %rdx"); + asm("mov $0x01, %rbx"); + asm("mov $0x01, %rsp"); + asm("mov $0x01, %rbp"); + asm("mov $0x01, %rsi"); + asm("mov $0x01, %rdi"); + asm("mov $0x01, %r8"); + asm("mov $0x01, %r9"); + asm("mov $0x01, %r10"); + asm("mov $0x01, %r11"); + asm("mov $0x01, %r12"); + asm("mov $0x01, %r13"); + asm("mov $0x01, %r14"); + asm("mov $0x01, %r15"); asm("syscall");