COMP1521 Revision 11a Revision Questions
Getting Started
revision11a and changing to this directory.
mkdir revision11a cd revision11a
There are some provided files for this revision which you can fetch with this command:
1521 fetch revision11a
If you're not working at CSE, you can download the provided files as a zip file or a tar file.
Revision Exercise: MIPS print odd (PS)
You have been given print_odd.s,
which contains a MIPS function print_odd,
that takes 2 arguments: a source array and its length.
Add code to print_odd
so that it is equivalent to this C function:
void print_odd(int *src, int n) {
for (int i = 0; i < n; i++) {
if (src[i] % 2 != 0) {
printf("%d ", src[i]);
}
}
printf("\n");
}
The function print_odd prints out every odd number in the array.
For example:
1521 mipsy test_print_odd.s print_odd.s Enter 10 integers: 1 2 3 4 5 6 7 8 9 10 1 3 5 7 9 1521 mipsy test_print_odd.s print_odd.s Enter 10 integers: 99 6 4 1 -4 0 2 87 3 5 99 1 87 3 5 1521 mipsy test_print_odd.s print_odd.s Enter 10 integers: 2 4 6 8 10 12 14 16 18 20
You can use make(1) to build the provided C code:
make print_odd
You can use 1521 mipsy to run your MIPS code:
1521 mipsy test_print_odd.s print_odd.s
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest mips_revision_print_odd
Revision Exercise: MIPS every kth (PS)
You have been given every_kth.s,
which contains a MIPS function every_kth,
that takes 4 arguments: a source array, its length, an integer k and a destination array
and returns the value 42.
Add code to every_kth
so that it is equivalent to this C function:
int every_kth(int *src, int n, int k, int *dest) {
int count = 0;
for (int i = 0; i < n; i++) {
if (i % k == 0) {
dest[count] = src[i];
count++;
}
}
return count;
}
The function every_kth copies every k-th element of src into dest and returns the number of elements copied.
It is assumed that destination array is large enough and k > 0.
For example:
1521 mipsy test_every_kth.s every_kth.s Enter k: 3 Enter 10 integers: 1 2 3 4 5 6 7 8 9 10 1 4 7 10 1521 mipsy test_every_kth.s every_kth.s Enter k: 2 Enter 10 integers: 99 6 4 1 -4 0 2 87 3 5 99 4 -4 2 3 1521 mipsy test_every_kth.s every_kth.s Enter k: 10 Enter 10 integers: 99 98 97 96 95 94 93 92 91 90 99
You can use make(1) to build the provided C code:
make every_kth
You can use 1521 mipsy to run your MIPS code:
1521 mipsy test_every_kth.s every_kth.s
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest mips_revision_every_kth
Revision Exercise: MIPS no vowels (PS)
You have been given mips_no_vowels.s,
which contains a MIPS function mips_no_vowels,
that takes 2 arguments: a source array and a destination array
and returns the value 42.
Add code to mips_no_vowels
so that it is equivalent to this C function:
// Copy all characters from the src array to the dest array
// except for upper case or lower case vowels
// src and dest are both '\0' terminated strings
// return the number of vowels found
int no_vowels(char *src, char *dest) {
int j = 0;
int n = 0;
char ch;
for (int i = 0; src[i] != '\0'; i++) {
ch = src[i];
if (is_vowel(ch)) {
n++;
} else {
dest[j] = ch;
j++;
}
}
dest[j] = '\0';
return n;
}
The function mips_no_vowels copies all characters from the src
array to the dest array except for upper or lower case vowels ie. ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U')
Note that src and dest are both '\0' terminated strings
The function must return the number of vowels found.
It is assumed that destination array is large enough to store the resulting string.
You must also implement the following helper function in MIPS too:
// returns 1 if the ascii character in c represents
// an upper or lower case vowel
// returns 0 otherwise
int is_vowel(char c) {
// Trick to convert case from Text Representation Lectures
char lower_case_c = c | 0x20;
if (lower_case_c == 'a' ||
lower_case_c == 'e' ||
lower_case_c == 'i' ||
lower_case_c == 'o' ||
lower_case_c == 'u') {
return 1;
}
return 0;
}
This function is_vowel takes a char and if it represents an upper case or lower case vowel in ASCII it returns 1 and returns 0 otherwise.
When both funcitons are implemented correctly you can run and test your code as follows:
1521 mipsy test_mips_no_vowels.s mips_no_vowels.s Enter a string: potato 3 vowels removed ptt 1521 mipsy test_mips_no_vowels.s mips_no_vowels.s Enter a string: We love MIPS! 4 vowels removed W lv MPS! 1521 mipsy test_mips_no_vowels.s mips_no_vowels.s Enter a string: xyz 0 vowels removed xyz 1521 mipsy test_mips_no_vowels.s mips_no_vowels.s Enter a string: AEIOUaeiou 10 vowels removedYou can use make(1) to build the provided C code:
make mips_no_vowels
You can use 1521 mipsy to run your MIPS code:
1521 mipsy test_mips_no_vowels.s mips_no_vowels.s
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest mips_revision_no_vowels
Revision Exercise: Create An add Instruction (PS)
Your task is to add code to this function in add.c:
// return the MIPS opcode for add $d, $s, $t
uint32_t make_add(uint32_t d, uint32_t s, uint32_t t) {
return 42; // REPLACE WITH YOUR CODE
}
The function make_add is given the operands for a MIPS add instruction .
Add code so that it returns the opcode for that instruction.
Reminder the bit pattern for MIPS add instruction is:
| Assembler | Description | C | Bit Pattern |
|---|---|---|---|
add $d, $s, $t
| add | d = s + t | 000000ssssstttttddddd00000100000
|
This is how your code should behave
./add 17 19 3 make_add(17, 19, 3) returned 0x02638820 ./add 9 27 12 make_add(9, 27, 12) returned 0x036c4820
Use make(1) to build your code:
make # or 'make add'
Assumptions/Limitations/Clarifications
You may define and call your own functions if you wish.
You are not permitted to change the
mainfunction you have been given, or to changeadd' prototype (its return type and argument types).
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest add
Revision Exercise: Print file contents (PS)
write a c program show_file so that,
given a single command line argument containing
the path to a file,
it reads and prints the contents of that file
to standard output.
For example:
cat sample.txt Hello, world! ./show_file sample.txt Hello, world! cat three_lines.bin one two three ./show_file three_lines.bin one two three
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest show_file
Revision Exercise: Print file contents using syscall wrappers (PS)
write a c program show_file_libc so that,
given a single command line argument containing
the path to a file,
it reads and prints the contents of that file
to standard output.
For example:
cat sample.txt Hello, world! ./show_file_libc sample.txt Hello, world! cat three_lines.bin one two three ./show_file_libc three_lines.bin one two three
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest show_file_libc
Revision Exercise: Copy File (PS)
Write a C program copy_file so that,
given two command line arguments —
the first being the path to a source file to be read,
and the second being the path to a destination file —
it copies the contents of the source file
to the destination file.
If the destination file already exists, it should be overwritten.
If the destination file does not exist, it should be created.
For example:
echo "Hello, world!" > sample.txt cat sample.txt Hello, world! ./copy_file sample.txt copy.txt cat copy.txt Hello, world!
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest copy_file
Revision Exercise: Remove the first half of a file (PS)
Computer viruses are pieces of code that infect computers and can corrupt data and replicate themselves. An example of this would be a virus that deletes the first half of files. For educational purposes only you'll be writing a c program to do this.
Write a C program halving_virus so that,
given one command line argument, a path to a file,
it removes the first half of the file. That is to say, if the source file
is four bytes long, bytes 2, 3 should be kept in the file and
bytes 0, 1 should be removed from the file.
Odd file sizes are to be rounded such that a source file that has 5 bytes
should only keep bytes 3, 4, 5.
If the size of the source file is less than or equal to one byte, your program should remove all contents of the file.
For example:
echo "Hello, world!" > sample.txt cat sample.txt Hello, world! ./halving_virus sample.txt Halved sample.txt cat sample.txt world! echo 1234 > five_bytes.txt cat five_bytes.txt 1234 ./halving_virus five_bytes.txt Halved five_bytes.txt cat five_bytes.txt 34 echo 123 > four_bytes.txt cat four_bytes.txt 123 ./halving_virus four_bytes.txt Halved four_bytes.txt cat four_bytes.txt 3
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest halving_virus
Revision Exercise: shred (PS)
This is a past exam question from 18s1
You have been given shred.c, which contains
a function shred that receives a
string in_path and a string out_path as input and does nothing.
}
When paper documents need to be destroyed, we would use a shredder to slice up the paper so that the text is no longer able to be reconstructed. With digital documents, simply removing them (e.g. via Unix's rm command), leaves the contents of the document on the disk where it could be recovered by scanning the raw disk (i.e. bypassing the file system). To render digital documents less likely to be available for discovery, it would be better to write random bytes over the top of the file containing the data.
In this question, you must write a function which takes the path of an input file and writes 64-byte blocks of "random" bytes for at least all of the bytes in the input file. Ideally, we would write these blocks over the top of the original file. However, we don't want to destroy each input file the first time you test your program, so we write the random blocks onto an output file with the suffix .out.
In this question, you must implement the void my_shred(char *in_path, char *out_path); function, which takes two parameters:
- in_path a file path you should open for reading
- out_path a file path you should open for writing
for the whole in_path file {
read a 64-byte block into a buffer
// may have < 64 bytes in buffer at end of file
overwrite the buffer with random characters from 'A'..'Z'
write the buffer to out_path
}
Hint: to create random byte from 'A'..'Z' use (rand () % 26) + 'A'
Note you do not need to error check. You can assume that the input files exist and can be opened and that you can open files for writing.
You should try and get your function to work with libc sys call wrappers first and then also try to write another version with stdio library functions too.
For example...
unzip shred_examples.zip xxd shred_examples/f0 00000000: 4865 6c6c 6f20 6576 6572 796f 6e65 0a Hello everyone. dcc -o shred shred.c shred_main.c ./shred shred_examples/f0 xxd shred_examples/f0.out 00000000: 444d 574a 4358 4554 415a 5257 4b4c 504d DMWJCXETAZRWKLPM 00000010: 465a 4c57 4b43 4858 4946 4657 5046 4653 FZLWKCHXIFFWPFFS 00000020: 5443 4459 4249 5244 4a4a 4154 5752 4945 TCDYBIRDJJATWRIE 00000030: 5154 4144 5648 4145 4f48 4345 4f4a 5949 QTADVHAEOHCEOJYI 00000040: 0a .
Note that you will get different random characters if you use different pathnames for the same file eg. ./shred shred_examples/f0 will give different random output to ./shred f0
No error checking is required.
Your function can assume each argument is always the pathname of an existing ordinary file.
Assume that the files could contain any byte.
Your program can not assume the file will fit in memory.
Your program can not assume the file will fit in an array.
Your solution must be in C only.
No error checking is necessary or required.
You are not permitted to run external programs. You are not permitted to use system, popen, posix_spawn, fork or exec.
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest shred
Revision Exercise: Create Borts File (PS-CR)
Write a C program, create_borts_file,
which takes 3 arguments:
- a filename,
- the beginning of a range of integers, and
- the end of a range of integers;
and which creates a file of this name containing the borts in the range provided. You can assume that the range will always be strictly ascending.
A bort is an unsigned two-byte big-endian integer (bort is a contraction of big-endian short).
The possible bort values are 0..65535, so each bort can be represented as a uint16_t, or
unsigned short. As borts are big-endian, they need to be written to the output
file with their most significant byte first, followed by the least significant byte.
This means for a number such as 0x1234, the first byte to be written should be 0x12, as it
is the most significant byte, followed by 0x34, the least-significant.
As a borts file is not a text file, we cannot use cat
to inspect its contents.
The linux utilities, xxd and od are good ways to print a binary file, as hexadecimal and
octal respectively. Note that the zero byte is printed first for each number here, as it is the most significant
byte in each bort.
For example:
dcc -o create_borts_file create_borts_file.c ./create_borts_file fortytwo.bort 40 42 ls -l fortytwo.bort -rw-r--r-- 1 andrewt andrewt 6 Nov 1 15:21 fortytwo.bort xxd fortytwo.bort 00000000: 0028 0029 002a .(.).* od fortytwo.bort 0000000 024000 024400 025000 0000006Another example, creating a file containing the five biggest borts possible:
./create_borts_file biggest.bort 65530 65535 ls -l biggest.bort -rw-r--r-- 1 andrewt andrewt 12 Nov 1 15:26 biggest.bort ./print_bytes biggest.bort xxd biggest.bort 00000000: fffa fffb fffc fffd fffe ffff ............We can give
od command-line options to decode borts, for example:
od --endian=big -t u2 -A d -w2 biggest.bort 0000000 65530 0000002 65531 0000004 65532 0000006 65533 0000008 65534 0000010 65535 0000012
Your program should print a suitable error message if given the wrong number of arguments, or if the file can not be created.
When you think your program is working you can use autotest to run some simple automated tests:
1521 autotest create_borts_file