Compare commits

...

2 Commits

Author SHA1 Message Date
nils polek
ac57431ac4 added big int lib 2024-01-15 16:28:41 +00:00
nils polek
3935d2778b alle rechenobjekte im stack sind jetzt pointer 2024-01-15 15:32:02 +00:00
23 changed files with 2671 additions and 75 deletions

View File

@ -7,10 +7,10 @@ CC = gcc
F = prog.bin
# Compiler flags
CFLAGS = -g -Wall -std=c99 -pedantic
CFLAGS = -I ./bigint/build/include -L ./bigint/build/lib -g -Wall -std=c99 -pedantic
# Source file
SRC = njvm.c
SRC = njvm.c
# Executable name
TARGET = njvm

22
bigint/Makefile Normal file
View File

@ -0,0 +1,22 @@
#
# Makefile for big integer library and test
#
DIRS = src tst
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -rf ./build
rm -f *~
dist: clean
(cd .. ; \
tar -cvf bigint.tar bigint ; \
gzip -f bigint.tar)

92
bigint/README Normal file
View File

@ -0,0 +1,92 @@
The "bigint" Package
====================
1. What is it?
--------------
This package implements a multiple-precision integer arithmetic package,
i.e., a collection of functions which can calculate with integers having
arbitrarily many digits. The algorithms are taken from [D. Knuth: The
Art of Computer Programming, Vol. 2, Seminumerical Algorithms], the
implementation language is C.
2. "Multiple Precision" - how does it work?
-------------------------------------------
Each integer number is represented as an array of digits. The array
is large enough to hold the number of digits necessary to represent
the number. Each digit occupies a single byte, so the number base of
this representation is 256. Addition, subtraction, and multiplication
work as we all have learned it: perform the desired operation digit
by digit, starting from the least significant digit, and observing
any "carries" from one place to the next higher one. Division is a
little bit more complicated because there is a certain amount of
guesswork involved. Knuth gives a formal treatment of this guesswork.
3. How do I use it?
-------------------
Because every big integer may have a differently sized array to hold
its digits, these structures are dynamically allocated on the heap of
the C runtime system, and accessed by pointers. If you want to perform
an arithmetic operation on one or two big integers, you have to load
the corresponding pointers into a structure called BIP ("Big Integer
Processor"), and call the arithmetic function. When the function has
returned, the pointer to the result of the operation can be found in
another component of the BIP. The following functions are available:
int bigSgn(void); /* sign */
int bigCmp(void); /* comparison */
void bigNeg(void); /* negation */
void bigAdd(void); /* addition */
void bigSub(void); /* subtraction */
void bigMul(void); /* multiplication */
void bigDiv(void); /* division */
void bigFromInt(int n); /* conversion int --> big */
int bigToInt(void); /* conversion big --> int */
void bigRead(FILE *in); /* read a big integer */
void bigPrint(FILE *out); /* print a big integer */
void bigDump(FILE *out, BigObjRef bigObjRef); /* dump a big integer */
Some of these functions accept or return ordinary integers. For the
exact definition of each function's interface, please see the comments
in the function's source.
4. What else is needed?
-----------------------
The library tries to detect fatal errors in using its functions (e.g.,
null pointers to operands) as well as internal errors (which "cannot
happen"). In either case a user-supplied error routine is called, which
is supposed to print an error message and then to terminate the program.
The library does not attempt to manage memory. For this purpose, it
relies on a user-supplied function "void* newPrimObject(int dataSize)",
which should allocate sufficiently many bytes and return a pointer to
a created object. In addition, the library needs to access a data field
- that implements the size-as-needed cocept - within the created object,
to actualy manage the data structures that represent the values of the
integer number. For this, the following function can be used:
void * getPrimObjectDataPointer(void * obj){
ObjRef oo = ((ObjRef) (obj));
return oo->data;
}
This function must also be a user-supplied function that must be
implemented by the program that wants to use this library.
For details about these three user-supplied functions take a look in
the file "support.c" in the directory "tst".
5. What is in the directory "tst"?
----------------------------------
Well, you may have guessed it already: these are test cases for the
library. You can learn how to link against the library by inspecting
the "Makefile" for the tests, and you can find a simple implementation
of the support library.

BIN
bigint/build/bin/testbip Executable file

Binary file not shown.

View File

@ -0,0 +1,60 @@
/*
* bigint.h -- big integer library
*/
#ifndef _BIGINT_H_
#define _BIGINT_H_
/* object representation */
typedef void* BigObjRef;
#include <stdio.h>
typedef struct {
int nd; /* number of digits; array may be bigger */
/* nd = 0 exactly when number = 0 */
unsigned char sign; /* one of BIG_NEGATIVE or BIG_POSITIVE */
/* zero always has BIG_POSITIVE here */
unsigned char digits[1]; /* the digits proper; number base is 256 */
/* LS digit first; MS digit is not zero */
} Big;
#include "support.h"
/* big integer processor registers */
typedef struct {
BigObjRef op1; /* first (or single) operand */
BigObjRef op2; /* second operand (if present) */
BigObjRef res; /* result of operation */
BigObjRef rem; /* remainder in case of division */
} BIP;
extern BIP bip; /* registers of the processor */
/* big integer processor functions */
int bigSgn(void); /* sign */
int bigCmp(void); /* comparison */
void bigNeg(void); /* negation */
void bigAdd(void); /* addition */
void bigSub(void); /* subtraction */
void bigMul(void); /* multiplication */
void bigDiv(void); /* division */
void bigFromInt(int n); /* conversion int --> big */
int bigToInt(void); /* conversion big --> int */
void bigRead(FILE *in); /* read a big integer */
void bigPrint(FILE *out); /* print a big integer */
void bigDump(FILE *out, BigObjRef bigObjRef); /* dump a big integer object */
#endif /* _BIGINT_H_ */

View File

@ -0,0 +1,15 @@
/*
* support.h -- object representation and support functions
*/
#ifndef _SUPPORT_H_
#define _SUPPORT_H_
/* support functions */
void fatalError(char *msg); /* print a message and exit */
void * newPrimObject(int dataSize); /* create a new primitive object */
void * getPrimObjectDataPointer(void * primObject);
#endif /* _SUPPORT_H_ */

Binary file not shown.

26
bigint/src/Makefile Normal file
View File

@ -0,0 +1,26 @@
#
# Makefile for big integer library
#
BUILD = ../build
CC = gcc
CFLAGS = -g -Wall
all: support.h bigint.h libbigint.a
install: all
mkdir -p $(BUILD)/include
cp support.h $(BUILD)/include
cp bigint.h $(BUILD)/include
mkdir -p $(BUILD)/lib
cp libbigint.a $(BUILD)/lib
libbigint.a: bigint.o
ar -crs libbigint.a bigint.o
bigint.o: bigint.c bigint.h support.h
$(CC) $(CFLAGS) -o bigint.o -c bigint.c
clean:
rm -f *~ bigint.o libbigint.a

987
bigint/src/bigint.c Normal file
View File

@ -0,0 +1,987 @@
/*
* bigint.c -- big integer library
*/
#include <stdio.h>
#include <ctype.h>
#include "bigint.h"
/**************************************************************/
/* debugging */
#define DIV_CHK_01 0
#define DIV_CHK_02 0
#define DIV_CHK_03 0
#define DIV_CHK_04 0
#define DIV_CHK_05 0
#define DIV_CHK_06 0
#define DIV_CHK_07 0
#define DIV_CHK_08 0
#define DIV_CHK_09 0
#define DIV_CHK_10 0
#define DIV_CHK_11 0
/**************************************************************/
/* big integer representation */
#define BIG_NEGATIVE ((unsigned char) 0)
#define BIG_POSITIVE ((unsigned char) 1)
#define BIG_PTR(bigObjRef) ((Big *) (getPrimObjectDataPointer(bigObjRef)))
#define GET_ND(bigObjRef) (BIG_PTR(bigObjRef)->nd)
#define SET_ND(bigObjRef, val) (BIG_PTR(bigObjRef)->nd = (val))
#define GET_SIGN(bigObjRef) (BIG_PTR(bigObjRef)->sign)
#define SET_SIGN(bigObjRef, val) (BIG_PTR(bigObjRef)->sign = (val))
#define GET_DIGIT(bigObjRef, i) (BIG_PTR(bigObjRef)->digits[i])
#define SET_DIGIT(bigObjRef, i, val) (BIG_PTR(bigObjRef)->digits[i] = (val))
/**************************************************************/
/* global data */
/*
* registers of the big integer processor
*/
BIP bip = {
NULL, /* op1 */
NULL, /* op2 */
NULL, /* res */
NULL, /* rem */
};
/**************************************************************/
/*
* construct a new big integer object
*
* number of digits is given by parameter
* a reference to a proper object is returned
* but no component of the big integer is set
*
* ATTENTION: All object references stored in
* places other than the bip registers may become
* invalid as soon as this function is called!
*/
static BigObjRef newBig(int nd) {
int dataSize;
BigObjRef bigObjRef;
dataSize = sizeof(int) + 1 + nd;
bigObjRef = newPrimObject(dataSize);
return bigObjRef;
}
/**************************************************************/
/* big integer unsigned arithmetic */
/*
* exchange bip.op1 and bip.op2
*/
static void bigXchg(void) {
BigObjRef tmp;
tmp = bip.op1;
bip.op1 = bip.op2;
bip.op2 = tmp;
}
/*
* big integer unsigned comparison
*
* operands in bip.op1 and bip.op2
* result is < 0, = 0, or > 0 if and only if the
* same relation holds for bip.op1 and bip.op2
*/
static int bigUcmp(void) {
int nd1;
int nd2;
int diff;
/* compare sizes */
nd1 = GET_ND(bip.op1);
nd2 = GET_ND(bip.op2);
if (nd1 != nd2) {
/* sizes are different: we know the bigger number */
return nd1 - nd2;
}
/* sizes are equal: we must look at the digits */
while (nd1--) {
diff = (int) GET_DIGIT(bip.op1, nd1) -
(int) GET_DIGIT(bip.op2, nd1);
if (diff != 0) {
return diff;
}
}
/* the numbers are equal */
return 0;
}
/*
* big integer unsigned addition
*
* operands in bip.op1 and bip.op2
* result in bip.res
*/
static void bigUadd(void) {
int nd1;
int nd2;
int i;
unsigned short carry;
unsigned short aux;
int xchgFlag;
/* make sure op1 has at least as many digits as op2 */
nd1 = GET_ND(bip.op1);
nd2 = GET_ND(bip.op2);
if (nd1 < nd2) {
/* exchange operands */
bigXchg();
i = nd1;
nd1 = nd2;
nd2 = i;
xchgFlag = 1;
} else {
/* don't exchange operands */
xchgFlag = 0;
}
/* allocate result */
bip.res = newBig(nd1 + 1);
/* copy op2 to result */
for (i = 0; i < nd2; i++) {
SET_DIGIT(bip.res, i, GET_DIGIT(bip.op2, i));
}
/* fill result with 0 up to size of op1 */
for (; i < nd1; i++) {
SET_DIGIT(bip.res, i, 0);
}
/* res = op1 + res */
carry = 0x00;
for (i = 0; i < nd1; i++) {
aux = (unsigned short) GET_DIGIT(bip.op1, i) +
(unsigned short) GET_DIGIT(bip.res, i) +
carry;
SET_DIGIT(bip.res, i, aux & 0xFF);
carry = aux >> 8;
}
SET_DIGIT(bip.res, i, carry);
/* determine actual size of result */
i = nd1 + 1;
while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ;
SET_ND(bip.res, i + 1);
/* restore operands */
if (xchgFlag) {
bigXchg();
}
}
/*
* big integer unsigned subtraction
*
* operands in bip.op1 and bip.op2
* result in bip.res, must not be negative
*/
static void bigUsub(void) {
int nd1;
int nd2;
int i;
unsigned short carry;
unsigned short aux;
/* op1 must have at least as many digits as op2 */
nd1 = GET_ND(bip.op1);
nd2 = GET_ND(bip.op2);
if (nd1 < nd2) {
/* unsigned subtraction would yield negative result */
fatalError("internal library error #1 - THIS SHOULD NEVER HAPPEN!");
}
/* allocate result */
bip.res = newBig(nd1);
/* copy op2 to result */
for (i = 0; i < nd2; i++) {
SET_DIGIT(bip.res, i, GET_DIGIT(bip.op2, i));
}
/* fill result with 0 up to size of op1 */
for (; i < nd1; i++) {
SET_DIGIT(bip.res, i, 0);
}
/* res = op1 - res */
carry = 0x01;
for (i = 0; i < nd1; i++) {
aux = (unsigned short) GET_DIGIT(bip.op1, i) -
(unsigned short) GET_DIGIT(bip.res, i) +
carry + 0xFF;
SET_DIGIT(bip.res, i, aux & 0xFF);
carry = aux >> 8;
}
if (carry != 0x01) {
/* unsigned subtraction would yield negative result */
fatalError("internal library error #2 - THIS SHOULD NEVER HAPPEN!");
}
/* determine actual size of result */
i = nd1;
while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ;
SET_ND(bip.res, i + 1);
}
/*
* big integer unsigned multiplication
*
* operands in bip.op1 and bip.op2
* result in bip.res
*/
static void bigUmul(void) {
int nd1;
int nd2;
int i, j, k;
unsigned short carry;
unsigned short aux;
/* get sizes of operands */
nd1 = GET_ND(bip.op1);
nd2 = GET_ND(bip.op2);
/* allocate result */
bip.res = newBig(nd1 + nd2);
/* reset lower nd1 digits of result */
for (i = 0; i < nd1; i++) {
SET_DIGIT(bip.res, i, 0);
}
/* res = op1 * op2 */
for (j = 0; j < nd2; j++) {
carry = 0x00;
for (k = j, i = 0; i < nd1; k++, i++) {
aux = (unsigned short) GET_DIGIT(bip.op1, i) *
(unsigned short) GET_DIGIT(bip.op2, j) +
(unsigned short) GET_DIGIT(bip.res, k) +
carry;
SET_DIGIT(bip.res, k, aux & 0xFF);
carry = aux >> 8;
}
SET_DIGIT(bip.res, k, carry);
}
/* determine actual size of result */
i = nd1 + nd2;
while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ;
SET_ND(bip.res, i + 1);
}
/*
* big integer unsigned division by single digit divisor
*
* dividend in bip.rem, divisor in parameter
* quotient in bip.rem, remainder is returned
*/
static unsigned char bigUdiv1(unsigned char divisor) {
BigObjRef tmp;
int nd;
int i;
unsigned short d, r;
unsigned short aux;
/* get size of dividend */
nd = GET_ND(bip.rem);
/* check for division by zero */
d = (unsigned short) divisor;
if (d == 0) {
fatalError("internal library error #3 - THIS SHOULD NEVER HAPPEN!");
}
/* allocate result */
tmp = newBig(nd);
/* tmp = dividend / divisor, r = dividend % divisor */
r = 0;
for (i = nd - 1; i >= 0; i--) {
aux = (r << 8) | (unsigned short) GET_DIGIT(bip.rem, i);
SET_DIGIT(tmp, i, aux / d);
r = aux % d;
}
/* determine actual size of quotient */
i = nd;
while (--i >= 0 && GET_DIGIT(tmp, i) == 0) ;
SET_ND(tmp, i + 1);
/* store quotient */
bip.rem = tmp;
/* return remainder */
return (unsigned char) r;
}
/*
* big integer unsigned division
*
* dividend in bip.op1, divisor in bip.op2
* quotient in bip.res, remainder in bip.rem
*/
static void bigUdiv(void) {
BigObjRef tmp;
int nd1;
int nd2;
int nd3;
int i, j, k, l;
unsigned char r;
unsigned short scale;
unsigned short carry;
unsigned short aux;
unsigned short qhat;
unsigned short v1, v2;
unsigned short uj0, uj1, uj2, two;
/* get sizes of operands */
nd1 = GET_ND(bip.op1);
nd2 = GET_ND(bip.op2);
/* check for division by zero */
if (nd2 == 0) {
fatalError("division by zero");
}
/* check for small dividend */
if (bigUcmp() < 0) {
/* res = 0 */
bip.res = newBig(0);
SET_ND(bip.res, 0);
/* rem = op1; BUT THIS HAS TO BE A COPY! */
bip.rem = newBig(nd1);
for (i = 0; i < nd1; i++) {
SET_DIGIT(bip.rem, i, GET_DIGIT(bip.op1, i));
}
SET_ND(bip.rem, nd1);
return;
}
/* check for single digit divisor */
if (nd2 == 1) {
/* yes - use simple division by single digit divisor */
bip.rem = bip.op1;
r = bigUdiv1(GET_DIGIT(bip.op2, 0));
bip.res = bip.rem;
if (r == 0) {
bip.rem = newBig(0);
SET_ND(bip.rem, 0);
} else {
bip.rem = newBig(1);
SET_ND(bip.rem, 1);
SET_DIGIT(bip.rem, 0, r);
}
return;
}
/*
* now for the general case
*/
#if DIV_CHK_01
printf("div_chk #01: division, general case\n");
printf(" dividend = ");
bigDump(stdout, bip.op1);
printf("\n");
printf(" divisor = ");
bigDump(stdout, bip.op2);
printf("\n");
#endif
/* determine scale factor for normalization */
scale = (unsigned short) 256 /
((unsigned short) GET_DIGIT(bip.op2, nd2 - 1) + 1);
#if DIV_CHK_02
printf("div_chk #02: scale factor = %02X\n", scale);
#endif
/* normalize dividend, result is in bip.rem */
bip.rem = newBig(nd1 + 1);
carry = 0x00;
for (i = 0; i < nd1; i++) {
aux = (unsigned short) GET_DIGIT(bip.op1, i) * scale +
carry;
SET_DIGIT(bip.rem, i, aux & 0xFF);
carry = aux >> 8;
}
SET_DIGIT(bip.rem, i, carry);
SET_ND(bip.rem, nd1 + 1);
#if DIV_CHK_03
printf("div_chk #03: normalized dividend = ");
bigDump(stdout, bip.rem);
printf("\n");
#endif
/* normalize divisor, result is in bip.res */
bip.res = newBig(nd2);
carry = 0x00;
for (i = 0; i < nd2; i++) {
aux = (unsigned short) GET_DIGIT(bip.op2, i) * scale +
carry;
SET_DIGIT(bip.res, i, aux & 0xFF);
carry = aux >> 8;
}
if (carry != 0x00) {
/* overflow in divisor normalization */
fatalError("internal library error #4 - THIS SHOULD NEVER HAPPEN!");
}
SET_ND(bip.res, nd2);
#if DIV_CHK_04
printf("div_chk #04: normalized divisor = ");
bigDump(stdout, bip.res);
printf("\n");
#endif
/* allocate quotient */
nd3 = nd1 - nd2 + 1;
tmp = newBig(nd3);
/* extract the two most significand digits of divisor */
v1 = (unsigned short) GET_DIGIT(bip.res, nd2 - 1);
v2 = (unsigned short) GET_DIGIT(bip.res, nd2 - 2);
/* loop on digits of dividend and compute digits of quotient */
/* j is index into dividend, k is index into quotient */
for (j = nd1, k = nd3 - 1; k >= 0; j--, k--) {
#if DIV_CHK_05
printf("div_chk #05: j = %d, k = %d\n", j, k);
#endif
/* calculate qhat */
uj0 = (unsigned short) GET_DIGIT(bip.rem, j);
uj1 = (unsigned short) GET_DIGIT(bip.rem, j - 1);
uj2 = (unsigned short) GET_DIGIT(bip.rem, j - 2);
two = (uj0 << 8) | uj1;
if (uj0 == v1) {
qhat = (unsigned short) 255;
#if DIV_CHK_06
printf("div_chk #06a: qhat = %02X\n", qhat);
#endif
} else {
qhat = two / v1;
#if DIV_CHK_06
printf("div_chk #06b: qhat = %02X\n", qhat);
#endif
}
while (qhat * v2 > (((two - qhat * v1) << 8) | uj2)) {
qhat--;
#if DIV_CHK_07
printf("div_chk #07: qhat decremented, is now %02X\n", qhat);
#endif
}
/* multiply and subtract */
/* l is index into dividend, i is index into divisor */
carry = 0xFF;
for (l = j - nd2, i = 0; i < nd2; l++, i++) {
aux = (unsigned short) GET_DIGIT(bip.rem, l) -
(unsigned short) GET_DIGIT(bip.res, i) * qhat +
carry + 0xFE01;
SET_DIGIT(bip.rem, l, aux & 0xFF);
carry = aux >> 8;
}
aux = (unsigned short) GET_DIGIT(bip.rem, l) +
carry + 0xFE01;
SET_DIGIT(bip.rem, l, aux & 0xFF);
carry = aux >> 8;
#if DIV_CHK_08
printf("div_chk #08: remainder = ");
bigDump(stdout, bip.rem);
printf("\n");
#endif
/* test remainder and possibly add back */
if (carry != 0xFF) {
/* qhat is one too large */
qhat--;
#if DIV_CHK_09
printf("div_chk #09: qhat final correction, is now %02X\n", qhat);
#endif
/* add back */
/* l is index into dividend, i is index into divisor */
carry = 0x00;
for (l = j - nd2, i = 0; i < nd2; l++, i++) {
aux = (unsigned short) GET_DIGIT(bip.rem, l) +
(unsigned short) GET_DIGIT(bip.res, i) +
carry;
SET_DIGIT(bip.rem, l, aux & 0xFF);
carry = aux >> 8;
}
aux = (unsigned short) GET_DIGIT(bip.rem, l) +
carry;
SET_DIGIT(bip.rem, l, aux & 0xFF);
carry = aux >> 8;
if (carry != 0x01) {
/* missing carry in add-back sum */
fatalError("internal library error #5 - THIS SHOULD NEVER HAPPEN!");
}
#if DIV_CHK_10
printf("div_chk #10: remainder = ");
bigDump(stdout, bip.rem);
printf("\n");
#endif
}
/* store quotient digit */
SET_DIGIT(tmp, k, qhat);
#if DIV_CHK_11
printf("div_chk #11: quotient digit = %02X\n", qhat);
#endif
}
/* finish quotient */
i = nd3;
while (--i >= 0 && GET_DIGIT(tmp, i) == 0) ;
SET_ND(tmp, i + 1);
bip.res = tmp;
/* finish and unnormalize remainder */
i = nd1 + 1;
while (--i >= 0 && GET_DIGIT(bip.rem, i) == 0) ;
SET_ND(bip.rem, i + 1);
r = bigUdiv1(scale);
if (r != 0) {
/* non-zero remainder in unnormalization */
fatalError("internal library error #6 - THIS SHOULD NEVER HAPPEN!");
}
}
/**************************************************************/
/* nil reference exception */
static void nilRefException(void) {
fatalError("big integer library detected illegal nil reference");
}
/**************************************************************/
/* big integer arithmetic */
/*
* big integer sign
*
* operand in bip.op1
* result is < 0, = 0, or > 0 if and only if
* the same relation holds for bip.op1
*/
int bigSgn(void) {
if (bip.op1 == NULL) {
nilRefException();
}
if (GET_ND(bip.op1) == 0) {
return 0;
}
if (GET_SIGN(bip.op1) == BIG_POSITIVE) {
return 1;
} else {
return -1;
}
}
/*
* big integer comparison
*
* operands in bip.op1 and bip.op2
* result is < 0, = 0, or > 0 if and only if the
* same relation holds for bip.op1 and bip.op2
*/
int bigCmp(void) {
if (bip.op1 == NULL ||
bip.op2 == NULL) {
nilRefException();
}
if (GET_SIGN(bip.op1) == BIG_POSITIVE) {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 >= 0 and op2 >= 0 */
return bigUcmp();
} else {
/* op1 >= 0 and op2 < 0 */
return 1;
}
} else {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 < 0 and op2 >= 0 */
return -1;
} else {
/* op1 < 0 and op2 < 0 */
return -bigUcmp();
}
}
}
/*
* big integer negation
*
* operand in bip.op1
* result in bip.res
*/
void bigNeg(void) {
int nd;
int i;
if (bip.op1 == NULL) {
nilRefException();
}
/* make copy of operand */
nd = GET_ND(bip.op1);
bip.res = newBig(nd);
for (i = 0; i < nd; i++) {
SET_DIGIT(bip.res, i, GET_DIGIT(bip.op1, i));
}
SET_ND(bip.res, nd);
/* store inverted sign */
if (GET_SIGN(bip.op1) == BIG_NEGATIVE || nd == 0) {
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
SET_SIGN(bip.res, BIG_NEGATIVE);
}
}
/*
* big integer addition
*
* operands in bip.op1 and bip.op2
* result in bip.res
*/
void bigAdd(void) {
if (bip.op1 == NULL ||
bip.op2 == NULL) {
nilRefException();
}
if (GET_SIGN(bip.op1) == BIG_POSITIVE) {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 >= 0 and op2 >= 0 */
bigUadd();
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
/* op1 >= 0 and op2 < 0 */
if (bigUcmp() >= 0) {
/* |op1| >= |op2| */
bigUsub();
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
/* |op1| < |op2| */
bigXchg();
bigUsub();
SET_SIGN(bip.res, BIG_NEGATIVE);
bigXchg();
}
}
} else {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 < 0 and op2 >= 0 */
if (bigUcmp() <= 0) {
/* |op1| <= |op2| */
bigXchg();
bigUsub();
SET_SIGN(bip.res, BIG_POSITIVE);
bigXchg();
} else {
/* |op1| > |op2| */
bigUsub();
SET_SIGN(bip.res, BIG_NEGATIVE);
}
} else {
/* op1 < 0 and op2 < 0 */
bigUadd();
SET_SIGN(bip.res, BIG_NEGATIVE);
}
}
}
/*
* big integer subtraction
*
* operands in bip.op1 and bip.op2
* result in bip.res
*/
void bigSub(void) {
if (bip.op1 == NULL ||
bip.op2 == NULL) {
nilRefException();
}
if (GET_SIGN(bip.op1) == BIG_POSITIVE) {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 >= 0 and op2 >= 0 */
if (bigUcmp() >= 0) {
/* |op1| >= |op2| */
bigUsub();
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
/* |op1| < |op2| */
bigXchg();
bigUsub();
SET_SIGN(bip.res, BIG_NEGATIVE);
bigXchg();
}
} else {
/* op1 >= 0 and op2 < 0 */
bigUadd();
SET_SIGN(bip.res, BIG_POSITIVE);
}
} else {
if (GET_SIGN(bip.op2) == BIG_POSITIVE) {
/* op1 < 0 and op2 >= 0 */
bigUadd();
SET_SIGN(bip.res, BIG_NEGATIVE);
} else {
/* op1 < 0 and op2 < 0 */
if (bigUcmp() <= 0) {
/* |op1| <= |op2| */
bigXchg();
bigUsub();
SET_SIGN(bip.res, BIG_POSITIVE);
bigXchg();
} else {
/* |op1| > |op2| */
bigUsub();
SET_SIGN(bip.res, BIG_NEGATIVE);
}
}
}
}
/*
* big integer multiplication
*
* operands in bip.op1 and bip.op2
* result in bip.res
*/
void bigMul(void) {
if (bip.op1 == NULL ||
bip.op2 == NULL) {
nilRefException();
}
bigUmul();
if (GET_SIGN(bip.op1) == GET_SIGN(bip.op2) || GET_ND(bip.res) == 0) {
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
SET_SIGN(bip.res, BIG_NEGATIVE);
}
}
/*
* big integer division, truncating towards zero
*
* dividend in bip.op1, divisor in bip.op2
* quotient in bip.res, remainder in bip.rem
*/
void bigDiv(void) {
if (bip.op1 == NULL ||
bip.op2 == NULL) {
nilRefException();
}
bigUdiv();
if (GET_SIGN(bip.op1) == GET_SIGN(bip.op2) || GET_ND(bip.res) == 0) {
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
SET_SIGN(bip.res, BIG_NEGATIVE);
}
if (GET_SIGN(bip.op1) == BIG_POSITIVE || GET_ND(bip.rem) == 0) {
SET_SIGN(bip.rem, BIG_POSITIVE);
} else {
SET_SIGN(bip.rem, BIG_NEGATIVE);
}
}
/**************************************************************/
/* big integer conversions */
/*
* conversion int --> big
*
* operand in parameter
* result in bip.res
*/
void bigFromInt(int n) {
int i;
bip.res = newBig(sizeof(int));
if (n < 0) {
n = -n;
SET_SIGN(bip.res, BIG_NEGATIVE);
} else {
SET_SIGN(bip.res, BIG_POSITIVE);
}
for (i = 0; i < sizeof(int); i++) {
SET_DIGIT(bip.res, i, n & 0xFF);
n >>= 8;
}
while (--i >= 0 && GET_DIGIT(bip.res, i) == 0) ;
SET_ND(bip.res, i + 1);
}
/*
* conversion big --> int
*
* operand in bip.op1
* result is returned
*/
int bigToInt(void) {
int nd;
int i;
int res;
if (bip.op1 == NULL) {
nilRefException();
}
nd = GET_ND(bip.op1);
if (nd > 4 ||
(nd == 4 && GET_DIGIT(bip.op1, 3) >= 0x80)) {
fatalError("big integer too big for conversion to int");
}
res = 0;
for (i = nd - 1; i >= 0; i--) {
res <<= 8;
res |= (unsigned int) GET_DIGIT(bip.op1, i);
}
if (GET_SIGN(bip.op1) == BIG_NEGATIVE) {
res = -res;
}
return res;
}
/**************************************************************/
/* big integer I/O */
/*
* read a big integer
*
* stream to read from in parameter
* result in bip.res
*/
void bigRead(FILE *in) {
int c;
int positive;
c = fgetc(in);
while (isspace(c)) {
c = fgetc(in);
}
if (c == '-') {
positive = 0;
c = fgetc(in);
} else {
positive = 1;
if (c == '+') {
c = fgetc(in);
}
}
if (!isdigit(c)) {
fatalError("no digits in input");
}
bigFromInt(10);
bip.rem = bip.res;
bigFromInt(0);
while (isdigit(c)) {
bip.op1 = bip.res;
bip.op2 = bip.rem;
bigUmul();
bip.op1 = bip.res;
bigFromInt(c - '0');
bip.op2 = bip.res;
bigUadd();
c = fgetc(in);
}
ungetc(c, in);
if (positive || GET_ND(bip.res) == 0) {
SET_SIGN(bip.res, BIG_POSITIVE);
} else {
SET_SIGN(bip.res, BIG_NEGATIVE);
}
}
/*
* print a big integer
*
* stream to write to in parameter
* number to print in bip.op1
*/
void bigPrint(FILE *out) {
int nd;
unsigned char r;
int skipZero;
if (bip.op1 == NULL) {
nilRefException();
}
nd = GET_ND(bip.op1);
if (nd == 0) {
fprintf(out, "0");
return;
}
if (GET_SIGN(bip.op1) == BIG_NEGATIVE) {
fprintf(out, "-");
}
/* number of digits in base 10 = number of digits
in base 256 * log10(256), and log10(256) < 2.5 */
nd = 2 * nd + nd / 2;
bip.rem = bip.op1;
bigFromInt(10);
bip.op2 = bip.res;
bigFromInt(1);
while (nd != 0) {
bip.op1 = bip.res;
bigUmul();
nd--;
}
bip.op1 = bip.rem;
bip.op2 = bip.res;
skipZero = 1;
do {
bigUdiv();
if (GET_ND(bip.res) == 0) {
if (!skipZero) {
fprintf(out, "0");
}
} else {
if (GET_ND(bip.res) != 1) {
fatalError("internal library error #7 - THIS SHOULD NEVER HAPPEN!");
}
fprintf(out, "%c", GET_DIGIT(bip.res, 0) + '0');
skipZero = 0;
}
bip.op1 = bip.rem;
bip.rem = bip.op2;
r = bigUdiv1(10);
bip.op2 = bip.rem;
} while (r == 0);
}
/**************************************************************/
/* debugging */
/*
* dump a big integer object
*/
void bigDump(FILE *out, BigObjRef bigObjRef) {
int nd;
unsigned char sign;
int i;
if (bigObjRef == NULL) {
nilRefException();
}
nd = GET_ND(bigObjRef);
sign = GET_SIGN(bigObjRef);
fprintf(out, "[%d %c", nd, sign == BIG_POSITIVE ? '+' : '-');
for (i = 0; i < nd; i++) {
fprintf(out, " %02X", GET_DIGIT(bigObjRef, i));
}
fprintf(out, "]");
}

