TINY14ELF Development

We summarise below the stages of development of TINY14ELF from TINY14E and TINY11ELF.

  • TINY14E saved as TINY14ELF, then assignFile(AsmFile, 'temp.asm'); changed to assignFile(AsmFile, 'temp.s');.
  • Existing procedures with ARM assembler output (from procedure Clear to procedure Header) copied from TINY11E to the uCodeGen unit in TINY14ELF.
  • In function NewLabel in uOutput, NewLabel := '@L' + S; changed to NewLabel := 'L' + S;. (@ denotes an in-line comment).
  • In procedure DoMain of uParser, writeLn(AsmFile); inserted as the penultimate line of code. (This prevents an assembler warning about code being on the last line of the file).
  • Intel output code in uCodeGen in procedures such as WriteString and LoadParam converted to output ARM assembler.
  • TINY14ELF tested with short TINY programs such as those in the remaining sections of this page.

Please be aware of these restrictions:

  • TINY14ELF does not work for large source files. Error message: "invalid literal constant; pool needs to be closer". One solution is to emit .ltorg in appropriate places as shown in TINY14PI Development.
  • Writing of strings is problematic, possibly due to rudimentary I/O handling by the simulator. The workaround is to keep strings for output to about 10 characters and to use writeLn not write before a read. We can tolerate the inconvenience at this stage but will aim to improve matters when outputting ARM code for the Raspberry Pi.
  • All parameters are passed via the stack.
  • Global variables are saved in memory. We do not use the many available registers instead, which would have speeded up the processing.

Below we provide examples of programs written in TINY that we used to test TINY14ELF. You can use these programs to see acceptable syntax and the workaround for satisfactory output. Note that the programs are short, strings for output are very short, and writeLn (rather than write) precedes each read.

Boolean Expressions

program BoolDemo
var
  Num1, Num2, NotNum1Less1, Num1ANDNum2, Num1ORNum2
begin
  Num1 = 5
  Num2 = 12
  writeLn('Num1 = ', Num1)
  writeLn('Num2 = ', Num2)
  NotNum1Less1 = !Num1 - 1
  writeln('NotNum1Less1 = ', NotNum1Less1)
  Num1ANDNum2 = Num1 & Num2
  writeln('Num1ANDNum2 = ', Num1ANDNum2)
  Num1ORNum2 = Num1 | Num2
  writeln('Num1ORNum2 = ', Num1ORNum2)
  repeat
    writeLn('Num1:')
    read(Num1)
    writeLn('Num2:')
    read(Num2)
    NotNum1Less1 = !Num1 - 1
    writeln('NotNum1Less1 = ', NotNum1Less1)
    Num1ANDNum2 = Num1 & Num2
    writeln('Num1ANDNum2 = ', Num1ANDNum2)
    Num1ORNum2 = Num1 | Num2
    writeln('Num1ORNum2 = ', Num1ORNum2)
  until Num1 = 999
end

Arithmetic Progression

program ArithProgDemo
var
 FirstA, DiffA, TermsA

{ Outputs the last term and series of an arithmetic progression
 with first term F, difference D and number of terms T. }
procedure SeqA(F, D, T)
var
  Last, Series
begin
  Last = F + (T - 1) * D
  Series = T * (2 * F + (T - 1) * D) / 2
  writeln()
  writeLn('Last term: ', Last)
  writeLn('Sum (series): ', Series)
  writeln()
end

begin
  writeLn('First val:')
  read(FirstA)
  writeLn('Difference:')
  read(DiffA)
  writeLn('Terms:')
  read(TermsA)
  { Test multiple parameters. }
  SeqA(FirstA, DiffA, TermsA)
end

Geometric Sequence

program GeoSeqDemo
var
  Result

{ Stores Num to the power Exponent in Result }
procedure Power(Num, Exponent)
var
  Count
begin
  Result = 1
  for Count = 1 Exponent
    Result = Result * Num
  endFor
end

  { Outputs the last term and sum of a geometric sequence }
procedure SeqR()
var
  First, Ratio, Terms, Last, Sum, Exp
