Stack Machines
Total Page:16
File Type:pdf, Size:1020Kb
What is SaM? • SaM is a simple stack machine designed to introduce you to compilers in 3-4 lectures • SaM I: written by me around 2000 – modeled vaguely after JVM SaM I Am • SaM II: complete reimplementation and major extensions by Ivan Gyurdiev and David Levitan (Cornell undergrads) around 2003 • Course home-page has – SaM jar file – SaM instruction set manual – SaM source code SaM Screen-shot Stack machine • All data is stored in stack (or heap) – no data registers although there might be control registers • Stack also contains addresses • Stack pointer (SP) points to the first free location on stack • In SaM, stack addresses start at 0 and go up • Int/float values take one stack location . …. 102 SP 101 5 100 4 . …... …... 0 1 Program area in SaM Program area Stack machine HALT …….. SaM 2 ……. • Stack machine is sometimes called a 0- 1 PUSHIMM 8 address machine 0 PUSHIMM 7 PC – arithmetic operations take operands from top of • Program area: stack and push result(s) on stack – contains SaM code – one instruction per location • Program Counter (PC): …. – address of instruction to be executed ADD 102 102 SP SP – initialized to 0 when SaM is booted up 101 5 101 100 4 100 9 • HALT: …... …... – Initialized to false (0) when SaM is booted up – Set to true (1) by the STOP command – Program execution terminates when HALT is set to true (1) Program Execution Program area Loader HALT …….. SaM 2 ……. • How do commands get into the Program 1 PUSHIMM 8 area of SaM? 0 PUSHIMM 7 PC • Loader: a program that can open an input Command interpreter: file of SaM commands, and read them into PC = 0; the Program area. while (HALT == 0) //STOP command sets HALT to 1 Execute command Program[PC]; //ADD etc increment PC 2 Interpreter and Loader 0 1 2 …….. Labels HALT Program area …….. PUSHIMM 2 PUSHIMM 3 PUSHIMM ADD • SaM assembly instructions in program file Interpreter: PC PC = 0; can be given labels while (HALT == 0) foo: PUSHIMM 1 Execute command Program[PC]; ……. Loader (command-file): File Loc = 0; JUMP foo Open command-file for input; while (! EOF) { • SaM loader resolves labels and replaces Read a command from command-file; Store command in Program[Loc]; jump targets with addresses Loc++; 2 PUSHIMM 3 PUSHIMM ADD …….. } Other SaM areas Some SaM commands • FBR: Frame Base Register (see later) • Heap: for dynamic storage allocation (malloc and free) SaM uses a version of Doug Lea’s allocator 3 ALU commands Classification of SaM commands • ADD,SUB,… • Arithmetic/logic commands: • DUP: duplicate top of stack (TOS) • ISPOS: – ADD,SUB,.. – Pop stack; let popped value be Vt • Load/store commands: – If Vt is positive, push true (1);otherwise push false (0) – PUSHIMM,PUSHIND,STOREIND,… • ISNEG: same as above but tests for negative value • RegisterStack commands: on top of stack – PUSHFBR,POPFBR, LINK,PUSHSP,… • ISNIL: same as above but tests for zero value on top of stack • Control commands: • CMP: pop two values Vt and Vb from stack; – JUMP, JUMPC, JSR, JUMPIND,… – If (Vb < Vt) push 1 – If (Vb = Vt) push 0 – If (Vb > Vt) push -1 Example Pushing values on stack SaM code to compute (2 + 3) • PUSHIMM c PUSHIMM 2 – “push immediate”: value to be pushed is in the PUSHIMM 3 instruction itself ADD – will push c on the stack (eg) PUSHIMM 4 SaM code to compute (2 – 3) * (4 + 7) PUSHIMM -7 PUSHIMM 2 PUSHIMM 3 SUB PUSHIMM 4 Compare with postfix notion (reverse Polish) PUSHIMM 7 ADD TIMES 4 Load/store commands • PUSHOFF n: push value contained in location Stack[FBR+n] • SaM ALU commands operate with values on top • v = Stack[FBR + n] of stack. • Push v on Stack • What if values we want to compute with are somewhere inside the stack? -9 • Need to copy these values to top of stack, and SP SP 33 33 store them back inside stack when we are done. • Specifying address of location: two ways FBR FBR – address specified in command as some offset from FBR -9 PUSHOFF -1 -9 (offset mode) – address on top of stack (indirect mode) Stack[FBR –1] contains -9 • STOREOFF n: Pop TOS and write value • PUSHIND: into location Stack[FBR+n] – TOS has an address • TOS has a value v – Pop that address, read contents of that address • Pop it and write v into Stack[FBR + n]. and push contents on stack SP SP -9 333 52 SP SP . PUSHIND . STOREOFF 2 52 -9 52 -9 -9 333 FBR FBR TOS is 52 Contents of location 52 is -9 Store 333 into Stack[FBR+2] 5 •STOREIND: Using PUSHOFF/STOREOFF – TOS has a value v; below it is address s – Pop both and write v into Stack[s]. • Consider simple language SL – only one method called main – only assignment statements 333 main( ){ SP 52 SP . int x,y; We need to assign stack locations for “x” and “y” STOREIND x = 5; . and read/write from/to these locations to/from TOS 52 -9 52 333 y = (x + 6); return (x*y); } TOS is value 333. Value 333 is written Below it is address 52. into location 52 Contents of location 52 is -9 Stack frame SaM code (attempt 1) main: PUSHIMM 0 //allocate space for return value PUSHIMM 0//allocate space for x ADDSP 3 • Sequence of stack locations for PUSHIMM 0//allocate space for y holding local variables of //code for x = 5; procedure PUSHIMM 5 – “x” and “y” STOREOFF 1 • In addition, frame will have a location for return value y //code for y = (x+6); y • Code for procedure must leave x PUSHOFF 1 x PUSHIMM 6 return value in return value slot FBR return value FBR return value • Use offsets from FBR to ADD address “x” and “y” STOREOFF 2 • Where should FBR point to //compute (x*y) and store in rv – let’s make it point to “return PUSHOFF 1 value” slot frame for main PUSHOFF 2 frame for main – we’ll change this later TIMES STOREOFF 0 ADDSP -2 //pop x and y STOP 6 Problem with SaM code RegisterStack Commands • How do we know FBR is pointing to the base of the frame when we start execution? • Need commands to save FBR, set it to base • Commands for moving contents of SP, FBR of frame for execution, and restore FBR to stack, and vice versa. when method execution is done. • Used mainly in invoking/returning from • Where do we save FBR? methods – Save it in a special location in the frame • Convenient to custom-craft some commands to make method invocation/return easier to y implement. x FBR saved FBR return value main:PUSHIMM 0//space for rv LINK//save and update FBR ADDSP 2//space for x and y FBR Stack commands //code for x = 5; PUSHIMM 5 – PUSHFBR: push contents of FBR on stack STOREOFF 1 • Stack[SP] = FBR; //code for y = (x+6); y • SP++; PUSHOFF 1 x – POPFBR: inverse of PUSHFBR PUSHIMM 6 • SP--; ADD FBR saved FBR • FBR = Stack[SP]; STOREOFF 2 return value – LINK : convenient for method invocation //compute (x+y) and store in rv • Similar to PUSHFBR but also updates FBR so it points to PUSHOFF 1 location where FBR was saved PUSHOFF 2 TIMES frame for main • Stack[SP] = FBR; SP 89 SP • FBR = SP; 88 88 89 34 STOREOFF –1 • SP++; -1 87 -1 ADDSP –2//pop locals 34 88 POPFBR//restore FBR FBR FBR STOP 7 SP Stack commands Control Commands • So far, command execution is sequential – PUSHSP: push value of SP on stack – execute command in Program[0] • Stack[SP] = SP; – execute command in Program[1] • SP++ –….. – POPSP: inverse of POPSP • For implementing conditionals and loops, we need • SP--; the ability to • SP = Stack[SP]; – skip over some commands – ADDSP n: convenient for method invocation • SP = SP + n – execute some commands repeatedly • For example, ADDSP –5 will subtract 5 from SP. • In SaM, this is done using • ADDSP n can be implemented as follows: – JUMP: unconditional jump – PUSHSP – PUSHIMM n – JUMPC: conditional jump – ADD • JUMP/JUMPC: like GOTO in PASCAL – POPSP •JUMP t://t is an integer Example – Jump to command at Program[t] and execute commands from there on. SP – Implementation: PC t SP SP -5 SP 0 SP -1 SP •JUMPC t: -5 -5 -5 -5 -5 5 – same as JUMP except that JUMP is taken only if the topmost value on stack is true; otherwise, execution continues with command after this one. PC 0 PC 1 PC 2 PC 3 PC 4 PC 5 – note: in either case, stack is popped. – Implementation: Program to find absolute value of TOS: • pop top of stack (Vt); 0: DUP • if Vt is true, PC t else PC++ 1: ISPOS If jump is not taken, sequence of PC values 2: JUMPC 5 is 0,1,2,5 3: PUSHIMM –1 4: TIMES 5: STOP 8 Symbolic Labels • It is tedious to figure out the numbers of commands that are jump targets (such as STOP in example). Using JUMPC for conditionals • SaM loader allows you to specify jump targets using a symbolic label such as DONE in example above. • Translating if e then B1 else B2 • When loading program, SaM figures out the addresses of all jump targets and replaces symbolic names with those addresses. code for e JUMPC newLabel1 DUP DUP code for B2 ISPOS ISPOS JUMP newLabel2 JUMPC 5 JUMPC DONE newLabel1: code for B1 PUSHIMM –1 PUSHIMM –1 newLabel2: TIMES TIMES …… STOP DONE: STOP PC Stack Commands Example • Obvious solution: something like – PUSHPC: save PC on stack // not a SaM command • Stack[SP] = PC; • SP++; …….