60
bigint/src/bigint.h Normal file
View File

@ -0,0 +1,60 @@
/*
* bigint.h -- big integer library
*/
#ifndef _BIGINT_H_
#define _BIGINT_H_
/* object representation */
typedef void* BigObjRef;
#include <stdio.h>
typedef struct {
int nd; /* number of digits; array may be bigger */
/* nd = 0 exactly when number = 0 */
unsigned char sign; /* one of BIG_NEGATIVE or BIG_POSITIVE */
/* zero always has BIG_POSITIVE here */
unsigned char digits[1]; /* the digits proper; number base is 256 */
/* LS digit first; MS digit is not zero */
} Big;
#include "support.h"
/* big integer processor registers */
typedef struct {
BigObjRef op1; /* first (or single) operand */
BigObjRef op2; /* second operand (if present) */
BigObjRef res; /* result of operation */
BigObjRef rem; /* remainder in case of division */
} BIP;
extern BIP bip; /* registers of the processor */
/* big integer processor functions */
int bigSgn(void); /* sign */
int bigCmp(void); /* comparison */
void bigNeg(void); /* negation */
void bigAdd(void); /* addition */
void bigSub(void); /* subtraction */
void bigMul(void); /* multiplication */
void bigDiv(void); /* division */
void bigFromInt(int n); /* conversion int --> big */
int bigToInt(void); /* conversion big --> int */
void bigRead(FILE *in); /* read a big integer */
void bigPrint(FILE *out); /* print a big integer */
void bigDump(FILE *out, BigObjRef bigObjRef); /* dump a big integer object */
#endif /* _BIGINT_H_ */

