The Assembly Code The compiler produces assembly code for a very simple computer. It has three registers: a stack pointer (SP) a frame pointer (FP) and a program counter (PC). The program counter contains the address of the next instruction to be executed. The stack grows from low addresses into high addresses as things are pushed. All calculations are done on the stack. Ints and floats occupy four bytes. All instructions have either one operand or none at all. In the following description: mem[n] represents the contents of the four bytes of memory starting at location n. Push(x) is an abbreviation for mem[SP]=x; SP=SP+1 x=Pop() is an abbreviation for SP=SP-1; x=mem[SP] opd represents any operand; operands may be: a number (fixed or floating point) a label, representing a memory address FP+n, representing the memory address n bytes above the Frame Pointer @opd, representing the address of operand opd. LOAD opd Push(mem[opd]) push memory content onto stack STOR opd mem[opd]=mem[SP-1] store value from top of stack in memory. not popped LOADN opd Push(opd) push (integer) constant onto stack LOADF opd Push(opd) push (floating point) constant onto stack POP Pop() remove something from the stack and ignore it STI b=Pop(); a=Pop(); mem[a]=b; Push(b) “Store indirect” LDI a=Pop(); b=mem[a]; Push(b) “Load indirect” DUP a=mem[SP-1]; Push(a) duplicate value on top of stack ADD b=Pop(); a=Pop(); Push(a+b) pop two ints, add them, push the result ADDF b=Pop(); a=Pop(); Push(a+b) same as above, but floating point, SUB b=Pop(); a=Pop(); Push(a-b) pop two ints, subtract them, push the result SUBF b=Pop(); a=Pop(); Push(a-b) same as above, but floating point, MUL b=Pop(); a=Pop(); Push(a*b) pop two ints, multiply them, push the result MULF b=Pop(); a=Pop(); Push(a*b) same as above, but floating point, DIV b=Pop(); a=Pop(); Push(a/b) pop two ints, divide them, push the result DIVF b=Pop(); a=Pop(); Push(a/b) same as above, but floating point, MOD b=Pop(); a=Pop(); Push(a%b) pop two ints, divide them, push the remainder FLOAT i=Pop(); f=(float)i; Push(f) pop a integer, convert to a float, and push it back FIX f=Pop(); i=(int)f; Push(i) pop a float, convert to an int, and push it back NOT a=Pop(); if (a==0) Push(1) otherwise Push(0) AND b=Pop(); a=Pop(); if a and b are both 1 Push(1) otherwise Push(0) OR b=Pop(); a=Pop(); if either a or b are 1 Push(1) otherwise Push(0) EQL b=Pop(); a=Pop(); if (a==b) Push(1) otherwise Push(0) EQLF same as above, but floating point NEQ b=Pop(); a=Pop(); if (a==b) Push(0) otherwise Push(1) NEQF same as above, but floating point LSS b=Pop(); a=Pop(); if (ab) Push(1) otherwise Push(0) GTRF same as above, but floating point LEQ b=Pop(); a=Pop(); if (a>b) Push(0) otherwise Push(1) LEQF same as above, but floating point GEQ b=Pop(); a=Pop(); if (a=0) { fac=fac*n; n=n-1; } calculating the factorial of n, looks like this: LOADN 1 STOR FAC L5: LOAD N -- label for going round again LOADN 0 GTR PJZ L6 -- pop the result of (n>=0) and jump if its zero LOAD FAC LOAD N MUL STOR FAC POP LOAD N LOADN 1 SUB STOR N POP JUMP L5 L6: -- all finished