---
# System prepended metadata

title: CS23B001 - Lab 2 Report

---

# CS23B001 - Lab 2 Report

## Q1

```
#include <stdio.h>

void main() {
        int x = 0x12345678;
        char * c = (char *) &x;
        printf("%x %x %x %x\n", c[0], c[1], c[2], c[3]);
}
```
1. Output of the program is *78 56 34 12*
2. Therefore my machine is **Little-Endian**

---

## Q2

```
#include <stdio.h>

union Union {
        int num;
        char bytes[sizeof(int)];
};

void main() {
        union Union U;
        U.num = 0x12345678;

        if (U.bytes[0] == 0x78)
                printf("Little-Endian\n");
        else
                printf("Big-Endian\n");
}
```

The union data structure has 2 data types, an integer *num* and a character array *bytes*

---

## Q3

```
uint32_t swap_endian(uint32_t value) {
    return ((value >> 24) & 0x000000FF) |
           ((value >> 8)  & 0x0000FF00) |
           ((value << 8)  & 0x00FF0000) |
           ((value << 24) & 0xFF000000);
}
```

The above code converts a Little-Endian to Big-Endian and vice versa.

Output:
```
Original number:
Value: 0x12345678

After endian conversion:
Value: 0x78563412
```

---

## Q4

```
g++ -g -O0 -Wa,-aslh assembly.cpp
```
The above command compiles the *assembly.cpp* program with flags to generate debugging information and assembly output:

1. *-g*: includes debugging symbols
2. *-O0*: Disables compiler optimizations
3. *-Wa*: Converts assembly code to machine code
4. *-aslh*: Enables assembly listing, includes assembly instructions, adds source code as comments, and inclues high-level source interleaving

The assembly output displays a 9 page report in which the C++ code is converted into low-level CPU instructions with debugging aids such as *variable handling*, *function operations*, and *security and debug*.

---

## Q5

```
static inline uint32_t convert(uint32_t x)
{
    return (x >> 24) | (x >> 8 & 0xff00) | (x << 8 & 0x00ff0000) | (x << 24);
}

static inline uint32_t to_bigendian(uint32_t n)
{
    union {
        int i;
        char c;
    } u = {1};
    return u.c ? convert(n) : n;
}

static inline uint32_t to_littleendian(uint32_t n)
{
    union {
        int i;
        char c;
    } u = {1};
    return u.c ? n : convert(n);
}
```

1. 0x00ff0000
2. convert(n) 
3. n
4. n 
5. convert(n)

**Purpose of the code:** Convert endianness of 32-bit integers

**Working of code:**
1. This code converts 32-bit integers between big-endian and little-endian formats.
2. The *convert* function reverses the byte order of a 4-byte integer
3. The *union* checks if the system is little-endian
4. The *to_bigendian* function returns *convert(n)* if system is little-endian, else returns *n* 
5. The *to_littleendian* function returns *convert(n)* if system is big-endian, else returns *n* 

---

## Q6

```
#include <stdlib.h>

void f(void) {
    int *x = (int *) malloc(10 * sizeof(int));
    x[10] = 0;
}

int main(void) {
    f();
    return 0;
}
```

1. The code compiles without any errors.
2. However, we have allocated 40 bytes of memory to the *x* pointer. If we try to access x[10], it should lead to a *segmentation fault*.
3. On running 
```
valgrind --leak-check=yes ./above_program
```
the output is:
```
==124364== Memcheck, a memory error detector
==124364== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==124364== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==124364== Command: ./q6.out
==124364== 
==124364== Invalid write of size 4
==124364==    at 0x10916B: f (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364==    by 0x109180: main (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364==  Address 0x4a86068 is 0 bytes after a block of size 40 alloc'd
==124364==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==124364==    by 0x10915E: f (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364==    by 0x109180: main (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364== 
==124364== 
==124364== HEAP SUMMARY:
==124364==     in use at exit: 40 bytes in 1 blocks
==124364==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==124364== 
==124364== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==124364==    at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==124364==    by 0x10915E: f (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364==    by 0x109180: main (in /home/adithya/chamber_of_secrets/COA/CS23B001_Lab2/q6.out)
==124364== 
==124364== LEAK SUMMARY:
==124364==    definitely lost: 40 bytes in 1 blocks
==124364==    indirectly lost: 0 bytes in 0 blocks
==124364==      possibly lost: 0 bytes in 0 blocks
==124364==    still reachable: 0 bytes in 0 blocks
==124364==         suppressed: 0 bytes in 0 blocks
==124364== 
==124364== For lists of detected and suppressed errors, rerun with: -s
==124364== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
```

There are 2 errors observed:
a. *Invalid write* for x[10]
b. *Memory leak* as the allocated memory was not freed

4. The numbers like *==33836==* in Valgrind's output represent the process ID (PID) of the program being analyzed. They help in **Identification of distinct messages** and **Track debugging processes**

After adding *sleep(20)* to the code and running valgrind, the following output is observed on running
```
ps -ef | grep 33836
```

Output:
```
adithya@hades:~/chamber_of_secrets/COA/CS23B001_Lab2$ ps -ef | grep 33836
adithya   125445  125436  0 13:24 pts/1    00:00:00 grep --color=auto 33836
adithya@hades:~/chamber_of_secrets/COA/CS23B001_Lab2$ ps -ef | grep 33836
adithya   125458  125436  0 13:25 pts/1    00:00:00 grep --color=auto 33836
adithya@hades:~/chamber_of_secrets/COA/CS23B001_Lab2$ ps -ef | grep 33836
adithya   125460  125436  0 13:25 pts/1    00:00:00 grep --color=auto 33836
```
These numbers are PID (process ID) to identify each process which change everytime we ran the above command

---

## Q7

1. On running ``` addi x1, x0, 10 ``` the value of register *x1* changed from *0x00000000* to *0x0000000a*.
2. On running ``` addi ra, zero, 10 ``` the alias of register *x1* is changed to *ra* while value is changed to *0x0000000a*.
3. On running ``` f = (g+h) - (i+j); ``` using assembly code, we observe that the values of the registers used have been changed from *0x00000000* to the respective hexadecimal values assigned to them.