BIN
bigint/src/bigint.o Normal file

Binary file not shown.

BIN
bigint/src/libbigint.a Normal file

Binary file not shown.

15
bigint/src/support.h Normal file
View File

@ -0,0 +1,15 @@
/*
* support.h -- object representation and support functions
*/
#ifndef _SUPPORT_H_
#define _SUPPORT_H_
/* support functions */
void fatalError(char *msg); /* print a message and exit */
void * newPrimObject(int dataSize); /* create a new primitive object */
void * getPrimObjectDataPointer(void * primObject);
#endif /* _SUPPORT_H_ */

28
bigint/tst/Makefile Normal file
View File

@ -0,0 +1,28 @@
#
# Makefile for big integer test
#
BUILD = ../build
CC = gcc
CFLAGS = -g -Wall -I$(BUILD)/include
LDFLAGS = -g -Wall -L$(BUILD)/lib
LDLIBS = -lbigint
all: testbip
install: all
mkdir -p $(BUILD)/bin
cp testbip $(BUILD)/bin
testbip: testbip.o support.o
$(CC) $(LDFLAGS) -o testbip testbip.o support.o $(LDLIBS)
testbip.o: testbip.c
$(CC) $(CFLAGS) -o testbip.o -c testbip.c
support.o: support.c
$(CC) $(CFLAGS) -o support.o -c support.c
clean:
rm -f *~ testbip.o support.o testbip

