№
|
Код інструкції
|
Двійкове значення
|
Зміст
|
Тип
|
18
|
HALT
|
00110
|
Збільшує значення ПЛ на 1, потім припиняє виконання,
стимулятор має повідомляти, що виконано зупинку.
|
O
|
19
|
NOOP
|
00111
|
Нічого не виконується
|
O
|
20
|
PUSH
|
10011
|
Записати в стек з 1 регістру
|
O
|
21
|
POP
|
10100
|
Зчитати з стеку в 1 регістр
|
O
|
O-тип інструкцій:
біти
24-22: код операції
біти
21-0: не використовуються (=0)
\
Структура СК після модифікації:
Рис 1. Функціональна схема СК після модифікації
В СК було додано 13 інструкцій, внаслідок чого
поле КОП збільшилося на 2 біти до 5 біт (максимально 32 інструкції з яких використано
21). Решта частина коду операції не зазнала зміни. Був доданий стек глибиною 32
слова по 32 біти, покажчик вершини стеку, прапорець стану ZF.
1. div: 45/5=9.
Програма:
lw 0 1 num1
lw 0 2 num2
div 1 2 3
done halt
num1 .fill 45
num2 .fill 5
Машинний
код:
8454148
8519685
34209795
25165824
45
5
Кінцевий
стан:
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 34209795
mem[
3 ] 25165824
mem[
4 ] 45
mem[
5 ] 5
registers:
reg[
0 ] 0
reg[
1 ] 45
reg[
2 ] 5
reg[
3 ] 9
reg[
4 ] 0
reg[
5 ] 0
reg[
7 ] 0
end
state
2.
imul: 3*(-4)=-12.
Програма:
lw
0 1 num1
lw
0 2 num2
imul 1 2 3
done
halt
num1
.fill 3
num2
.fill -4
Машинний
код:
8454148
8519685
34209795
25165824
3
-4
Кінцевий
стан:
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 38404099
mem[
3 ] 25165824
mem[
4 ] 3
mem[
5 ] -4
registers:
reg[
0 ] 0
reg[
1 ] 3
reg[
2 ] -4
reg[
3 ] -12
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
3.
xidiv: 30/(-5)=-6, обміняти операнди місцями.
Програма:
lw 0 1 num1
lw 0 2 num2
xidiv 1 2 3
done halt
num1 .fill 30
num2 .fill -5
Машинний
код:
8454148
8519685
42598403
25165824
30
-5
Кінцевий
стан:
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 42598403
mem[
3 ] 25165824
mem[
4 ] 30
mem[
5 ] -5
registers:
reg[
0 ] 0
reg[
1 ] -5
reg[
2 ] 30
reg[
3 ] -6
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
4.and:
5&3=1
0101
&
0011
0001
Програма:
lw 0 1 num1
lw 0 2 num2
andf 1 2 3
done halt
num1 .fill 5
num2 .fill 3
Машинний
код:
8454148
8519685
46792707
25165824
5
3
Кінцевий
стан:
@@@
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 46792707
mem[
3 ] 25165824
mem[
4 ] 5
mem[
5 ] 3
registers:
reg[
0 ] 0
reg[
1 ] 5
reg[
2 ] 3
reg[
3 ] 1
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
xor:
5#3=6
0101
#
0011
0110
Програма:
lw 0 1 num1
lw 0 2 num2
xorf 1 2 3
done halt
num1 .fill 3
num2 .fill 5
Машинний
код:
8454148
8519685
50987011
25165824
3
5
Кінцевий
стан:
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 50987011
mem[
3 ] 25165824
mem[
4 ] 3
mem[
5 ] 5
registers:
reg[
0 ] 0
reg[
1 ] 3
reg[
2 ] 5
reg[
3 ] 6
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
6.
cmpge: 1= 5>=3
Програма:
@@@
state:
pc 4
ZF
= 0
stack:
memory:
mem[
0 ] 8454148
mem[
1 ] 8519685
mem[
2 ] 55181315
mem[
3 ] 25165824
mem[
4 ] 5
mem[
5 ] 3
registers:
reg[
0 ] 0
reg[
1 ] 5
reg[
2 ] 3
reg[
3 ] 1
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
7. jma:
if (7>=4) reg[4]=7; else reg[5]=4, reg[4]=7.
Програма:
lw 0 1 num1
lw 0 2 num2
jmae 1 2 1
lw 0 5 num2
lw 0 4 num1
done halt
num1 .fill 7
num2 .fill 4
Машинний
код:
8454150
8519687
59375617
8716295
8650758
25165824
7
3
Кінцевий
стан:
@@@
state:
pc 6
ZF
= 0
stack:
memory:
mem[
0 ] 8454150
mem[
1 ] 8519687
mem[
2 ] 59375617
mem[
3 ] 8716295
mem[
4 ] 8650758
mem[
5 ] 25165824
mem[
6 ] 7
mem[
7 ] 4
registers:
reg[
0 ] 0
reg[
1 ] 7
reg[
2 ] 4
reg[
3 ] 0
reg[
4 ] 7
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
8.
jmnae: if (5!>=6) reg[4]=6; else reg[4]=5, reg[5]=6.
Програма:
lw 0 1 num1
lw 0 2 num2
jmnae 1 2 1
lw 0 5 num2
lw 0 4 num1
done halt
num1 .fill 5
num2 .fill 6
Машинний
код:
8454150
8519687
63569921
8716295
8650758
25165824
5
6
Кінцевий
стан:
@@@
state
pc 6
ZF
= 0
stack:
memory:
mem[
0 ] 8454150
mem[
1 ] 8519687
mem[
2 ] 63569921
mem[
3 ] 8716295
mem[
4 ] 8650758
mem[
5 ] 25165824
mem[
6 ] 5
mem[
7 ] 6
registers:
reg[
0 ] 0
reg[
1 ] 5
reg[
2 ] 6
reg[
3 ] 0
reg[
4 ] 5
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
9. bsr:
if (16=1000) “1” – в позиції 4.
Програма:
lw 0 1 num1
bsr 1 2
done halt
num1 .fill 16
Машинний
код:
8454150
8519687
25165824
16
Кінцевий
стан:
@@@
state:
pc 3
ZF
= 1
stack:
memory:
mem[
0 ] 8454147
mem[
1 ] 71958528
mem[
2 ] 25165824
mem[
3 ] 16
registers:
reg[
0 ] 0
reg[
1 ] -2147483648
reg[
2 ] 4
reg[
3 ] 0
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
10.
bsf: 8 (1000) – «1» в позиції 3.
Програма:
lw 0 1 num1
bsf 1 2
done halt
num1 .fill 8
Машинний
код:
8454147
71958528
25165824
8
Кінцевий
стан:
@@@
@@@
state:
pc 3
ZF
= 1
stack:
memory:
mem[
0 ] 8454147
mem[
1 ] 67764224
mem[
2 ] 25165824
mem[
3 ] 8
registers:
reg[
0 ] 0
reg[
1 ] 1
reg[
2 ] 3
reg[
3 ] 0
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
11.
jne: if (16=1000) “1” – в позиції 4, ZF=1: Робота програми завершується, else
reg[4]=8.
Програма:
lw 0 1 num1
bsr 1 0 3
jne 0 0 4
lw 0 4 num1
done halt
num1 .fill 8
Машинний код:
8454150
67764224
8454147
25165824
8
Кінцевий
стан:
@@@
state:
@@@
state:
pc 5
ZF
= 1
stack:
memory:
mem[
0 ] 8454149
mem[
1 ] 71827456
mem[
2 ] 75497476
mem[
3 ] 8650757
mem[
4 ] 25165824
mem[
5 ] 8
registers:
reg[
0 ] 0
reg[
1 ] -2147483648
reg[
2 ] 0
reg[
3 ] 0
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
12.
push, pop: push 2, push 3, pop, pop.
Програма:
lw 0 1 num1
push
lw 0 1 num2
push
pop
pop
done halt
num1 .fill 2
num2 .fill 3
Машинний
код:
8454150
79691776
8454151
79691776
83886080
83886080
25165824
2
3
Проміжний
стан, після двох push:
@@@
state:
pc 4
ZF
= 0
stack:
stk[
0 ] 2
stk[
1 ] 3
memory:
mem[
0 ] 8454151
mem[
1 ] 79691776
mem[
2 ] 8454152
mem[
3 ] 79691776
mem[
4 ] 83886080
mem[
5 ] 83886080
mem[
6 ] 25165824
mem[
7 ] 2
mem[
8 ] 3
registers:
reg[
0 ] 0
reg[
1 ] 3
reg[
2 ] 0
reg[
3 ] 0
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
Кінцевий
стан:
@@@
state:
pc 7
ZF
= 0
stack:
memory:
mem[
0 ] 8454151
mem[
1 ] 79691776
mem[
2 ] 8454152
mem[
3 ] 79691776
mem[
4 ] 83886080
mem[
5 ] 83886080
mem[
6 ] 25165824
mem[
7 ] 2
mem[
8 ] 3
registers:
reg[
0 ] 0
reg[
1 ] 2
reg[
2 ] 0
reg[
3 ] 0
reg[
4 ] 0
reg[
5 ] 0
reg[
6 ] 0
reg[
7 ] 0
end
state
При виконанні даного курсового
проекту було реалізовано прототипний CISC - комп’ютер згідно із поставленим завданням.
Створений комп’ютер пройшов тестування на коректність виконуваних операцій та на
відловлювання помилок у вхідному асемблерному коді при синтаксичному та семантичному
аналізі. Засвоєно принципи дії та архітектуру прототипних варіантів CISC - комп’ютера.
Було внесено зміни в структуру існуючого симулятора CISC - комп’ютера, а саме, доповнена
система команд заданими інструкціями, змінено формат усіх команд в частині КОП.
До існуючих типів адресації CISC - комп’ютера було добавлено безадресний тип адресації,
що в свою чергу призвело до створення стеку всередині структури комп’ютера. Було
проведено аналіз роботи команд усіх типів та написано тести з поданням результату
роботи симулятора у вигляді виведеного стану машини.
1.
Мельник А.О. Архітектура комп’ютера. Наукове видання. - Луцьк: Волинська
обласна друкарня, 2008. - 470 с.
2.
Жмакин А.П. Архитектура ЭВМ. - СПб.: БХВ-Петербург, 2006. - 320 с.
3.
Таненбаум Э. Архитектура компьютера.5-е изд. (+CD). - СПб.: Питер,
2007. - 844 с.
4.
Patterson D., and Hennessy J.computer Architecture.
A quantitative Approach. Second Edition. - Morgan Kaufmann Publishers, Inc., San Francisco, California, 1996. - 760
p.
Доаток I (код програми-асемблера):
/* Assembler for LC
*/
#include <stdlib.
h>
#include <stdio.
h>
#include <string.
h>
#define MAXLINELENGTH
1000
#define MAXNUMLABELS
65536
#define MAXLABELLENGTH
7 /* includes the null character termination */
#define ADD 0
#define NAND 1
#define LW 2
#define SW 3
#define BEQ 4
#define JALR 5
#define HALT 6
#define NOOP 7
#define div 8
#define imul 9
#define xidiv 10
#define andf 11
#define xorf 12
#define cmpge 13
#define jmae 14
#define jmnae 15
#define bsf 16
#define bsr 17
#define jne 18
#define push 19
#define pop 20
int readandfParse
(FILE *, char *, char *, char *, char *, char *);
int translateSymbol
(char labelArray [MAXNUMLABELS] [MAXLABELLENGTH], int labelAddress [MAXNUMLABELS],
int, char *);
int isNumber (char
*);
void testRegArg (char
*);
void testAddrArg (char
*);
int main (int argc,
char *argv [])
{
char *inFileString,
*outFileString;
FILE *inFilePtr, *outFilePtr;
int address;
char label [MAXLINELENGTH],
opcode [MAXLINELENGTH], arg0 [MAXLINELENGTH],
arg1 [MAXLINELENGTH],
arg2 [MAXLINELENGTH], argTmp [MAXLINELENGTH];
int i;
int numLabels=0;
int num;
int addressField;
char labelArray [MAXNUMLABELS]
[MAXLABELLENGTH];
int labelAddress [MAXNUMLABELS];
if (argc! = 3) {
printf ("error:
usage: %s <assembly-code-file> <machine-code-file>\n",
argv [0]);
exit (1);
}
inFileString = argv
[1];
outFileString = argv
[2];
inFilePtr = fopen
(inFileString, "r");
if (inFilePtr == NULL)
{
printf ("error
in opening %s\n", inFileString);
exit (1);
}
outFilePtr = fopen
(outFileString, "w");
if (outFilePtr == NULL)
{
printf ("error
in opening %s\n", outFileString);
exit (1);
}
/* map symbols to addresses
*/
/* assume address start
at 0 */
for (address=0; readandfParse
(inFilePtr, label, opcode, arg0, arg1, arg2);
address++) {
/*
printf ("%d: label=%s,
opcode=%s, arg0=%s, arg1=%s, arg2=%s\n",
address, label, opcode,
arg0, arg1, arg2);
*/
/* check for illegal
opcode */
if (strcmp (opcode,
"add") && strcmp (opcode, "nand") &&
strcmp (opcode,
"lw") && strcmp (opcode, "sw") &&
strcmp (opcode,
"beq") && strcmp (opcode, "jalr") &&
strcmp (opcode,
"halt") && strcmp (opcode, "noop") &&
strcmp (opcode,".
fill") && strcmp (opcode, "div") &&
strcmp (opcode,
"imul") && strcmp (opcode, "xidiv") &&
strcmp (opcode,
"andf") && strcmp (opcode, "xorf") &&
strcmp (opcode,
"cmpge") && strcmp (opcode, "jmae") &&
strcmp (opcode,
"jmnae") && strcmp (opcode, "bsr") &&
strcmp (opcode,
"jne") && strcmp (opcode, "bsf") &&
strcmp (opcode,
"push") && strcmp (opcode, "pop"))
{
printf ("error:
unrecognized opcode %s at address %d\n", opcode,
address);
exit (1);
}
/* check register fields
*/
if (! strcmp (opcode,
"add") ||! strcmp (opcode, "nand") ||
! strcmp (opcode,
"lw") ||! strcmp (opcode, "sw") ||
! strcmp (opcode,
"beq") ||! strcmp (opcode, "jalr") ||
! strcmp (opcode,
"div") ||! strcmp (opcode, "imul") ||
! strcmp (opcode,
"xidiv") ||! strcmp (opcode, "andf") ||
! strcmp (opcode,
"xorf") ||! strcmp (opcode, "cmpge") ||
! strcmp (opcode,
"bsf") ||! strcmp (opcode, "bsr"))
{
testRegArg (arg0);
testRegArg (arg1);
}
if (! strcmp (opcode,
"nand") ||! strcmp (opcode, "add") ||
! strcmp (opcode,
"div") ||! strcmp (opcode, "imul") ||
! strcmp (opcode,
"xidiv") ||! strcmp (opcode, "andf") ||
! strcmp (opcode,
"xorf") ||! strcmp (opcode, "cmpge"))
{
testRegArg (arg2);
}
/* check addressField
*/
if (! strcmp (opcode,
"lw") ||! strcmp (opcode, "sw") ||
! strcmp (opcode,
"beq") ||! strcmp (opcode, "jmae") ||
! strcmp (opcode,
"jmnae") ||! strcmp (opcode, "jne"))
{
testAddrArg (arg2);
}
if (! strcmp (opcode,".
fill"))
{
testAddrArg (arg0);
}
/* check for enough
arguments */
if ( (strcmp (opcode,
"halt") && strcmp (opcode, "noop") &&
strcmp (opcode,".
fill") && strcmp (opcode, "jalr") &&
strcmp (opcode,
"bsf") && strcmp (opcode, "bsr") &&
strcmp (opcode,
"pop") && strcmp (opcode, "push") &&
strcmp (opcode,
"je") && arg2 [0] =='\0') ||
(! strcmp (opcode,
"jalr") && arg1 [0] =='\0') ||
(! strcmp (opcode,".
fill") && arg0 [0] =='\0'))
{
printf ("error
at address %d: not enough arguments\n", address);
exit (2);
}
if (label [0]! = '\0')
{
/* check for labels
that are too long */
if (strlen (label)
>= MAXLABELLENGTH) {
printf ("label
too long\n");
exit (2);
}
/* make sure label
starts with letter */
if (! sscanf (label,
"% [a-zA-Z]", argTmp)) {
printf ("label
doesn't start with letter\n");
exit (2);
}
/* make sure label
consists of only letters andf numbers */
sscanf (label,
"% [a-zA-Z0-9]", argTmp);
if (strcmp (argTmp,
label)) {
printf ("label
has character other than letters andf numbers\n");
exit (2);
}
/* look for duplicate
label */
for (i=0; i<numLabels;
i++) {
if (! strcmp (label,
labelArray [i])) {
printf ("error:
duplicate label %s at address %d\n",
label, address);
exit (1);
}
}
/* see if there are
too many labels */
if (numLabels >=
MAXNUMLABELS) {
printf ("error:
too many labels (label=%s) \n", label);
exit (2);
}
strcpy (labelArray
[numLabels], label);
labelAddress [numLabels++]
= address;
}
}
for (i=0; i<numLabels;
i++) {
/* printf ("%s
= %d\n", labelArray [i], labelAddress [i]); */
}
/* now do second pass
(print machine code, with symbols filled in as
addresses) */
rewind (inFilePtr);
for (address=0; readandfParse
(inFilePtr, label, opcode, arg0, arg1, arg2);
address++) {
if (! strcmp (opcode,
"add")) {
num = (ADD <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "nand")) {
num = (NAND <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "div")) {
num = (div <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "imul")) {
num = (imul <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "xidiv")) {
num = (xidiv <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "andf")) {
num = (andf <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "xorf")) {
num = (xorf <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "cmpge")) {
num = (cmpge <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16) | atoi (arg2);
} else if (! strcmp
(opcode, "jalr")) {
num = (JALR <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16);
} else if (! strcmp
(opcode, "bsf")) {
num = (bsf <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16);
} else if (! strcmp
(opcode, "push")) {
num = (push <<
22);
} else if (! strcmp
(opcode, "pop")) {
num = (pop <<
22);
} else if (! strcmp
(opcode, "halt")) {
num = (HALT <<
22);
} else if (! strcmp
(opcode, "noop")) {
num = (NOOP <<
22);
} else if (! strcmp
(opcode, "bsr")) {
num = (bsr <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16);
} else if (! strcmp
(opcode, "lw") ||! strcmp (opcode, "sw") ||
! strcmp (opcode,
"beq") ||! strcmp (opcode, "jmae") ||
! strcmp (opcode,
"jmnae") ||! strcmp (opcode, "jne")) {
/* if arg2 is symbolic,
then translate into an address */
if (! isNumber (arg2))
{
addressField = translateSymbol
(labelArray, labelAddress,
numLabels, arg2);
/*
printf ("%s being
translated into %d\n", arg2, addressField);
*/
if (! strcmp (opcode,
"beq") ||! strcmp (opcode, "jmae") ||! strcmp (opcode,
"jmnae")) {
addressField = addressField-address-1;
}
} else {
addressField = atoi
(arg2);
}
if (addressField <
- 32768 || addressField > 32767) {
printf ("error:
offset %d out of range\n", addressField);
exit (1);
}
/* truncate the offset
field, in case it's negative */
addressField = addressField
& 0xFFFF;
if (! strcmp (opcode,
"beq")) {
num = (BEQ <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16)
| addressField;
} else if (! strcmp
(opcode, "jmae")) {
num = (jmae <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16)
| (addressField);
} else if (! strcmp
(opcode, "jmnae")) {
num = (jmnae <<
22) | (atoi (arg0) << 19) | (atoi (arg1) << 16)
| (addressField);
} else if (! strcmp
(opcode, "jne")) {
num = (jne <<
22) | (addressField);
} else {
/* lw or sw */
if (! strcmp (opcode,
"lw")) {
num = (LW <<
22) | (atoi (arg0) << 19) |
(atoi (arg1) <<
16) | addressField;
num = (SW <<
22) | (atoi (arg0) << 19) |
(atoi (arg1) <<
16) | addressField;
}
}
} else if (! strcmp
(opcode,". fill")) {
if (! isNumber (arg0))
{
num = translateSymbol
(labelArray, labelAddress, numLabels,
arg0);
} else {
num = atoi (arg0);
}
}
/* printf ("
(address %d): %d (hex 0x%x) \n", address, num, num); */
fprintf (outFilePtr,
"%d\n", num);
}
exit (0);
}
/*
* Read andf parse a
line of the assembly-language file. Fields are returned
* in label, opcode,
arg0, arg1, arg2 (these strings must have memory already
* allocated to them).
*
* Return values:
* 0 if reached end
of file
* 1 if all went well
*
* exit (1) if line
is too long.
*/
int readandfParse
(FILE *inFilePtr, char *label, char *opcode, char *arg0,char *arg1, char *arg2)
{
char line [MAXLINELENGTH];
char *ptr = line;
/* delete prior values
*/
label [0] = opcode
[0] = arg0 [0] = arg1 [0] = arg2 [0] = '\0';
/* read the line from
the assembly-language file */
if (fgets (line, MAXLINELENGTH,
inFilePtr) == NULL) {
/* reached end of file
*/
return (0);
}
/* check for line too
long */
if (strlen (line) ==
MAXLINELENGTH-1) {
printf ("error:
line too long\n");
exit (1);
}
/* is there a label?
*/
ptr = line;
if (sscanf (ptr,
"% [^\t\n]", label)) {
/* successfully read
label; advance pointer over the label */
ptr += strlen (label);
}
/*
* Parse the rest of
the line. Would be nice to have real regular
* expressions, but
scanf will suffice.
*/
sscanf (ptr,
"%* [\t\n\r] % [^\t\n\r] %* [\t\n\r] % [^\t\n\r] %* [\t\n\r] % [^\t\n\r] %*
[\t\n\r] % [^\t\n\r] ",
opcode, arg0, arg1,
arg2);
return (1);
}
int translateSymbol
(char labelArray [MAXNUMLABELS] [MAXLABELLENGTH],
int labelAddress [MAXNUMLABELS],
int numLabels, char *symbol)
{
int i;
/* search through address
label table */
for (i=0; i<numLabels
&& strcmp (symbol, labelArray [i]); i++) {
}
if (i>=numLabels)
{
printf ("error:
missing label %s\n", symbol);
exit (1);
}
return (labelAddress
[i]);
}
int isNumber (char
*string)
{
/* return 1 if string
is a number */
int i;
return ( (sscanf (string,
"%d", &i)) == 1);
}
/* Test register argument;
make sure it's in range andf has no bad characters. */
void testRegArg (char
*arg)
{
int num;
char c;
if (atoi (arg) <
0 || atoi (arg) > 7) {
printf ("error:
register out of range\n");
exit (2);
}
if (sscanf (arg,
"%d%c", &num, &c)! = 1) {
printf ("bad character
in register argument\n");
exit (2);
}
}
/* Test addressField
argument. */
void testAddrArg (char
*arg)
{
int num;
char c;
/* test numeric addressField
*/
if (isNumber (arg))
{
if (sscanf (arg,
"%d%c", &num, &c)! = 1) {
printf ("bad character
in addressField\n");
exit (2);
}
}
}
Додаток II (код
симулятора)
/*Instruction-level
simulator for the LC */
#include <stdio.
h>
#include <stdlib.
h>
#include <string>
#include <math.
h>
#include <vector>
using namespace std;
#define NUMMEMORY 65536
/* maximum number of words in memory */
#define NUMREGS 8 /*
number of machine registers */
#define MAXLINELENGTH
1000
#define STACKDEPTH
32
#define ADD 0
#define NAND 1
#define LW 2
#define SW 3
#define BEQ 4
#define JALR 5
#define HALT 6
#define NOOP 7
#define div 8
#define imul 9
#define xidiv 10
#define andf 11
#define xorf 12
#define cmpge 13
#define jmae 14
#define jmnae 15
#define bsf 16
#define bsr 17
#define jne 18
#define push 19
#define pop 20
typedef struct stateStruct
{
int pc;
int mem [NUMMEMORY];
int reg [NUMREGS];
int numMemory;
vector <int>
sStack;
int ZF;
} stateType;
void printState (stateType
*);
void run (stateType);
int convertNum (int);
int main (int argc,
char *argv [])
{
int i;
char line [MAXLINELENGTH];
stateType state;
FILE *filePtr;
if (argc! = 2) {
printf ("error:
usage: %s <machine-code file>\n", argv [0]);
exit (1);
}
/* initialize memories
and registers */
for (i=0; i<NUMMEMORY;
i++) {
state. mem [i] = 0;
}
for (i=0; i<NUMREGS;
i++) {
state. reg [i] = 0;
}
state. ZF=0;
state. pc=0;
/* read machine-code
file into instruction/data memory (starting at
address 0) */
filePtr = fopen (argv
[1], "r");
if (filePtr == NULL)
{
printf ("error:
can't open file %s\n", argv [1]);
perror ("fopen");
exit (1);
}
for (state. numMemory=0;
fgets (line, MAXLINELENGTH, filePtr)! = NULL;
state. numMemory++)
{
if (state. numMemory
>= NUMMEMORY) {
printf ("exceeded
memory size\n");
exit (1);
}
if (sscanf (line,
"%d", state. mem+state. numMemory)! = 1) {
printf ("error
in reading address %d\n", state. numMemory);
exit (1);
}
printf ("memory
[%d] =%d\n", state. numMemory, state. mem [state. numMemory]);
}
printf ("\n");
/* run never returns
*/
run (state);
return (0);
}
void run (stateType
state)
{
int i;
int arg0, arg1, arg2,
addressField;
int instructions=0;
int opcode;
int maxMem=-1; /* highest
memory address touched during run */
for (; 1; instructions++)
{ /* infinite loop, exits when it executes halt */
printState (&state);
if (state. pc <
0 || state. pc >= NUMMEMORY) {
printf ("pc went
out of the memory range\n");
exit (1);
}
maxMem = (state. pc
> maxMem)? state. pc: maxMem;
/* this is to make
the following code easier to read */
opcode = state. mem
[state. pc] >> 22;
arg0 = (state. mem
[state. pc] >> 19) & 0x7;
arg1 = (state. mem
[state. pc] >> 16) & 0x7;
arg2 = state. mem
[state. pc] & 0x7; /* only for add, nand */
addressField = convertNum
(state. mem [state. pc] & 0xFFFF); /* for beq,
lw, sw */
state. pc++;
if (opcode == ADD)
{
state. reg [arg2] =
state. reg [arg0] + state. reg [arg1];
} else if (opcode ==
NAND) {
state. reg [arg2] =
~ (state. reg [arg0] & state. reg [arg1]);
} else if (opcode ==
LW) {
if (state. reg [arg0]
+ addressField < 0 ||
state. reg [arg0] +
addressField >= NUMMEMORY) {
printf ("address
out of bounds\n");
exit (1);
}
state. reg [arg1] =
state. mem [state. reg [arg0] + addressField];
if (state. reg [arg0]
+ addressField > maxMem) {
maxMem = state. reg
[arg0] + addressField;
}
} else if (opcode ==
SW) {
if (state. reg [arg0]
+ addressField < 0 ||
state. reg [arg0] +
addressField >= NUMMEMORY) {
printf ("address
out of bounds\n");
exit (1);
}
state. mem [state.
reg [arg0] + addressField] = state. reg [arg1];
if (state. reg [arg0]
+ addressField > maxMem) {
maxMem = state. reg
[arg0] + addressField;
}
} else if (opcode ==
BEQ) {
if (state. reg [arg0]
== state. reg [arg1]) {
state. pc += addressField;
}
} else if (opcode ==
JALR) {
state. reg [arg1] =
state. pc;
if (arg0! = 0)
state. pc = state.
reg [arg0];
else
state. pc = 0;
} else if (opcode ==
NOOP) {
} else if (opcode ==
HALT) {
printf ("machine
halted\n");
printf ("total
of %d instructions executed\n", instructions+1);
printf ("final
state of machine: \n");
printState (&state);
exit (0);
} else if (opcode ==
xidiv) {
state. reg [arg2] =
state. reg [arg0] / state. reg [arg1];
state. reg [arg0] ^=state.
reg [arg1] ^=state. reg [arg0] ^=state. reg [arg1];
} else if (opcode ==
div) {
state. reg [arg2] =
(unsigned) state. reg [arg0] / (unsigned) state. reg [arg1];
} else if (opcode ==
imul) {
state. reg [arg2] =
state. reg [arg0] * state. reg [arg1];
} else if (opcode ==
andf) {
state. reg [arg2] =
state. reg [arg0] & state. reg [arg1];
} else if (opcode ==
xorf) {
state. reg [arg2] =
state. reg [arg0] xor state. reg [arg1];
} else if (opcode ==
cmpge) {
state. reg [arg2] =
state. reg [arg0] >= state. reg [arg1];
} else if (opcode ==
jmae) {
if ( (unsigned) state.
reg [arg0] >= (unsigned) state. reg [arg1])
state. pc += addressField;
} else if (opcode ==
jmnae) {
if ( (unsigned) state.
reg [arg0] < (unsigned) state. reg [arg1])
state. pc += addressField;
} else if (opcode ==
bsf) {
state. ZF=0;
for (i=0; i<31;
i++) {
if (state. reg [arg0]
%2==1) {
state. ZF=1;
state. reg [arg1] =i;
break;
}
else {
state. reg [arg0] =state.
reg [arg0] >>1;
}
}
} else if (opcode ==
bsr) {
state. ZF=0;
for (i=31; i>0;
i--) {
if (state. reg [arg0]
/0x80000000==1) {
state. ZF=1;
state. reg [arg1] =i;
break;
}
else {
state. reg [arg0] =state.
reg [arg0] <<1;
}
}
} else if (opcode ==
jne) {
if (state. ZF! =0)
state. pc = addressField;
} else if (opcode ==
push) {
if (state. sStack.
size () > STACKDEPTH - 1)
{
printf ("\nerror:
stack overflow! 0x%x\n", opcode);
printf ("total
of %d instructions executed\n", instructions+1);
printf ("final
state of machine: \n");
printState (&state);
exit (1);
}
else state. sStack.
push_back (state. reg [1]);
} else if (opcode ==
pop) {
if (state. sStack.
empty ())
{
printf ("\nerror:
stack underflow! 0x%x\n", opcode);
printf ("total
of %d instructions executed\n", instructions+1);
printf ("final
state of machine: \n");
printState (&state);
exit (1);
}
else
{
state. reg [1] = state.
sStack. back ();
state. sStack. pop_back
();
}
} else {
printf ("error:
illegal opcode 0x%x\n", opcode);
exit (1);
}
state. reg [0] = 0;
}
}
void
printState (stateType
*statePtr)
{
int i;
printf ("\n@@@\nstate:
\n");
printf ("\tpc
%d\n", statePtr->pc);
printf ("\t\tZF
= %d\n",statePtr->ZF);
vector <int>::
iterator stackiter;
printf ("\tstack:
\n");
for (stackiter = statePtr->sStack.
begin (), i = 0; stackiter < statePtr->sStack. end (); stackiter++, i++) {
printf ("\t\tstek
[%d] %d\n", i, *stackiter);
}
printf ("\tmemory:
\n");
for (i=0; i<statePtr->numMemory;
i++) {
printf ("\t\tmem
[%d] %d\n", i, statePtr->mem [i]);
}
printf ("\tregisters:
\n");
for (i=0; i<NUMREGS;
i++) {
printf ("\t\treg
[%d] %d\n", i, statePtr->reg [i]);
}
}
int convertNum (int
num)
{
/* convert a 16-bit
number into a 32-bit Sun integer */
if (num & (1<<15))
{
num - = (1<<16);
}
return (num);
}