Number Systems, Pointers, Arrays, and MIPS Registers

Number Systems

Data types:

  • int: 4 bytes
  • float: 4 bytes
  • double: 8 bytes
  • char: 1 byte

Format Specifiers:

  • %d: int
  • %f: float
  • %p: pointer
  • %c: char

Converting Base-R to Decimal

Example: 1101.102 = 1 * 23 + 1 * 22 + 0 * 21 + 1 * 20 + 1 * 2-1 + 0 * 2-2

Converting Decimal to Base-R

For Whole numbers: Repeated division by R until the quotient is 0. The remainders form the answer, with the first remainder being the least significant bit (LSB).

For Fractions: Repeated multiplication by R until the fractional part is 0. The carried digits form the answer, with the first carried digit being the most significant bit (MSB).

For numbers with both whole and fractional parts: Perform division on the whole number part and multiplication on the fractional part.


Representing Negative Numbers

Sign-and-magnitude: Uses a sign bit (1 for negative, 0 for positive).

1s Complement: -x = 2n – x – 1. Invert all bits of the positive representation.

2s Complement: -x = 2n – x. Invert all bits of the positive representation and add 1.

Difference in addition (1s & 2s): In 2s complement, ignore the carry-out bit.

Remember to check for overflow (if the result has the opposite sign of the inputs).

Positive numbers in 1s and 2s complement are the same as their binary representation.

Subtraction in 1s and 2s: Find the negative of the second operand and add.

Excess Representation: Example: Excess-4, 0000 represents -4, 0001 represents -3, etc.


Representing Real Numbers

Fixed point: The number of bits for the whole and fractional parts is fixed.

IEEE-754 Floating-Point Representation:

Single precision (32-bit): 1-bit sign, 8-bit exponent with bias 127 (Excess-127), and 23-bit mantissa.

Double precision (64-bit): 1-bit sign, 11-bit exponent with bias 1023 (Excess-1023), and 52-bit mantissa.

  • Sign: 0 for positive, 1 for negative.
  • Exponent: 127 + exponent from the normalized fraction (for single precision).
  • Mantissa: Normalized to 1.XXXX; XXXX is stored in the mantissa.

Example: 110.12 = 1.101 * 22. The mantissa is 101, and the exponent is 2 + 127 = 129.

Pointers and Functions

Syntax:

int a = 0;
int *a_ptr = &a;

*a_ptr = 10; (sets the value of ‘a’ to 10). a_ptr will return the address of ‘a’.

Incrementing pointer variables:

The increment depends on the data type the pointer refers to and its size in bytes:

  • char: +1
  • int: +4
  • float: +4
  • double: +8

Pass-By-Value: When variables are passed into a function, new variables are created to store the passed values. This means you cannot change the original variables outside the function.

Pass-By-Reference: When pointers are passed into a function, the new variable receives the address of the original variable. This allows modification of the original variable’s value within the function.

Function definition examples:

void functionDef(int *);
void functionDef(int *pointer);

Arrays

arr is equivalent to &arr[0] (the address of the first element).

Array assignment: Direct assignment of one array to another is not possible. To copy arrays, use a loop to copy each element individually.

Function passing: Array names represent the address of the first element. Therefore, arrays are passed by reference, allowing modification of array elements within a function.

Function definition examples:

int funDef(int arr[]);
int funDef(int *arr);

Strings

Strings are arrays of characters with a null terminator (\0) at the end.

Examples:

char str[4] = {'H', 'e', 'l', '\0'};
char str[] = "Hel";  // \0 is implicitly added

Structures

Structures can be assigned directly: box1 = box2;

Structures follow pass-by-value semantics. Passing a structure as a parameter copies the entire structure.

typedef struct {
    int length, width, height;
} box_t;

box_t box1; // Declaring a structure
box1.length = 1; // Assigning values

//Pointer to structure
box_t *box_ptr;
(*box_ptr).length = 1; //Accessing members using pointer
box_ptr->length = 1; // Alternative syntax using -> operator

Registers

MIPS General Purpose Registers: 32 registers, each holding 32 bits.

Instructions:

  • sll/srl: Shift Left Logical/Shift Right Logical. Can be used to multiply/divide by 2n.
  • and: Used for masking (placing 0s on bits to be ignored).
  • or: Used to force certain bits to 1 (placing 1s on bits to be set to 1).
  • nor: Returns 1 if both inputs are 0, otherwise returns 0. nor $t0, $t0, $zero implements a NOT function.
  • xor: Returns 1 if the bits are different.

Immediates are only 16 bits long. To get a 32-bit immediate:

  1. Use lui (load upper immediate) to set the upper 16 bits: lui $t0, 0xAAAA
  2. Use ori to set the lower 16 bits: ori $t0, $t0, 0xAAAA. Now, $t0 stores 0xAAAAAAAA.