diff --git a/Project-01/uap25-pro01-tram/README.md b/Project-01/uap25-pro01-tram/README.md new file mode 100644 index 0000000..5504f1e --- /dev/null +++ b/Project-01/uap25-pro01-tram/README.md @@ -0,0 +1,15 @@ +**Author: Jan-Niclas Loosen (1540907)** + + +The jar ``jar/tram.jar`` contains all required dependencies. + +```bash +java -jar tram.jar [options] +``` +**Optional arguments:** + +`--debug`: Enables debug logging to the console. + +`--debug `: Enables debug logging and writes output to the specified file. + +`--stack [v1,v2,...]`: Initializes the stack with the given integers (for example `[4,10]`). diff --git a/Project-01/uap25-pro01-tram/build.sh b/Project-01/uap25-pro01-tram/build.sh new file mode 100644 index 0000000..ea10227 --- /dev/null +++ b/Project-01/uap25-pro01-tram/build.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -e + +OUT=jar +MAIN_CLASS=de.unitrier.st.uap.w25.tram.Main +JAR_NAME=tram.jar +LIB=lib +TMP=$OUT/tmp + +# Clean and prepare +rm -rf "$OUT" +mkdir -p "$TMP" + +# 1. Compile sources +if [ -d "$LIB" ]; then + javac -d "$TMP" -cp "$LIB/*" $(find src -name "*.java") +else + javac -d "$TMP" $(find src -name "*.java") +fi + +# 2. Unpack dependency jars +if [ -d "$LIB" ]; then + for jar in "$LIB"/*.jar; do + [ -f "$jar" ] && jar xf "$jar" -C "$TMP" + done +fi + +# 3. Create manifest +echo "Main-Class: $MAIN_CLASS" > "$TMP/MANIFEST.MF" + +# 4. Package into single jar +jar cfm "$OUT/$JAR_NAME" "$TMP/MANIFEST.MF" -C "$TMP" . + +# 5. Clean temporary files +rm -rf "$TMP" + +echo "Built: $OUT/$JAR_NAME" +echo "Run with:" +echo " java -jar $OUT/$JAR_NAME" diff --git a/Project-01/uap25-pro01-tram/jar/tram.jar b/Project-01/uap25-pro01-tram/jar/tram.jar new file mode 100644 index 0000000..ca34862 Binary files /dev/null and b/Project-01/uap25-pro01-tram/jar/tram.jar differ diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java index 17d136f..8fbb022 100644 --- a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachine.java @@ -26,7 +26,7 @@ public class AbstractMachine { // Executes until halts and returns final configuration public void execute() { - while(!isHalted()) { + while (!isHalted()) { executeStep(); } confStr(); @@ -34,152 +34,160 @@ public class AbstractMachine { // Executes single step and returns configuration public void executeStep() { - ensureCapacity(this.TOP); - Instruction inst = this.prog.get(this.PC); + try { + ensureCapacity(this.TOP); + Instruction inst = this.prog.get(this.PC); - int arg1 = inst.getArg1() != null ? inst.getArg1() : 0; - int arg2 = inst.getArg2() != null ? inst.getArg2() : 0; - int arg3 = inst.getArg3() != null ? inst.getArg3() : 0; + int arg1 = inst.getArg1() != null ? inst.getArg1() : 0; + int arg2 = inst.getArg2() != null ? inst.getArg2() : 0; + int arg3 = inst.getArg3() != null ? inst.getArg3() : 0; - switch (inst.getOpcode()) { - case Instruction.CONST: - // Pg. 9 - this.stack.set(this.TOP + 1, arg1); - this.TOP += 1; - this.PC += 1; - break; - case Instruction.LOAD: - // Pg. 25 - int loadSpp = spp(arg2, this.PP, this.FP); - this.stack.set(this.TOP + 1, this.stack.get(loadSpp + arg1)); - this.TOP += 1; - this.PC += 1; - break; - case Instruction.STORE: - // Pg. 25 - int storeSpp = spp(arg2, this.PP, this.FP); - this.stack.set(storeSpp + arg1, this.stack.get(this.TOP)); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.ADD: - // Pg. 9 - int addA = stack.get(this.TOP - 1); - int addB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, addA + addB); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.SUB: - // Pg. 9 - int subA = stack.get(this.TOP - 1); - int subB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, subA - subB); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.MUL: - // Pg. 9 - int mulA = stack.get(this.TOP - 1); - int mulB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, mulA * mulB); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.DIV: - // Pg. 9 - int divA = stack.get(this.TOP - 1); - int divB = stack.get(this.TOP); - - if (divB == 0) { - throw new ArithmeticException("Division by zero"); - } - - this.stack.set(this.TOP - 1, divA / divB); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.LT: - // Pg. 12 - int ltA = stack.get(this.TOP - 1); - int ltB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, ltA < ltB ? 1 : 0); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.GT: - // Pg. 12 - int gtA = stack.get(this.TOP - 1); - int gtB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, gtA > gtB ? 1 : 0); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.EQ: - // Pg. 12 - int eqA = stack.get(this.TOP - 1); - int eqB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, eqA == eqB ? 1 : 0); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.NEQ: - // Pg. 12 - int neqA = stack.get(this.TOP - 1); - int neqB = stack.get(this.TOP); - this.stack.set(this.TOP - 1, neqA != neqB ? 1 : 0); - this.TOP -= 1; - this.PC += 1; - break; - case Instruction.IFZERO: - // Pg. 13 - if (this.stack.get(this.TOP) == 0) { - this.PC = arg1; - } - else { + switch (inst.getOpcode()) { + case Instruction.CONST: + // Pg. 9 + this.stack.set(this.TOP + 1, arg1); + this.TOP += 1; this.PC += 1; - } - this.TOP -= 1; - break; - case Instruction.GOTO: - // Pg. 13 - this.PC = arg1; - break; - case Instruction.HALT: - // Pg. 13 - this.PC = -1; - break; - case Instruction.NOP: - // Pg. 13 - this.PC += 1; - break; - case Instruction.INVOKE: - // Pg. 23 - this.stack.set(this.TOP + 1, this.PC + 1); - this.stack.set(this.TOP + 2, this.PP); - this.stack.set(this.TOP + 3, this.FP); - this.stack.set(this.TOP + 4, spp(arg3, this.PP, this.FP)); - this.stack.set(this.TOP + 5, sfp(arg3, this.PP, this.FP)); - this.PP = this.TOP - arg1 + 1; - this.FP = this.TOP + 1; - this.TOP += 5; - this.PC = arg2; - break; - case Instruction.RETURN: - // Pg. 24 - int res = this.stack.get(this.TOP); - this.TOP = this.PP; - this.PC = this.stack.get(this.FP); - this.PP = this.stack.get(this.FP + 1); - this.FP = this.stack.get(this.FP + 2); - this.stack.set(this.TOP, res); - break; - case Instruction.POP: - // Not in docs, see MaMa - this.TOP -= 1; - this.PC += 1; - break; - default: break; + break; + case Instruction.LOAD: + // Pg. 25 + int loadSpp = spp(arg2, this.PP, this.FP); + this.stack.set(this.TOP + 1, this.stack.get(loadSpp + arg1)); + this.TOP += 1; + this.PC += 1; + break; + case Instruction.STORE: + // Pg. 25 + int storeSpp = spp(arg2, this.PP, this.FP); + this.stack.set(storeSpp + arg1, this.stack.get(this.TOP)); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.ADD: + // Pg. 9 + int addA = stack.get(this.TOP - 1); + int addB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, addA + addB); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.SUB: + // Pg. 9 + int subA = stack.get(this.TOP - 1); + int subB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, subA - subB); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.MUL: + // Pg. 9 + int mulA = stack.get(this.TOP - 1); + int mulB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, mulA * mulB); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.DIV: + // Pg. 9 + int divA = stack.get(this.TOP - 1); + int divB = stack.get(this.TOP); + + if (divB == 0) { + throw new ArithmeticException("Division by zero"); + } + + this.stack.set(this.TOP - 1, divA / divB); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.LT: + // Pg. 12 + int ltA = stack.get(this.TOP - 1); + int ltB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, ltA < ltB ? 1 : 0); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.GT: + // Pg. 12 + int gtA = stack.get(this.TOP - 1); + int gtB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, gtA > gtB ? 1 : 0); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.EQ: + // Pg. 12 + int eqA = stack.get(this.TOP - 1); + int eqB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, eqA == eqB ? 1 : 0); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.NEQ: + // Pg. 12 + int neqA = stack.get(this.TOP - 1); + int neqB = stack.get(this.TOP); + this.stack.set(this.TOP - 1, neqA != neqB ? 1 : 0); + this.TOP -= 1; + this.PC += 1; + break; + case Instruction.IFZERO: + // Pg. 13 + if (this.stack.get(this.TOP) == 0) { + this.PC = arg1; + } else { + this.PC += 1; + } + this.TOP -= 1; + break; + case Instruction.GOTO: + // Pg. 13 + this.PC = arg1; + break; + case Instruction.HALT: + // Pg. 13 + this.PC = -1; + break; + case Instruction.NOP: + // Pg. 13 + this.PC += 1; + break; + case Instruction.INVOKE: + // Pg. 23 + this.stack.set(this.TOP + 1, this.PC + 1); + this.stack.set(this.TOP + 2, this.PP); + this.stack.set(this.TOP + 3, this.FP); + this.stack.set(this.TOP + 4, spp(arg3, this.PP, this.FP)); + this.stack.set(this.TOP + 5, sfp(arg3, this.PP, this.FP)); + this.PP = this.TOP - arg1 + 1; + this.FP = this.TOP + 1; + this.TOP += 5; + this.PC = arg2; + break; + case Instruction.RETURN: + // Pg. 24 + int res = this.stack.get(this.TOP); + this.TOP = this.PP; + this.PC = this.stack.get(this.FP); + this.PP = this.stack.get(this.FP + 1); + this.FP = this.stack.get(this.FP + 2); + this.stack.set(this.TOP, res); + break; + case Instruction.POP: + // Not in docs, see MaMa + this.TOP -= 1; + this.PC += 1; + break; + default: + break; + } + } + catch(Exception e) { + String line = this.prog.get(this.PC).toString(); + String msg = e.getMessage(); + msg = String.format("Error at PC=%d (%s): %s%nCurrent stack=%s", this.PC, line, msg, stackStr()); + throw new RuntimeException(msg, e); } } @@ -207,14 +215,13 @@ public class AbstractMachine { protected void ensureCapacity(int currSize) { int size = stack.size(); - // Initialize stack with default capacity of 16 - if (size == 0) { - for (int i = 0; i < 16; i++) stack.add(0); - return; + // Always ensure a minimum working capacity of 16 + if (size < 16) { + for (int i = size; i < 16; i++) stack.add(0); + size = 16; } // Double list capacity when fewer than 8 free slots remain - // (largest instruction, INVOKE, needs 5 additional cells) if (currSize >= size - 8) { int newSize = size * 2; for (int i = size; i < newSize; i++) stack.add(0); diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java index 60f837b..8747397 100644 --- a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/AbstractMachineTests.java @@ -1,6 +1,9 @@ package de.unitrier.st.uap.w25.tram; import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.*; public class AbstractMachineTests { @@ -66,8 +69,98 @@ public class AbstractMachineTests { AbstractMachine tram = new AbstractMachine(code, new Integer[]{}); // empty stack tram.execute(); - assertTrue(tram.isHalted(), "Machine should halt after executing wrapper(4,10)."); + assertTrue(tram.isHalted(), "Machine should halt."); int result = tram.result(); assertEquals(4, result, "Expected result of wrapper(4,10) = 4."); } + + @Test + void testGGTx48y18() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{48, 18}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(6, result, "Expected ggt(48,18) = 6."); + } + + @Test + void testGGTx270y192() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{270, 192}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(6, result, "Expected ggt(270,192) = 6."); + } + + @Test + void testModPositive() { + Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{17, 5}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(2, result, "Expected 17 mod 5 = 2."); + } + + @Test + void testModExactDivision() { + Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{20, 5}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(0, result, "Expected 20 mod 5 = 0."); + } + + @Test + void testModSmallerDividend() { + Instruction[] code = Assembler.readTRAMCode("tramcode/mod.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{3, 10}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(3, result, "Expected 3 mod 10 = 3."); + } + + + @Test + void testGGTx17y5() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{17, 5}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(1, result, "Expected ggt(17,5) = 1."); + } + + @Test + void testGGTx25y0() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{25, 0}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(25, result, "Expected ggt(25,0) = 25."); + } + + @Test + void testGGTx0y25() { + Instruction[] code = Assembler.readTRAMCode("tramcode/ggt.tram"); + AbstractMachine tram = new AbstractMachine(code, new Integer[]{0, 25}); + tram.execute(); + + assertTrue(tram.isHalted(), "Machine should halt."); + int result = tram.result(); + assertEquals(25, result, "Expected ggt(0,25) = 25."); + } + } diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/LoggedMachine.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/LoggedMachine.java index 0b58c15..c6de517 100644 --- a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/LoggedMachine.java +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/LoggedMachine.java @@ -2,53 +2,19 @@ package de.unitrier.st.uap.w25.tram; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder; -import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory; -import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration; -import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder; -// Write subclass to enhance Single-Responsibility-Principle public class LoggedMachine extends AbstractMachine { - protected static Logger logger = LogManager.getLogger(LoggedMachine.class); - protected int stepCounter = 0; + private static final Logger logger = LogManager.getLogger(LoggedMachine.class); + private int stepCounter = 0; - // No changes in the constructor - public LoggedMachine(Instruction[] prog) { - super(prog); - } - - // No changes in the constructor - public LoggedMachine(Instruction[] prog, Integer[] stack) { - super(prog, stack); - } - - // Enable file logging - public static void toFile(String fileName) { - ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder(); - - AppenderComponentBuilder fileAppender = builder.newAppender("File", "File") - .addAttribute("fileName", fileName) - .add(builder.newLayout("PatternLayout") - .addAttribute("pattern", "%d{HH:mm:ss} %-5level %msg%n")); - - builder.add(fileAppender); - builder.add(builder.newRootLogger(Level.DEBUG).add(builder.newAppenderRef("File"))); - - LoggerContext ctx = LoggerContext.getContext(false); - ctx.start(builder.build()); - - logger = LogManager.getLogger(LoggedMachine.class); - } + public LoggedMachine(Instruction[] prog) { super(prog); } + public LoggedMachine(Instruction[] prog, Integer[] stack) { super(prog, stack); } @Override public void execute() { logger.info("Executing..."); - logger.debug("{}: {}", 0, confStr()); - while(!isHalted()) { - executeStep(); - } + logger.debug("0: {}", confStr()); + while (!isHalted()) executeStep(); logger.info("Finished with STACK: {}", stackStr()); } diff --git a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java index e1b7666..35a810c 100644 --- a/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java +++ b/Project-01/uap25-pro01-tram/src/de/unitrier/st/uap/w25/tram/Main.java @@ -2,8 +2,6 @@ package de.unitrier.st.uap.w25.tram; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; - -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -12,27 +10,21 @@ import java.util.List; public final class Main { private Main() {} - public static void main(String[] argv) { + static void main(String[] argv) { if (argv.length < 1) { System.err.println("Usage:"); - System.err.println(" java -jar tram.jar [--debug [logFile]] [--stack [v1,v2,...]]"); + System.err.println(" java -jar tram.jar [--debug] [--stack [v1,v2,...]]"); System.exit(1); } String tramPath = argv[0]; boolean debug = false; - String logFile = null; String stackArg = null; // Parse arguments for (int i = 1; i < argv.length; i++) { switch (argv[i]) { - case "--debug" -> { - debug = true; - if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) { - logFile = argv[++i]; - } - } + case "--debug" -> debug = true; case "--stack" -> { if (i + 1 < argv.length) { stackArg = argv[++i]; @@ -55,24 +47,9 @@ public final class Main { System.exit(4); } - // Configure logging + // Configure console logging only if (debug) { Configurator.setRootLevel(Level.DEBUG); - if (logFile != null) { - Path logPath = Path.of(logFile); - try { - Files.createDirectories(logPath.getParent() != null ? logPath.getParent() : Path.of(".")); - if (!Files.exists(logPath)) Files.createFile(logPath); - } catch (IOException e) { - System.err.println("Error: cannot create log file -> " + logPath); - e.printStackTrace(); - System.exit(5); - } - LoggedMachine.toFile(logPath.toString()); - System.out.println("Debug logging to file: " + logPath); - } else { - System.out.println("Debug logging to console."); - } } else { Configurator.setRootLevel(Level.INFO); } @@ -88,20 +65,13 @@ public final class Main { System.out.println("Execution complete."); } - /** - * Parses a stack argument given in Python list notation, e.g. "[1,2,3]" - */ + // Parse "[1,2,3]" or "1,2,3" private static Integer[] parseStack(String stackArg) { - if (stackArg == null || stackArg.isBlank()) { - return new Integer[] {}; - } + if (stackArg == null || stackArg.isBlank()) return new Integer[]{}; String trimmed = stackArg.trim(); - if (trimmed.startsWith("[") && trimmed.endsWith("]")) { + if (trimmed.startsWith("[") && trimmed.endsWith("]")) trimmed = trimmed.substring(1, trimmed.length() - 1); - } - if (trimmed.isBlank()) { - return new Integer[] {}; - } + if (trimmed.isBlank()) return new Integer[]{}; String[] parts = trimmed.split(","); List list = new ArrayList<>(); @@ -115,4 +85,4 @@ public final class Main { } return list.toArray(new Integer[0]); } -} +} \ No newline at end of file diff --git a/Project-01/uap25-pro01-tram/tramcode/ggt.tram b/Project-01/uap25-pro01-tram/tramcode/ggt.tram new file mode 100644 index 0000000..95e6d95 --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/ggt.tram @@ -0,0 +1,22 @@ +// Quellkode: ggt(a,b) { if (b==0) then a else ggt(b, a mod b) } +// Annahmen: Die Argumente a und b werden durch Kellerzellen 0 und 1 repräsentiert, +// sowie PP=0, FP=0 und TOP=-1 +INVOKE 2 LGGT 0 +POP +HALT + +LGGT: +// b +LOAD 1 0 +// if b != 0 -> 1 +IFZERO 1 +// return a +LOAD 0 0 +RETURN +L1: +LOAD 1 0 // b +LOAD 0 0 +LOAD 1 0 +MOD // a mod b +INVOKE 2 LGGT 0 // ggt(b, a mod b) +RETURN diff --git a/Project-01/uap25-pro01-tram/tramcode/mod.tram b/Project-01/uap25-pro01-tram/tramcode/mod.tram new file mode 100644 index 0000000..1dbf814 --- /dev/null +++ b/Project-01/uap25-pro01-tram/tramcode/mod.tram @@ -0,0 +1,12 @@ +# Quellkode: let mod(a,b) { a - (a / b) * b } in mod(14,5) +# Annahmen: a→stack[0], b→stack[1], PP=0, FP=0, TOP=-1 +INVOKE 2 MOD 0 +HALT + +MOD: LOAD 1 0 +LOAD 1 0 +DIV +LOAD 2 0 +MUL +SUB +RETURN