mirror of
https://github.com/samsonjs/compiler.git
synced 2026-04-27 14:57:45 +00:00
[NEW] Boolean expressions. Print statement.
This commit is contained in:
parent
55c047d0ef
commit
dc23e23b92
8 changed files with 575 additions and 39 deletions
16
Makefile
16
Makefile
|
|
@ -1,5 +1,19 @@
|
||||||
|
lt: test.rb test_lt.code
|
||||||
|
ruby test.rb test_lt.code > test_lt.asm
|
||||||
|
nasm -f elf -g -o test_lt.o test_lt.asm
|
||||||
|
ld -o test_lt test_lt.o
|
||||||
|
# $? indicates success as per unix convention
|
||||||
|
./test_lt
|
||||||
|
|
||||||
|
print: test.rb test_print.code
|
||||||
|
ruby test.rb test_print.code > test_print.asm
|
||||||
|
nasm -f elf -g -o test_print.o test_print.asm
|
||||||
|
ld -o test_print test_print.o
|
||||||
|
# $? indicates success as per unix convention
|
||||||
|
./test_print
|
||||||
|
|
||||||
build: test.rb test.code
|
build: test.rb test.code
|
||||||
ruby test.rb test.code
|
ruby test.rb test.code > test.asm
|
||||||
nasm -f elf -g -o test.o test.asm
|
nasm -f elf -g -o test.o test.asm
|
||||||
ld -o test test.o
|
ld -o test test.o
|
||||||
# $? indicates success as per unix convention
|
# $? indicates success as per unix convention
|
||||||
|
|
|
||||||
311
compiler.rb
311
compiler.rb
|
|
@ -29,8 +29,9 @@ class Compiler
|
||||||
|
|
||||||
# reserved words (... constant?)
|
# reserved words (... constant?)
|
||||||
#
|
#
|
||||||
# if, else, end, while, until, repeat, for, do, break
|
# if, else, end, while, until, repeat, do, for, break, true, false, print,
|
||||||
@keywords = %w[i l e w u r f d b]
|
# not, and, or, add, subtract, multiply, divide, xor, bool tests
|
||||||
|
@keywords = %w[i l e w u r f d b t f p ! & | + - * / ^ = < > #]
|
||||||
|
|
||||||
# seed the lexer
|
# seed the lexer
|
||||||
get_char
|
get_char
|
||||||
|
|
@ -63,12 +64,12 @@ class Compiler
|
||||||
def factor
|
def factor
|
||||||
if @look == '('
|
if @look == '('
|
||||||
match('(')
|
match('(')
|
||||||
expression
|
boolean_expression
|
||||||
match(')')
|
match(')')
|
||||||
elsif alpha?(@look)
|
elsif alpha?(@look)
|
||||||
identifier # or call
|
identifier # or call
|
||||||
elsif digit?(@look)
|
elsif digit?(@look)
|
||||||
x86_mov(:eax, get_num)
|
x86_mov(:eax, get_number)
|
||||||
else
|
else
|
||||||
expected(:'integer, identifier, function call, or parenthesized expression')
|
expected(:'integer, identifier, function call, or parenthesized expression')
|
||||||
end
|
end
|
||||||
|
|
@ -76,15 +77,10 @@ class Compiler
|
||||||
|
|
||||||
# Parse a signed factor.
|
# Parse a signed factor.
|
||||||
def signed_factor
|
def signed_factor
|
||||||
unary_op = if @look == '-'
|
sign = @look
|
||||||
match('-')
|
match(sign) if sign == '-' || sign == '+'
|
||||||
:neg
|
|
||||||
elsif @look == '+'
|
|
||||||
match('+')
|
|
||||||
:pos
|
|
||||||
end
|
|
||||||
factor
|
factor
|
||||||
x86_neg(:eax) if unary_op == :neg
|
x86_neg(:eax) if sign == '-'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse and translate a single term (factor or mulop). Result is in
|
# Parse and translate a single term (factor or mulop). Result is in
|
||||||
|
|
@ -172,12 +168,162 @@ class Compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#######################
|
||||||
|
# boolean expressions #
|
||||||
|
#######################
|
||||||
|
|
||||||
|
def boolean_expression
|
||||||
|
boolean_term
|
||||||
|
|
||||||
|
while orop?
|
||||||
|
x86_push(:eax)
|
||||||
|
case @look
|
||||||
|
when '|': or_expr
|
||||||
|
when '^': xor_expr
|
||||||
|
end
|
||||||
|
x86_add(:esp, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def or_expr
|
||||||
|
match('|')
|
||||||
|
boolean_term
|
||||||
|
x86_or(:eax, '[esp]')
|
||||||
|
end
|
||||||
|
|
||||||
|
def xor_expr
|
||||||
|
match('^')
|
||||||
|
boolean_term
|
||||||
|
x86_xor(:eax, '[esp]')
|
||||||
|
end
|
||||||
|
|
||||||
|
def boolean_term
|
||||||
|
not_factor
|
||||||
|
|
||||||
|
while andop?
|
||||||
|
x86_push(:eax)
|
||||||
|
# and_expr
|
||||||
|
match('&')
|
||||||
|
not_factor
|
||||||
|
x86_and(:eax, '[esp]')
|
||||||
|
x86_add(:esp, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def boolean_factor
|
||||||
|
if boolean?(@look)
|
||||||
|
if get_boolean
|
||||||
|
x86_mov(:eax, -1)
|
||||||
|
else
|
||||||
|
x86_xor(:eax, :eax)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
relation
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def not_factor
|
||||||
|
if @look == '!'
|
||||||
|
match('!')
|
||||||
|
boolean_factor
|
||||||
|
make_boolean(:eax) # ensure it is -1 or 0...
|
||||||
|
x86_not(:eax) # so that not is also boolean not
|
||||||
|
else
|
||||||
|
boolean_factor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Convert any identifier to a boolean (-1 or 0). This is
|
||||||
|
# semantically equivalent to !!reg in C or Ruby.
|
||||||
|
def make_boolean(reg=:eax)
|
||||||
|
end_label = unique_label(:endmakebool)
|
||||||
|
x86_cmp(reg, 0) # if false do nothing
|
||||||
|
x86_jz(end_label)
|
||||||
|
x86_mov(reg, -1) # truthy, make it true
|
||||||
|
emit_label(end_label)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_boolean
|
||||||
|
expected(:boolean) unless boolean?(@look)
|
||||||
|
value = @look == 't'
|
||||||
|
get_char
|
||||||
|
value
|
||||||
|
end
|
||||||
|
|
||||||
|
def relation
|
||||||
|
expression
|
||||||
|
if relop?
|
||||||
|
x86_push(:eax)
|
||||||
|
case @look
|
||||||
|
when '=': eq_relation
|
||||||
|
when '#': neq_relation
|
||||||
|
when '>': gt_relation
|
||||||
|
when '<': lt_relation
|
||||||
|
# TODO ge, le (needs real tokens)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def eq_relation
|
||||||
|
match('=')
|
||||||
|
expression
|
||||||
|
x86_pop(:ebx)
|
||||||
|
x86_sub(:eax, :ebx)
|
||||||
|
make_boolean
|
||||||
|
x86_not(:eax)
|
||||||
|
end
|
||||||
|
|
||||||
|
def neq_relation
|
||||||
|
match('#')
|
||||||
|
expression
|
||||||
|
x86_pop(:ebx)
|
||||||
|
x86_sub(:eax, :ebx)
|
||||||
|
make_boolean
|
||||||
|
end
|
||||||
|
|
||||||
|
def gt_relation
|
||||||
|
match('>')
|
||||||
|
gt_label = unique_label(:gt)
|
||||||
|
end_label = unique_label(:endgt)
|
||||||
|
expression
|
||||||
|
x86_pop(:ebx)
|
||||||
|
x86_cmp(:eax, :ebx) # b - a < 0 if a > b
|
||||||
|
x86_jl(gt_label)
|
||||||
|
x86_xor(:eax, :eax)
|
||||||
|
x86_jmp(end_label)
|
||||||
|
emit_label(gt_label)
|
||||||
|
x86_xor(:eax, :eax)
|
||||||
|
x86_not(:eax)
|
||||||
|
emit_label(end_label)
|
||||||
|
end
|
||||||
|
|
||||||
|
def lt_relation
|
||||||
|
match('<')
|
||||||
|
lt_label = unique_label(:lt)
|
||||||
|
end_label = unique_label(:endlt)
|
||||||
|
expression
|
||||||
|
x86_pop(:ebx)
|
||||||
|
x86_cmp(:ebx, :eax) # a - b < 0 if a < b
|
||||||
|
x86_jl(lt_label)
|
||||||
|
x86_xor(:eax, :eax)
|
||||||
|
x86_jmp(end_label)
|
||||||
|
emit_label(lt_label)
|
||||||
|
x86_xor(:eax, :eax)
|
||||||
|
x86_not(:eax)
|
||||||
|
emit_label(end_label)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
######################################
|
||||||
|
# statements and controls structures #
|
||||||
|
######################################
|
||||||
|
|
||||||
# Parse an assignment statement. Value is in eax.
|
# Parse an assignment statement. Value is in eax.
|
||||||
def assignment
|
def assignment
|
||||||
name = get_name
|
name = get_name
|
||||||
match('=')
|
match('=')
|
||||||
expression
|
boolean_expression
|
||||||
var(name)
|
defvar(name) unless var?(name)
|
||||||
x86_mov("dword [#{name}]", :eax)
|
x86_mov("dword [#{name}]", :eax)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -199,6 +345,9 @@ class Compiler
|
||||||
do_stmt
|
do_stmt
|
||||||
when 'b'
|
when 'b'
|
||||||
break_stmt(label)
|
break_stmt(label)
|
||||||
|
when 'p'
|
||||||
|
print_stmt
|
||||||
|
newline
|
||||||
else
|
else
|
||||||
assignment
|
assignment
|
||||||
newline
|
newline
|
||||||
|
|
@ -210,10 +359,10 @@ class Compiler
|
||||||
# Parse an if-else statement.
|
# Parse an if-else statement.
|
||||||
def if_else_stmt(label)
|
def if_else_stmt(label)
|
||||||
match('i')
|
match('i')
|
||||||
condition
|
|
||||||
skip_any_whitespace
|
|
||||||
else_label = unique_label(:end_or_else)
|
else_label = unique_label(:end_or_else)
|
||||||
end_label = else_label # only generated if else clause present
|
end_label = else_label # only generated if else clause present
|
||||||
|
condition
|
||||||
|
skip_any_whitespace
|
||||||
x86_jz(else_label)
|
x86_jz(else_label)
|
||||||
block(label)
|
block(label)
|
||||||
if @look == 'l'
|
if @look == 'l'
|
||||||
|
|
@ -278,12 +427,12 @@ class Compiler
|
||||||
end_label = unique_label(:endfor)
|
end_label = unique_label(:endfor)
|
||||||
counter = "[#{get_name}]"
|
counter = "[#{get_name}]"
|
||||||
match('=')
|
match('=')
|
||||||
expression # initial value
|
boolean_expression # initial value
|
||||||
x86_sub(:eax, 1) # pre-decrement because of the
|
x86_sub(:eax, 1) # pre-decrement because of the
|
||||||
# following pre-increment
|
# following pre-increment
|
||||||
x86_mov(counter, :eax) # stash the counter in memory
|
x86_mov(counter, :eax) # stash the counter in memory
|
||||||
match('>'); match('>')
|
match('.'); match('.')
|
||||||
expression # final value
|
boolean_expression # final value
|
||||||
skip_any_whitespace
|
skip_any_whitespace
|
||||||
x86_push(:eax) # stash final value on stack
|
x86_push(:eax) # stash final value on stack
|
||||||
final = '[esp]'
|
final = '[esp]'
|
||||||
|
|
@ -307,7 +456,7 @@ class Compiler
|
||||||
match('d')
|
match('d')
|
||||||
start_label = unique_label(:do)
|
start_label = unique_label(:do)
|
||||||
end_label = unique_label(:enddo)
|
end_label = unique_label(:enddo)
|
||||||
expression
|
boolean_expression
|
||||||
skip_any_whitespace
|
skip_any_whitespace
|
||||||
x86_mov(:ecx, :eax)
|
x86_mov(:ecx, :eax)
|
||||||
x86_push(:ecx)
|
x86_push(:ecx)
|
||||||
|
|
@ -335,11 +484,54 @@ class Compiler
|
||||||
|
|
||||||
# Evaluates any expression for now. There are no boolean operators.
|
# Evaluates any expression for now. There are no boolean operators.
|
||||||
def condition
|
def condition
|
||||||
expression
|
boolean_expression
|
||||||
x86_cmp(:eax, 0) # 0 is false, anything else is true
|
|
||||||
skip_whitespace
|
skip_whitespace
|
||||||
|
x86_cmp(:eax, 0) # 0 is false, anything else is true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def print_stmt
|
||||||
|
match('p')
|
||||||
|
# define a lookup table of digits
|
||||||
|
unless var?('DIGITS')
|
||||||
|
defvar('DIGITS', 4)
|
||||||
|
x86_mov('dword [DIGITS]', 0x33323130)
|
||||||
|
x86_mov('dword [DIGITS+4]', 0x37363534)
|
||||||
|
x86_mov('dword [DIGITS+8]', 0x62613938)
|
||||||
|
x86_mov('dword [DIGITS+12]', 0x66656463)
|
||||||
|
end
|
||||||
|
# 3 dwords == 12 chars
|
||||||
|
defvar('HEX', 3) unless var?('HEX')
|
||||||
|
# TODO check sign and prepend '-' if negative
|
||||||
|
x86_mov('word [HEX]', 0x7830) # "0x" == [48, 120]
|
||||||
|
x86_mov('word [HEX+10]', 0xa) # newline + null terminator
|
||||||
|
boolean_expression
|
||||||
|
# convert eax to a hex string
|
||||||
|
x86_lea(:esi, '[DIGITS]')
|
||||||
|
x86_lea(:edi, '[HEX+9]')
|
||||||
|
# build the string backwards (right to left), byte by byte
|
||||||
|
x86_mov(:ecx, 4)
|
||||||
|
emit_label(loop_label=unique_label)
|
||||||
|
# low nybble of nth byte
|
||||||
|
x86_movzx(:ebx, :al)
|
||||||
|
x86_and(:bl, 0x0f) # isolate low nybble
|
||||||
|
x86_movzx(:edx, 'byte [esi+ebx]')
|
||||||
|
x86_mov('byte [edi]', :dl)
|
||||||
|
x86_dec(:edi)
|
||||||
|
# high nybble of nth byte
|
||||||
|
x86_movzx(:ebx, :al)
|
||||||
|
x86_and(:bl, 0xf0) # isolate high nybble
|
||||||
|
x86_shr(:bl, 4)
|
||||||
|
x86_mov(:dl, 'byte [esi+ebx]')
|
||||||
|
x86_mov('byte [edi]', :dl)
|
||||||
|
x86_dec(:edi)
|
||||||
|
x86_shr(:eax, 8)
|
||||||
|
x86_loop(loop_label)
|
||||||
|
x86_mov(:eax, 4) # SYS_write
|
||||||
|
x86_mov(:ebx, 1) # STDOUT
|
||||||
|
x86_lea(:ecx, '[HEX]')
|
||||||
|
x86_mov(:edx, 11) # excluding term, max # of chars to print
|
||||||
|
x86_int(0x80)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
|
|
@ -359,6 +551,17 @@ class Compiler
|
||||||
@look == '*' || @look == '/'
|
@look == '*' || @look == '/'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def relop?
|
||||||
|
@look == '=' || @look == '#' || @look == '<' || @look == '>'
|
||||||
|
end
|
||||||
|
|
||||||
|
def orop?
|
||||||
|
@look == '|' || @look == '^'
|
||||||
|
end
|
||||||
|
|
||||||
|
def andop?
|
||||||
|
@look == '&'
|
||||||
|
end
|
||||||
|
|
||||||
# Read the next character from the input stream.
|
# Read the next character from the input stream.
|
||||||
def get_char
|
def get_char
|
||||||
|
|
@ -403,6 +606,10 @@ class Compiler
|
||||||
alpha?(char) || digit?(char)
|
alpha?(char) || digit?(char)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def boolean?(char)
|
||||||
|
char == 't' || char == 'f'
|
||||||
|
end
|
||||||
|
|
||||||
def whitespace?(char)
|
def whitespace?(char)
|
||||||
char == ' ' || char == "\t"
|
char == ' ' || char == "\t"
|
||||||
end
|
end
|
||||||
|
|
@ -451,7 +658,7 @@ class Compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# Parse a number.
|
# Parse a number.
|
||||||
def get_num
|
def get_number
|
||||||
expected(:integer) unless digit?(@look)
|
expected(:integer) unless digit?(@look)
|
||||||
many(method(:digit?))
|
many(method(:digit?))
|
||||||
end
|
end
|
||||||
|
|
@ -473,15 +680,23 @@ class Compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# Define a variable with the given name and size (in dwords).
|
# Define a variable with the given name and size (in dwords).
|
||||||
def var(name, dwords=1)
|
def defvar(name, dwords=1)
|
||||||
unless @vars[name]
|
unless var?(name)
|
||||||
@bss << "#{name}: resd #{dwords}\n"
|
@bss << "#{name}: resd #{dwords}\n"
|
||||||
@vars[name] = name
|
@vars[name] = name
|
||||||
# else
|
else
|
||||||
# raise ParseError, "identifier #{name} redefined"
|
STDERR.puts "[warning] attempted to redefine #{name}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def var?(name)
|
||||||
|
@vars[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
def var(name)
|
||||||
|
@vars[name]
|
||||||
|
end
|
||||||
|
|
||||||
# Emit a line of code wrapped between a tab and a newline.
|
# Emit a line of code wrapped between a tab and a newline.
|
||||||
def emit(code, options={})
|
def emit(code, options={})
|
||||||
tab = options.has_key?(:tab) ? options[:tab] : "\t"
|
tab = options.has_key?(:tab) ? options[:tab] : "\t"
|
||||||
|
|
@ -506,7 +721,11 @@ class Compiler
|
||||||
# Some asm methods for convenience and arity checks.
|
# Some asm methods for convenience and arity checks.
|
||||||
|
|
||||||
def x86_mov(dest, src)
|
def x86_mov(dest, src)
|
||||||
emit("mov #{dest}, #{src}")
|
emit("mov #{dest}, #{src.is_a?(Numeric) ? "0x#{src.to_s(16)}" : src}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def x86_movzx(dest, src)
|
||||||
|
emit("movzx #{dest}, #{src}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def x86_add(dest, src)
|
def x86_add(dest, src)
|
||||||
|
|
@ -529,10 +748,18 @@ class Compiler
|
||||||
emit("inc #{op}")
|
emit("inc #{op}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_dec(op)
|
||||||
|
emit("dec #{op}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_push(reg)
|
def x86_push(reg)
|
||||||
emit("push #{reg}")
|
emit("push #{reg}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_pop(reg)
|
||||||
|
emit("pop #{reg}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_call(label)
|
def x86_call(label)
|
||||||
emit("call #{label}")
|
emit("call #{label}")
|
||||||
end
|
end
|
||||||
|
|
@ -541,10 +768,22 @@ class Compiler
|
||||||
emit("neg #{reg}")
|
emit("neg #{reg}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_not(rm32)
|
||||||
|
emit("not #{rm32}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_xchg(op1, op2)
|
def x86_xchg(op1, op2)
|
||||||
emit("xchg #{op1}, #{op2}")
|
emit("xchg #{op1}, #{op2}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_and(op1, op2)
|
||||||
|
emit("and #{op1}, #{op2}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def x86_or(op1, op2)
|
||||||
|
emit("or #{op1}, #{op2}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_xor(op1, op2)
|
def x86_xor(op1, op2)
|
||||||
emit("xor #{op1}, #{op2}")
|
emit("xor #{op1}, #{op2}")
|
||||||
end
|
end
|
||||||
|
|
@ -561,11 +800,27 @@ class Compiler
|
||||||
emit("jmp #{label}")
|
emit("jmp #{label}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_jl(label)
|
||||||
|
emit("jl #{label}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_cmp(a, b)
|
def x86_cmp(a, b)
|
||||||
emit("cmp #{a}, #{b}")
|
emit("cmp #{a}, #{b}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_lea(a, b)
|
||||||
|
emit("lea #{a}, #{b}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def x86_shr(a, b)
|
||||||
|
emit("shr #{a}, #{b}")
|
||||||
|
end
|
||||||
|
|
||||||
def x86_loop(label)
|
def x86_loop(label)
|
||||||
emit("loop #{label}")
|
emit("loop #{label}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def x86_int(num)
|
||||||
|
emit("int 0x#{num.to_s(16)}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
21
test.code
21
test.code
|
|
@ -1,4 +1,4 @@
|
||||||
a=9
|
a=1
|
||||||
aa=10
|
aa=10
|
||||||
somethinglong=65536
|
somethinglong=65536
|
||||||
x=5*(3-5)
|
x=5*(3-5)
|
||||||
|
|
@ -19,7 +19,7 @@ i1x=3
|
||||||
i1c=4
|
i1c=4
|
||||||
ee
|
ee
|
||||||
|
|
||||||
i 1
|
i 1 > 2
|
||||||
x=3
|
x=3
|
||||||
i 1 c=4
|
i 1 c=4
|
||||||
e
|
e
|
||||||
|
|
@ -28,25 +28,28 @@ l
|
||||||
e
|
e
|
||||||
|
|
||||||
w 0
|
w 0
|
||||||
a = a + 1
|
w a < 10
|
||||||
|
a = a + 1
|
||||||
|
e
|
||||||
e
|
e
|
||||||
|
|
||||||
u 1
|
u a = 0
|
||||||
a = a - 1
|
a = a - 1
|
||||||
i 1
|
i t
|
||||||
b
|
b
|
||||||
e
|
e
|
||||||
e
|
e
|
||||||
|
|
||||||
|
cc = c
|
||||||
r
|
r
|
||||||
cc = c * 2
|
cc = cc * 2
|
||||||
i 1
|
i cc = 32
|
||||||
b
|
b
|
||||||
e
|
e
|
||||||
e
|
e
|
||||||
|
|
||||||
s=0
|
s=0
|
||||||
f x = 1 >> 5
|
f x = 1 .. 5
|
||||||
s = s + x
|
s = s + x
|
||||||
e
|
e
|
||||||
|
|
||||||
|
|
@ -54,4 +57,4 @@ d 10
|
||||||
a = a * a
|
a = a * a
|
||||||
e
|
e
|
||||||
|
|
||||||
xitcode=a-a
|
xitcode=(1 < 1)
|
||||||
|
|
|
||||||
2
test.rb
2
test.rb
|
|
@ -32,7 +32,7 @@ def main(arg)
|
||||||
data, bss, code = *parse(input)
|
data, bss, code = *parse(input)
|
||||||
template = File.read("template.asm")
|
template = File.read("template.asm")
|
||||||
asm = interpolate(template, :data => data, :bss => bss, :code => code)
|
asm = interpolate(template, :data => data, :bss => bss, :code => code)
|
||||||
File.open("test.asm", "w") { |f| f.puts(asm) }
|
STDOUT.puts(asm)
|
||||||
end
|
end
|
||||||
|
|
||||||
main(ARGV[0].to_s)
|
main(ARGV[0].to_s)
|
||||||
|
|
|
||||||
54
test_lt.asm
Normal file
54
test_lt.asm
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
GLOBAL _start
|
||||||
|
SECTION .data
|
||||||
|
|
||||||
|
SECTION .bss
|
||||||
|
z: resd 1
|
||||||
|
x: resd 1
|
||||||
|
y: resd 1
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
_start:
|
||||||
|
mov eax, 1
|
||||||
|
push eax
|
||||||
|
mov eax, 1
|
||||||
|
pop ebx
|
||||||
|
cmp ebx, eax
|
||||||
|
jl L000001_lt_1
|
||||||
|
xor eax, eax
|
||||||
|
jmp L000002_endlt_1
|
||||||
|
L000001_lt_1:
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
L000002_endlt_1:
|
||||||
|
mov dword [z], eax
|
||||||
|
mov eax, 1
|
||||||
|
push eax
|
||||||
|
mov eax, 3
|
||||||
|
pop ebx
|
||||||
|
cmp ebx, eax
|
||||||
|
jl L000003_lt_2
|
||||||
|
xor eax, eax
|
||||||
|
jmp L000004_endlt_2
|
||||||
|
L000003_lt_2:
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
L000004_endlt_2:
|
||||||
|
mov dword [x], eax
|
||||||
|
mov eax, 3
|
||||||
|
push eax
|
||||||
|
mov eax, 1
|
||||||
|
pop ebx
|
||||||
|
cmp ebx, eax
|
||||||
|
jl L000005_lt_3
|
||||||
|
xor eax, eax
|
||||||
|
jmp L000006_endlt_3
|
||||||
|
L000005_lt_3:
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
L000006_endlt_3:
|
||||||
|
mov dword [y], eax
|
||||||
|
|
||||||
|
;; The result in eax is the exit code, move it to ebx.
|
||||||
|
mov ebx, eax
|
||||||
|
mov eax, 1 ; _exit syscall
|
||||||
|
int 0x80 ; call Linux
|
||||||
3
test_lt.code
Normal file
3
test_lt.code
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
x = 1 < 3
|
||||||
|
y = 3 < 1
|
||||||
|
z = 1 < 1
|
||||||
199
test_print.asm
Normal file
199
test_print.asm
Normal file
|
|
@ -0,0 +1,199 @@
|
||||||
|
GLOBAL _start
|
||||||
|
SECTION .data
|
||||||
|
|
||||||
|
SECTION .bss
|
||||||
|
DIGITS: resd 4
|
||||||
|
HEX: resd 3
|
||||||
|
xitcode: resd 1
|
||||||
|
|
||||||
|
SECTION .text
|
||||||
|
_start:
|
||||||
|
mov dword [DIGITS], 0x33323130
|
||||||
|
mov dword [DIGITS+4], 0x37363534
|
||||||
|
mov dword [DIGITS+8], 0x62613938
|
||||||
|
mov dword [DIGITS+12], 0x66656463
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 0
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000001:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000001
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 1
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000002:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000002
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 1
|
||||||
|
neg eax
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000003:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000003
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 123
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000004:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000004
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 123
|
||||||
|
neg eax
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000005:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000005
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 4096
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000006:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000006
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov word [HEX], 0x7830
|
||||||
|
mov word [HEX+10], 0xa
|
||||||
|
mov eax, 4096
|
||||||
|
neg eax
|
||||||
|
lea esi, [DIGITS]
|
||||||
|
lea edi, [HEX+9]
|
||||||
|
mov ecx, 0x4
|
||||||
|
L000007:
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 15
|
||||||
|
movzx edx, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
movzx ebx, al
|
||||||
|
and bl, 240
|
||||||
|
shr bl, 4
|
||||||
|
mov dl, byte [esi+ebx]
|
||||||
|
mov byte [edi], dl
|
||||||
|
dec edi
|
||||||
|
shr eax, 8
|
||||||
|
loop L000007
|
||||||
|
mov eax, 0x4
|
||||||
|
mov ebx, 0x1
|
||||||
|
lea ecx, [HEX]
|
||||||
|
mov edx, 0xb
|
||||||
|
int 0x80
|
||||||
|
mov eax, 0
|
||||||
|
mov dword [xitcode], eax
|
||||||
|
|
||||||
|
;; The result in eax is the exit code, move it to ebx.
|
||||||
|
mov ebx, eax
|
||||||
|
mov eax, 1 ; _exit syscall
|
||||||
|
int 0x80 ; call Linux
|
||||||
8
test_print.code
Normal file
8
test_print.code
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
p 0
|
||||||
|
p 1
|
||||||
|
p -1
|
||||||
|
p 123
|
||||||
|
p -123
|
||||||
|
p 4096
|
||||||
|
p -4096
|
||||||
|
xitcode=0
|
||||||
Loading…
Reference in a new issue