55
bigint/tst/support.c Normal file
View File

@ -0,0 +1,55 @@
/*
* support.c -- support functions for big integer library
*/
#include <stdio.h>
#include <stdlib.h>
#include "support.h"
typedef struct {
unsigned int size; /* byte count of payload data */
unsigned char data[1]; /* payload data, size as needed */
} *ObjRef;
/*
* This routine is called in case a fatal error has occurred.
* It should print the error message and terminate the program.
*/
void fatalError(char *msg) {
printf("Fatal error: %s\n", msg);
exit(1);
}
/*
* This function is called whenever a new primitive object with
* a certain amount of internal memory is needed. It should return
* an object reference to a regular object, which contains a freely
* usable memory area of at least the requested size (measured in
* bytes). The memory area need not be initialized in any way.
*
* Note that this function may move all objects in memory at will
* (due to, e.g., garbage collection), as long as the pointers in
* the global "bip" structure point to the correct objects when
* the function returns.
*/
void * newPrimObject(int dataSize) {
ObjRef bigObjRef;
bigObjRef = malloc(sizeof(unsigned int) +
dataSize * sizeof(unsigned char));
if (bigObjRef == NULL) {
fatalError("newPrimObject() got no memory");
}
bigObjRef->size = dataSize;
return bigObjRef;
}
void * getPrimObjectDataPointer(void * obj){
ObjRef oo = ((ObjRef) (obj));
return oo->data;
}

