# CS23B001 - Lab 8 Report
## Q1
To convert 0.1 from decimal system to binary, we perform the following steps:
1. 0.1 x 2 = 0.2 -> Integer part: 0, Fractional part: 0.2
2. 0.2 x 2 = 0.4 -> Integer part: 0, Fractional part: 0.4
3. 0.4 x 2 = 0.8 -> Integer part: 0, Fractional part: 0.8
4. 0.8 x 2 = 1.6 -> Integer part: 1, Fractional part: 0.6
5. 0.6 x 2 = 1.2 -> Integer part: 1, Fractional part: 0.2
6. 0.2 x 2 = 0.4 -> Integer part: 0, Fractional part: 0.4
7. 0.4 x 2 = 0.8 -> Integer part: 0, Fractional part: 0.8
8. 0.8 x 2 = 1.6 -> Integer part: 1, Fractional part: 0.6
9. 0.6 x 2 = 1.2 -> Integer part: 1, Fractional part: 0.2
10. 0.2 x 2 = 0.4 -> Integer part: 0, Fractional part: 0.4
11. 0.4 x 2 = 0.8 -> Integer part: 0, Fractional part: 0.8
If we observe the integer parts, we get *00011001100...* with the sequence *1100* repeating indefinitely.
Therefore, 0.1<sub>ten</sub> is 0.00011001100110011...<sub>2</sub>
## Q2
To convert a decimal number to binary using IEEE 754 standard, we follow the below steps:
1. Convert 0.1<sub>ten</sub> to binary:
- From Q1, we found out that 0.1<sub>ten</sub> is 0.00011001100110011...<sub>2</sub>
2. Normalize the binary fraction:
- Using scientific notation, shift the binary point to the right until there's exactly one non-zero digit before the point.
- 0.00011001100110011...<sub>2</sub> = 1.1001100110011..<sub>2</sub> x 2<sup>-4</sup>
- Here, we define two terms:
- **Mantissa:** 1.1001100110011...
- **Exponent:** -4
3. Determine the Sign Bit:
- Since 0.1 is positive, the signed bit is 0.
4. IEEE uses an excess-127 biasing system, where:
- E = Actual exponent + 127
- Here, E = (-4) + 127 = 123
- Converting 123<sub>10</sub> to binary, 123<sub>10</sub> to 01111011<sub>2</sub> (8 bits)
5. Form the Mantissa (32 bits):
- IEEE stores only the fractional part (after the leading 1) in 23 bits:
- Mantissa = 10011001100110011001100
6. Assemble the IEEE 754 Representation:
| Sign (1 bit) | Exponent (8 bits) | Mantissa (23 bits) |
| :------------: | :-----------------: | :--------------------: |
| 0 | 01111011 | 10011001100110011001100 |
Thus, the IEEE 754 single-precision representation of
0.1<sub>ten</sub> in 32-bit format is: **0 01111011 10011001100110011001100**
## Q3
We perform the following steps to convert 0.2<sub>ten</sub> to binary using IEEE 754 standard:
1. Convert 0.1<sub>ten</sub> to binary:
0.2 * 2 = 0.4 -> Integer part: 0, Fractional part: 0.4
0.4 * 2 = 0.8 -> Integer part: 0, Fractional part: 0.8
0.8 * 2 = 1.6 -> Integer part: 1, Fractional part: 0.6
0.6 * 2 = 1.2 -> Integer part: 1, Fractional part: 0.2
0.2 * 2 = 0.4 -> Integer part: 0, Fractional part: 0.4
If we observe the integer parts, we get *0011001100...* with the sequence *0011* repeating indefinitely.
Therefore, 0.2<sub>ten</sub> is 0.0011001100110011...<sub>2</sub>
2. Normalize the binary fraction:
0.001100110011...<sub>2</sub> = 1.100110011...<sub>2</sub> x 2<sup>-3</sup>
**Matnisaa:** 1.1001100110011...
**Exponent:** -3
3. Determine the Sign Bit:
Since 0.2 is positive, the sign bit is 0
4. Apply the excess-127 biasing system:
E = (-3) + 127 = 124
124<sub>10</sub> = 01111100<sub>2</sub> (8 bits)
5. From the Mantissa:
Mantissa = 10011001100110011001100 (23 bits)
6. Assemble the IEEE 754 Representation:
| Sign (1 bit) | Exponent (8 bits) | Mantissa (23 bits) |
| :------------: | :-----------------: | :--------------------: |
| 0 | 01111100 | 10011001100110011001100 |
Thus, the IEEE 754 single-precision representation of
0.2<sub>ten</sub> in 32-bit format is: **0 01111100 10011001100110011001100**
7. Find the numerical exponent from the 8-bit exponent. Binary of **01111100** = **124**. This exponent is stored in bias-127 form as **124 - 127 = -3**.
8. Decoding the Mantissa:
1.100110011001100<sub>2</sub> is converted into decimal as 1 + 1x2<sup>-1</sup> + 0x2<sup>-2</sup> + 0x2<sup>-3</sup> + 1x2<sup>-4</sup> + ... $\approx$ 1.5999999046325684 $\approx$ 1.6
9. We combine the values using the formula:
Value = (-1)<sup>sign</sup> x significand x 2<sup>exponent</sup>
Here, value = (-1)<sup>0</sup> x 1.6 x 2<sup>-3</sup> = 1.6 x (1/8) = 0.2
## Q4
**Design:**
My floating-point representation will consist of three components:
1. **Sign bit:** 0 if the number if positive, 1 if the number is negative
2. **Exponent:** Represents the position of the decimal point
3. **Mantissa:** Represents the significant digits of the number
**Storage:**
We use three memory locations for each floating-point number:
1. 1 bit for the *Sign Bit*
2. 8 bits for the *Exponent*
3. 23 bits for the *Mantissa*
**Normalization:**
We normalize our numbers to have the form 1.xxx x 2<sup>y</sup>, where:
1. 1.xxx represents the *mantissa*
2. y represents the *exponent*
Since the leading digit in the normalized form is always 1 (*hidden bit*), we don't need to store it.
**Bias for Exponent:**
To handle both positive and negative exponents, we used a bias of 127, which basically means we add 127 to the current exponent.
*Stored exponent = Actual exponent + 127*
**Register-based Implementation:**
For floating-point numbers, we can use a **two-register** approach:
1. **Integer Register:** Stores the integer part of the numbet (before the decimal point)
2. **Fraction Register:** Stores the fractional part (after the decimal point)
**Register Specifications:**
1. **Integer Register:** 32-bit signed register
2. **Fraction Register:** 32-bit unsigned integer representing fractional values
- For the fraction register, we'll use a fixed-point representation where the value represents the fraction as if divided by 10<sup>n</sup>, where n is the number of decimal places we want to support.
- For example, with n=3, the fraction 0.391 would be stored as 391.
**Example:**
1. **5.391:**
- Integer Register: 5
- Fractional Register: 391
2. **3.012:**
- Integer Register: 3
- Fractional Register: 012 (To maintain precision, we use 3 decimal places for all numbers, hence we store 0.012 as 012 and not as 12)
**Floating-Point Addition using Registers:**
1. Add the integer registers
2. Add the fractional registers
3. Handle any overflow from the fractional part to the integer part
In our example:
1. **Add integer parts:** 5 + 3 = 8
2. **Add fractional parts:** 391 + 012 = 403
3. **Check for overflow:** Since 403 < 1000 (where 1000 represents 1.000), there's no overflow to handle
4. **Result:**
- Integer Register: 8
- Fractional Register: 403
- This gives us 8.403 which is the sum of 5.391 and 3.012
**Handling Overflow:**
1. Consider the addition of 5.9 and 3.2.
2. Integer: 5 + 3 = 8
3. Fractional: 900 + 200 = 1100 > 1000
4. Integer: 8 + 1 = 9 (Add the overflow)
5. Fraction: 1100 - 1000 = 100
6. **Result:** 9.1
## Q5
- The assembly code to add 2 floating point numbers and store the sum in a memory location is given below.
- Comments have been used to explain the functioning of the code.
- IEEE 754 single-precision floating-point addition has been manually implemented using integer registers due to the inability of my Ripes simulator to support floating-point instructions.
```
.data
num1: .word 0b00111101110011001100110011001101 # IEEE 754 representation of 0.1
num2: .word 0b00111110010011001100110011001101 # IEEE 754 representation of 0.2
result: .word 0 # Space to store the final result
.text
.globl main
main:
# Load the floating-point numbers (stored as integers)
la t0, num1
lw t1, 0(t0) # Load num1 into t1
la t0, num2
lw t2, 0(t0) # Load num2 into t2
# Step 1: Extract sign, exponent, and mantissa
li t3, 0x80000000 # Bit mask to isolate the sign bit
and t4, t1, t3 # Get the sign of num1 (t4 = sign1)
and t5, t2, t3 # Get the sign of num2 (t5 = sign2)
li t3, 0x7F800000 # Bit mask for the exponent bits
and t6, t1, t3 # Extract exponent of num1
srli t6, t6, 23 # Shift right to get the actual exponent value
and s7, t2, t3 # Extract exponent of num2
srli s7, s7, 23 # Shift right to get the actual exponent value
li t3, 0x007FFFFF # Bit mask for the mantissa
and s1, t1, t3 # Extract mantissa of num1
and s2, t2, t3 # Extract mantissa of num2
li t3, 0x00800000 # Adding implicit 1 at the start of the mantissa
or s1, s1, t3
or s2, s2, t3
# Step 2: Align exponents by shifting the smaller number
align_exponents:
beq t6, s7, add_mantissas # If exponents are equal, move to addition
blt t6, s7, shift_mantissa1
srli s2, s2, 1 # Shift right to align the mantissa
addi s7, s7, 1 # Increase the smaller exponent
j align_exponents
shift_mantissa1:
srli s1, s1, 1 # Shift the other mantissa instead
addi t6, t6, 1 # Increase the exponent
j align_exponents
# Step 3: Add or subtract the mantissas
add_mantissas:
add s3, s1, s2 # Adding mantissas (assuming both numbers have the same sign for now)
# Step 4: Normalize the result to fit IEEE 754 format
normalize:
li t3, 0x01000000 # Check if the result overflowed
bge s3, t3, shift_right
li t3, 0x00800000 # Check if the result is too small
bge s3, t3, pack_result
slli s3, s3, 1 # Shift left to normalize
addi t6, t6, -1 # Adjust exponent
j normalize
shift_right:
srli s3, s3, 1 # Shift right if needed
addi t6, t6, 1 # Adjust exponent
# Step 5: Pack the result back into IEEE 754 format
pack_result:
slli t6, t6, 23 # Put the exponent back in place
li t3, 0x007FFFFF # Mask to keep only mantissa bits
and s3, s3, t3 # Keep only the mantissa
or t0, t6, s3 # Combine exponent and mantissa
or t0, t0, t4 # Add the sign bit back
# Store the computed result
la t1, result
sw t0, 0(t1)
# Exit the program
li a7, 10 # Exit system call
ecall
```