begin
  writeLn('First term:')
  read(First)
  writeLn('Ratio: ')
  read(Ratio)
  writeLn('Terms: ')
  read(Terms)
  Exp = Terms - 1
  Power(Ratio, Exp)
  Last = Result * First
  Sum = First * (Ratio * Result - 1) / (Ratio - 1)
  writeLn('Last term: ', Last)
  writeLn('Sum of ', Terms, ' Terms: ', Sum)
end

begin
  SeqR()
end

Pascal's Triangle 1

program PasTriDemo1
var
  Result, n, k, i, Coeff, nFact, kFact, subnkFact

{ Factorial by recursion, leaving the factorial in Result. }
procedure Fact(Num)
begin
  if Num = 0
    Result = 1
  else
    Fact(Num - 1)
    Result = Result * Num
  endIf
end

procedure PrintSpaces(n)
var
  i
begin
  for i = 1 n
    write(' ')
  endFor
end

begin
  writeLn()
  for n = 0 12
    PrintSpaces(30 - n * 2)
    for k = 0 n
      if (k = 0) | (k = n)
        Coeff = 1
      else
        Fact(n)
        nFact = Result
        Fact(k)
        kFact = Result
        Fact(n - k)
        subnkFact = Result
        Coeff = nFact/kFact / subnkFact
      endIf
      write(Coeff, ' ')
      if Coeff / 100 < 1
        write(' ')
      endIf
      if Coeff / 10 < 1
        write(' ')
      endIf
    endFor
    writeLn()
  endFor
  writeLn()
  writeLn()
end

Pascal's Triangle 2

program PasTriDemo2
var
  MAX, Result, n, k, i, Coeff, Divisor

{ Factorial by recursion, leaving the factorial in Result. }
procedure Fact(Num)
begin
  if Num = 0
    Result = 1
  else
    Fact(Num - 1)
    Result = Result * Num
  endIf
end

{ Recursive procedure for coefficient suggested by Rolfe }
procedure Coefficient(n, k)
begin
  Result = 1
  if (k = 0) | (k = n)
    Coeff = 1
  else
    Coefficient(n - 1, k - 1)
    Result = Result * n / k
  endIf
end

begin
  MAX = 22
  writeLn()
  for n = 0 MAX
    for k = 0 n
      if (k = 0) | (k = n)
        Coeff = 1
      else
        Coefficient(n, k)
        Coeff = Result
      endIf
      write(Coeff, ' ')
      Divisor = 100000
      while Divisor >= 10
        if Coeff / Divisor < 1
          write(' ')
        endIf
        Divisor = Divisor / 10
      endWhile
    endFor
    writeLn()
  endFor
  writeLn()
  writeLn()
end

Factorial

program FactDemo
var
  Result, Num

{ Factorial by recursion, leaving the factorial in Result. }
procedure Fact(Num)
begin
  if Num = 0
    Result = 1
  else
    Fact(Num - 1)
    Result = Result * Num
  endIf
end

begin
  repeat
    writeLn('Enter 0-12 ')
    readln(Num);
  until (Num >= 0) & (Num <= 12)
  Result = 1
  Fact(Num)
  writeLn(Num, '! = ', Result)
end

Primes

program PrimesDemo
var
  Result

{Stores the MOD in Result }
procedure Modulus(NumA, NumB)
var
  Quotient
begin
  Quotient = NumA / NumB
  Result = NumA - Quotient * NumB
end

{ Outputs primes less than 1000. }
procedure Primes()
var
  i, IsPrime, Divisor
begin
  writeLn('Primes')
  writeLn('2')
  i = 3
  while i < 1001
    IsPrime = T
    Divisor = 3
    while (IsPrime = T) & (Divisor < I/2) & (Divisor < 33)
      Modulus(I, Divisor)
      if Result = 0
        IsPrime = F
      endIf
      Divisor = Divisor + 2
    endWhile
    if IsPrime = T
      write(i, ' ')
    endIf
    I = I + 2
  endWhile
  writeLn()
end

begin
  Primes()
end
Programming - a skill for life!

by PPS in association with Jack Crenshaw