# 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.