Skip to main content

CS2100 Computer Organisation Notes

· 8 min read

P.S. The following information is based on various resources from the course CS2100 NUS, certain parts are adapted to include my comments and explanations for my better understanding & review. I will try to include source in relevant section as much as possible to honor the authors' work (Mainly Prof Aaron & Prof Colin & TA Alvin).

P.P.S Half way through the course, I decided to change the way I take notes and therefore the information contained here only cover the first few chapters of the module.


C

  • Read Array
// while-loop
int readArray(int arr[], int limit) {
int index, input;
printf("Enter up to %d integers, terminating with a negative integer.\n", limit);
index = 0; // Must remember to initialize to zero
scanf("%d", &input);
while (input >= 0) {
arr[index] = input;
index++;
scanf("%d", &input);
}
return index; // Which is the actual array size
}
// for-loop
int readArray2(int arr[], int limit) {
int index, input;
printf("Enter up to %d integers, terminating with a negative integer.\n", limit);
for (index = 0; index < limit; index ++) {
if (arr[index] < 0) {
break;
}
scanf("%d", &arr[index]);
}
return index - 1; // Which is the actual array size
}
  • Reverse Array
// iterative while-loop
void reverseArray(int arr[], int size) {
int left = 0, right = size - 1, temp;
while (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
// iteractive for-loop
void reverseArray2(int arr[], int size) {
int start, temp, end = size - 1;
for (start = 0; start < size / 2; start++) {
temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
end--;
}
}
// recursive
void reverseArray3(int arr[], int size) {
reverseArrayRec(arr, 0, size - 1);
}

void reverseArrayRec(int arr[], int left, int right) {
int temp;
if (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
reverseArrayRec(arr, left + 1, right - 1);
}
}
// recursive C-style : from TA Alvin CS2100
void reverseArray4(int arr[], int size) {
if (size <= 1) {
return;
} else {
temp = arr[0];
arr[0] = arr[size - 1];
arr[size - 1] = temp;
// Add 1 to array pointer => shift pointer by 4 bytes
// => move to next item in array, that is the new base
// => treat it as removing the front and back items,
// hence size - 2
reverseArray4(arr + 1, size - 2)
}
}

Sign extension

When we want to represent an n-bit signed integer as an m bit signed integer, where m > n. We do this by copying the sign-bit of the n-bit signed m - n times to the left of the n-bit number to create an m-bit number.

To show that sign extension is value-preserving, we can simply check two cases:

  • If the signed bit is 0, adding 0s to the left is similar to adding 0 to the right of a decimal point. It does not change the value.
  • If the signed bit is 1, adding 1s to the left seems to change the value, but not really. This is because the newly added 1s to the right of the newly added signed bit increases the value while the signed bit decreases the value of the number. This effectively cancels out the changes in value. E.g. Focusing on the value that signed bit and the extended signed bit portion, original: 1001 => -2**3 = -8, extended: 111001 => -2**5 + 2**4 + 2**3 = -8

Addition of two 1's complement number with decimal

  • Sign extend or pad zero to the end so that they are of equal length.
  • Invert all the bits for negative number to use addition.
  • If there is a carry out, add 1 to the result.
  • Check for overflow if the result is opposite sign of A and B.

Converting decimal numbers to fixed-point binary

When doing the rounding

  • 0.0000 is rounded to 0.000.
  • 0.0001 is rounded to 0.001.

Represent decimal value in IEEE 754 format

  • When converting the 32 bits to Hexadecimal, make sure that the signed bit is also included.

Bitwise operations

a = 001010
b = 101011
a | b = 101011
a & b = 001010
a ^ b = 100001
~a = 110101
a << 2 = 101000 # equivalent to a *= 4
a >> 2 = 001010 # equivalent to floor(b /= 4)

Special thing about XOR

x ^ x = 0
x ^ 0 = x

a = 00110
a = 00110
a ^ a = 00000

b = 00000
c = 00110
c ^ b = 00110

Swap without temporary variable, with bitwise operator

void swap(int *a, int *b) {
*a = *a ^ *b
*b = *a ^ *b # equivalent to *a ^ *b ^ *b = *a
*a = *a ^ *b # equivalent to *a ^ *b ^ *a = *b
}

MIPS Masking

Summary

  • andi/ori/xori use zero-extension to fill in upper 32 bits. The operation acts on all 32 bits.
andi x, 1 = x
andi x, 0 = 0
ori x, 0 = x
ori x, 1 = 1
nor x, 0 = ~x
xor x, 1 = ~x
xor x, 0 = x

Set bits 2, 8, 16 to 1 in b, a -> $s0, b -> $s1, c -> $s2

# 16th bit is outside the range of immediate, which is only 0 - 15th bit
# use intermediate registers for results
lui $t0, 0b1 # this sets the 16th bit
ori $t0, 0b0000000100000100 # this sets 0 - 15th bit
or $s1, $s1, $t0

Copy over bits 1, 3 of b into a

lui $t1, 0b1111111111111111
ori $t1, t1, 0b1111111111110101
and $s0, $s0, $t1 # clear the two bits from a
andi $t0, $s1, 0b0000000000001010 # get the two bits from b
or $s0, $s0, $t0 # copy the bits over

Make bits 2, 4 of c inverse of bits 1, 3 of b

xori $t0, $s1, 0b0000000000001010 # this invert and copy
andi $t0, $t0, 0b0000000000001010 # clear everything else
sll $t0, $t0, 1 # shift left to 2, 4
lui $t1, $t1, 0b1111111111111111 # clear out 2, 4 of c, 3 steps, lui, ori, and
ori $t1, $t1, 0b1111111111101011
and $s2, $s2, $t1
or $s2, $s2, $t0 # copy over to c

MIPS arithmetic

a -> $s0 b -> $s1 c -> $s2 d -> $s3

d = 6a + 3(b - 2c) d = 6a + 3b - 6c d = 3(2a + b - 2c) d = 3(2(a - c) + b)

sub $t0, $s0, $s2   # a - c
sll $t0, $t0, 1 # 2(a - c)
add $t0, $t0, $s1 # 2(a - c) + b
sll $s3, $t0, 2 # 4(2(a - c) + b)
sub $s3, $s3, $t0 # 3(2(a - c) + b)

MIPS tracing

add $t0, $s0, $ zero    # make a copy
lui $t1, 0x8000 # set t1 to 1 at MSB and 0 else where
lp: beq $t0, $zero, e # if t0 == zero, exit
andi $t2, $t0, 1 # t2 left with LSB
beq $t2, $zero, s # if t2 LSB == 0, s
xor $s0, $s0, $t1 # invert MSB
s: srl $t0, $t0, 1 # discard LSB
j lp # loop back
e: # exit

What happens when integer overflow in C

  • int is 4 bytes (in sunfire), which is 4 x 8 = 32 bits
  • the range is from -2,147,483,648 (-2^31) through +2,147,483,647(2^31 - 1)
  • This range comes from 32 bits 2s complement representation,
  • from 10000000000000000000000000000000 (smallest negative number)
  • to 01111111111111111111111111111111 (largest positive number)
  • when adding 1 to the largest positive number, it becomes the smallest negative number
  • adding another 1 will make it 10000000000000000000000000000001,
  • which is -2147483647, (literally add 1 to the decimal number)

For an n-bit sign-and-magnitude representation, what is the range of values that can be represented?

  • -(2^(n-1) - 1)
  • 2^(n-1) - 1

1s Complement

  • -x = 2^n - 1 - x (in decimal)
  • -x = 2^n - 1 - x + 1 (in decimal)
  • minus 1 because you want the largest possible values in that base

2s Complement

  • -2^(n - 1)
  • 2^(n-1) - 1
  • Adding A + B
  • Ignore the carry out of the MSB
  • Check for overflow. Overflow occurs if the carry in and the carry out of the MSB are different, or if result is opposite sign of A and B

CS2030/S Programming Methodology Overview

· 2 min read

P.S. The following information on CS2030/S Programming Methodology II is based on past experience and subject to changes. The purpose is to provide a rough idea of what is to come for prospective students so that one can prepare early if possible.

In the recent run of the module, "A module about abstractions" is Prof Henry's description for CS2030. Having the opportunity to be a lab tutor for this module, I think it is a very fair way to describe it.

ComponentsRemarks
Weekly labs (5%)- Need not complete the solution during lab
- Useful for checking concepts taught in lectures
- May need to refer to Java API for unfamiliar syntax
- It is perfectly normal to not be able to complete the labs or find them difficult during the lab sessions. This is partly because of unfamiliarity with Java APIs that are involved (e.g., use of Generics, Optionals, Streams)
Individual project (10%)- Two-part projects that require you to write small to medium scale programs
- Released during read week 1 & 2 (Or released incrementally throughout the semester)
- Difficulty lies in managing code complexity and adhering to design principles
- Strongly advised to start early and anticipate some serious work required to complete them on time
Practical assessment #1 in week 7 (15%)- 90 minutes levelized coding exercise
- Similar to lab exercises but tests all topics
Practical assessment #2 in week 12 (20%)- Similar to Practical 1, except in terms of difficulty
In-lecture quiz (5%)- Meant to test your understanding
Class participation and peer learning activities (5%)- Participate in posting/answering questions on Github issues
- Add notes on Github Wiki
Final exam (40%)- Structured questions that might involve writing of small Java programs to implement OOP design or other topics covered
- Format similar to PYPs but not really predictable as this depends on the setter

Updated as of: 28/4/2021

WordPress Tracking Number of Downloads

· 6 min read

Motivation

Dealing with WordPress again. What I want to achieve is for the documents(PDFs, Images etc) that I have on a WordPress site, the visitors will have to key in their information in order to download them. This way, the number of downloads per document(publication, in my case) and also the details of people who are downloading the documents can be recorded and analysed later on.

Process

My initial idea was to look for a free backend service which would serve to process API calls from my front-end. On the pages where I display the documents, I will have a form that collects visitor information before allowing download to happen. When information is collected, download will initiate and an API call will be made to communicate with the backend.

Front-end can be make up of a simple HTML form + Javascript for any data preprocessing. The issue I had was that even if I am able to find a free backend service, the POST API call that I make to that backend will contain authentication keys. Leaving API keys in plain javascript is definitely not a good idea. Although, I must say that there are many interesting Database-as-a-service that caught my attention. One of them is Quickmetrics. It provides free 10000 events per day and 5 metrics to track. No time limit and no credit card required. I will definitely check this out in the future. The documentation also seems to be straight to the point.

Ok, so sending request from Javascript may not be a good idea. The way to go will then be via PHP. There is plenty of opportunities to write PHP in WordPress and my first instinct was to check if there is a plugin available. I did not manage to find suitable ones and those form service plugins are mostly limited in their free versions. So the next step for me was to download a plugin that I used before to easily insert PHP code into a page: Post Snippets. It makes creating shortcodes fairly easy. Also, even if PHP is not used, it is still a good way to write some HTML/Javascript code that can be used in different pages.


My PHP code to render the front-end form is as follows:

Part 1: Copy and edit a html form template from W3 School
echo "<h3>Please tell us about you before downloading</h3>";

$html= <<<HTML
<form id="toolkit" method="post" action="">
<label for="name">Name:</label>
<input
type="text"
id="name"
name="name"
placeholder="e.g John"
required
maxlength="100"
minlength="1"
/>
<label for="email">Email:</label>
<input
type="email"
id="email"
name="email"
placeholder="e.g John@example.com"
required
/>
<label for="organisation">Organisation:</label>
<input
type="text"
id="organisation"
name="organisation"
placeholder="e.g Google"
maxlength="100"
minlength="1"
required
/>
<input type="hidden" id="publication" name="publication" value="" />
<input type="hidden" name="action" value="addDownload" />
<input type="submit" />
</form>
HTML;

echo $html;
Part 2: Copy and add in the style for the html form as well
$style = <<<STYLE
<style>
/* Style inputs, select elements and textareas */
input[type="text"],
select,
input[type="email"] {
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
resize: vertical;
}
/* Style the label to display next to the inputs */
label {
padding: 12px 12px 12px 0;
display: inline-block;
}
/* Style the submit button */
input[type="submit"] {
background-color: #4caf50;
color: white;
padding: 12px 20px;
margin-top: 10px;
border: none;
border-radius: 4px;
cursor: pointer;
float: right;
}
/* Style the container */
.container {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
/* Floating column for labels: 25% width */
.col-25 {
float: left;
width: 25%;
margin-top: 6px;
}
/* Floating column for inputs: 75% width */
.col-75 {
float: left;
width: 75%;
margin-top: 6px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
.col-25,
.col-75,
input[type="submit"] {
width: 100%;
margin-top: 0;
}
}
</style>
STYLE;

echo $style ;
Part 3: Add in JS logic to handle form submit

Two things I did here:

  • Submit the completed form via Ajax to "/wp-admin/admin-ajax.php" (my backend)
  • Trigger auto download of document by simulating clicking of downloable link to the document
$js = <<<JS
<script>
jQuery("#toolkit").submit(ajaxSubmit);
const submitBtn = document.querySelector("input[type='submit']");

// add title of publication as part of form
const title = document.querySelector(".blog-post-detail .inner h2").innerText;
const publication = document.querySelector("#publication");
publication.value = title;

function ajaxSubmit() {
// handle storing of data
var newDownloaderForm = jQuery(this).serialize();
jQuery.ajax({
type: "POST",
url: "/wp-admin/admin-ajax.php",
data: newDownloaderForm,
success: function (data) {
console.log(data);
submitBtn.value = "Thank You";
submitBtn.style.backgroundColor = "grey";
submitBtn.disable = true;
},
error: function (error) {
console.log(error);
submitBtn.value = "Something is wrong...please try again";
submitBtn.style.backgroundColor = "grey";
submitBtn.disable = true;
},
});

// handle auto downloading of files
const link = document.createElement("a");
link.href ="{link}";
link.download = "";
link.dispatchEvent(new MouseEvent("click"));

return false;
}
</script>
JS;

echo $js;

So that's all for the front-end. Not the best way to do things but it does the job. The last part of the puzzle is to setup the backend to receive the form and store data accordingly.

I honestly do not know WordPress well enough to find an alternative. So here, I will add my backend processing code in the current theme's functions.php file (accessible from Appearance -> Theme Editor -> functions.php). I am aware that if the theme changes, this code will no longer work but oh well...

Part 4: Add in PHP function to be triggered to save form data
// Add to the bottom of functions.php
// Added to deal with tracking of document downloads
// Every download will add a post of post type: downloader
// and it includes the form data
// https://stackoverflow.com/questions/43557755/how-to-call-ajax-in-wordpress
wp_enqueue_script('jquery');

function update() {
$new_post = array(
'post_title' => sanitize_text_field($_POST['publication']),
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'downloader'
);

// Insert the post into the database
$new_post_id = wp_insert_post( $new_post );
update_field('name', sanitize_text_field($_POST['name']) , $new_post_id);
update_field('email', sanitize_email($_POST['email']), $new_post_id);
update_field('organisation', sanitize_text_field($_POST['organisation']), $new_post_id);
update_field('publication', sanitize_text_field($_POST['publication']), $new_post_id);
}

// this is invoked when ajax call from front-end JS is invoked
// because of <input type="hidden" name="action" value="addDownload" />
// the ajax action(function) to call is specified in the form to be named "addDownload"
function addDownload() {
update();
echo "done";
}
add_action('wp_ajax_addDownload', 'addDownload');
add_action('wp_ajax_nopriv_addDownload', 'addDownload');

This is by no means a difficult task but I am really happy to actually know how to make an ajax call within WordPress.

Achievement unlocked!