BIN
bigint/tst/support.o Normal file

Binary file not shown.

BIN
bigint/tst/testbip Executable file

Binary file not shown.

1253
bigint/tst/testbip.c Normal file

File diff suppressed because it is too large Load Diff

BIN
bigint/tst/testbip.o Normal file

Binary file not shown.

View File

@ -7,12 +7,25 @@
#include "stack.c"
void inspect(struct stack s, int fp){
//todo Does not work dont know why
char input[20];
char ref[20];
char refStr[20];
printf("DEBUG [inspect]: stack, datam object?");
fgets(input,20,stdin);
if (input[0] == 's') printStack(s, fp);
if (input[0] == 'd'){/* todo */ }
if (input[0] == 'o'){/* todo */}
if (input[0] == 'o'){
scanf("%19s",ref);
ObjRefContainer container;
container = getRefs(s);
for (int i = 0; i<= container.size; i++) {
sprintf(refStr, "%p", (void *)&container.refs[i]);
if(strcmp(ref, refStr) == 0) printf("Adress exists\n");
else printf("Adress doeas not exist\n");
printf("%s",refStr);
}
}
}
void list(){
//todo

44
njvm.c
View File

@ -7,7 +7,6 @@
#include "program.c"
#include "codeReader.c"
#include "SDA.c"
#include "reg.c"
#include "debugMenu.c"
// Debug
@ -18,7 +17,7 @@ struct stack stack;
#define SIZE 1000
//Register
struct reg reg;
struct stack reg;
// Program
struct program program;
@ -41,6 +40,7 @@ void execute(struct program program) {
unsigned int temp;
char charInput;
StackSlot tempSlot;
ObjRef tempObj;
for (i = 0; i < *program.size; ++i) {
if (debug == 1) debugMenu(fp,stack,&debug);
switch (program.program[i] >> 24) {
@ -113,7 +113,7 @@ void execute(struct program program) {
*stack.current = fp;
if (debug == 1) printf("pop: %i\n", peek(stack, 1));
tempSlot = pop(stack) ;
fp = getIntValfromStackSlot(tempSlot);
fp = tempSlot.u.number;
break;
case POPL:
if (debug == 1) printf("popl: %i\n", SIGN_EXTEND(IMMEDIATE(program.program[i])));
@ -125,37 +125,37 @@ void execute(struct program program) {
break;
case NE:
if (debug == 1) printf("ne: %i != %i\n", peek(stack, 2), peek(stack, 1));
if (getIntValfromStackSlot(pop(stack)) != getIntValfromStackSlot(pop(stack))) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) != getIntValfromStackSlot(pop(stack))) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case EQ:
if (debug == 1) printf("eq: %i == %i\n", peek(stack, 2), peek(stack, 1));
if (getIntValfromStackSlot(pop(stack)) == getIntValfromStackSlot(pop(stack))) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) == getIntValfromStackSlot(pop(stack))) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case LT:
if (debug == 1) printf("lt: %i < %i\n", peek(stack, 2), peek(stack, 1));
temp = getIntValfromStackSlot(pop(stack));
if (getIntValfromStackSlot(pop(stack)) < temp) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) < temp) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case LE:
if (debug == 1) printf("le: %i <= %i\n", peek(stack, 2), peek(stack, 1));
temp = getIntValfromStackSlot(pop(stack));
if (getIntValfromStackSlot(pop(stack)) <= temp) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) <= temp) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case GT:
if (debug == 1) printf("gt: %i > %i\n", peek(stack, 2), peek(stack, 1));
temp = getIntValfromStackSlot(pop(stack));
if (getIntValfromStackSlot(pop(stack)) > temp) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) > temp) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case GE:
if (debug == 1) printf("ge: %i >= %i\n", peek(stack, 2), peek(stack, 1));
temp = getIntValfromStackSlot(pop(stack));
if (getIntValfromStackSlot(pop(stack)) >= temp) push(stack, stackSlotWitchNumber(1));
else push(stack, stackSlotWitchNumber(0));
if (getIntValfromStackSlot(pop(stack)) >= temp) push(stack, stackSlotWithObjRef(getIntObj(1)));
else push(stack, stackSlotWithObjRef(getIntObj(0)));
break;
case BRF:
if (debug == 1) printf("brf: %i\n", SIGN_EXTEND(IMMEDIATE(program.program[i])));
@ -197,19 +197,17 @@ void execute(struct program program) {
break;
case DUP:
if (debug==1) printf("dup\n");
temp = getIntValfromStackSlot(pop(stack));
push(stack, stackSlotWitchNumber(temp));
push(stack, stackSlotWitchNumber(temp));
tempObj = pop(stack).u.objRef;
push(stack, stackSlotWithObjRef(tempObj));
push(stack, stackSlotWithObjRef(tempObj));
break;
case POPR:
if (debug==1) printf("popr") ;
pushR(reg, getIntValfromStackSlot(pop(stack)));
if(debug == 1) printStackR(reg);
push(reg, pop(stack));
break;
case PUSHR:
if(debug == 1) printf("pushr");
push(stack, stackSlotWitchNumber(popR(reg)));
if(debug == 1) printStackR(reg);
push(stack, pop(reg));
break;
}
}
@ -233,7 +231,7 @@ int main(int argc, char *argv[]) {
// Initialize the registery
int rSize = SIZE;
int rCurrent = 0;
unsigned int r[SIZE];
StackSlot r[SIZE];
reg.size = &rSize;
reg.current = &rCurrent;
reg.stack = r;

48
reg.c
View File

@ -1,48 +0,0 @@
//
// Created by Nils on 29.10.2023.
//
#ifndef REG
#define REG
#include <stdio.h>
#include <stdlib.h>
struct reg {
int* size;
int* current;
unsigned int *stack;
};
void printStackR(struct reg stack) {
printf("Regurn reg\nSize:\t\t%i\nCurrent:\t%i\n", *stack.size, *stack.current);
for (int i = *stack.current-1; i > 0; --i) {
printf("||%i||\n", stack.stack[i]);
}
}
void pushR(struct reg s, unsigned int value) {
if (*s.current >= *s.size) {
printf("Stack Overflow\n");
exit(EXIT_FAILURE);
}
s.stack[*s.current] = value;
*s.current=*s.current + 1;
}
unsigned int popR(struct reg s) {
if (*s.current == 0) {
printf("Stack Underflow\n");
exit(EXIT_FAILURE);
}
*s.current = *s.current -1;
return s.stack[*s.current];
}
unsigned int peekR(struct reg s, int steps) {
if (*s.current - steps < 0) {
printf("Stack Underflow\n");
exit(EXIT_FAILURE);
}
return s.stack[*s.current - steps];
}
#endif

22
stack.c
View File

@ -14,12 +14,17 @@ struct stack {
StackSlot *stack;
};
typedef struct {
unsigned int size;
ObjRef *refs;
}ObjRefContainer;
void printStack(struct stack stack, int fp) {
printf("Stack\nSize:\t\t%i\nCurrent:\t%i\n", *stack.size, *stack.current);
for (int i = *stack.current -1; i >= 0; --i) {
printf("%i\t",i);
if(stack.stack[i].isObjRef){
printf("|%p|", stack.stack[i].u.objRef);
printf("|%p|", (void *)stack.stack[i].u.objRef);
if(stack.stack[i].u.objRef->size == sizeof(int))
printf("(%i)",*(int *)stack.stack[i].u.objRef->data);
}else {
@ -31,6 +36,21 @@ void printStack(struct stack stack, int fp) {
}
}
ObjRefContainer getRefs(struct stack stack){
ObjRefContainer continer;
int counter = 0;
for (int i = 0; i <= *stack.current; i++) {
if(stack.stack[i].isObjRef == true) counter++;
}
continer.size = counter;
ObjRef *list = (ObjRef *)malloc(counter * sizeof(ObjRef));
for (int i = 0; i<= *stack.current; i++)
if(stack.stack[i].isObjRef == true)
list[counter--] = stack.stack[i].u.objRef;
continer.refs = list;
return continer;
}
void push(struct stack s, StackSlot value) {
if (*s.current >= *s.size) {
printf("Stack Overflow\n");