Step-by-step compilation process

This exercise is a tutorial that guides the student to generate executable files from source files. It requires the students to perform, step-by-step, all the code generation steps, including compilation, assembling, and linking.

Instructions

Perform the following program compilation process step-by-step, i.e., generating the assembly language code and then the object code for each source file and finally calling the linker to put all the object files together and produce the executable file named prog.x. You must use the clang-15 compiler and generate code for the RISC-V R32 architecture.

The program is composed of two source files: file1.c and file2.c. The following listings show the file contents.

extern void write(int __fd, const void *__buf, int __n);

int main(void) {
  const char str[] = "Hello World!\n";
  write(1, str, 13);
  return 0;
}
file1.c
extern int main(void);

void exit(int code) {
  __asm__ __volatile__(
    "mv a0, %0           # return code\n"
    "li a7, 93           # syscall exit (93) \n"
    "ecall"
    :             // Output list
    :"r"(code)    // Input list
    : "a0", "a7"
  );
}

void write(int __fd, const void *__buf, int __n){
  __asm__ __volatile__(
    "mv a0, %0           # file descriptor\n"
    "mv a1, %1           # buffer \n"
    "mv a2, %2           # size \n"
    "li a7, 64           # syscall write (64) \n"
    "ecall"
    :   // Output list
    :"r"(__fd), "r"(__buf), "r"(__n)    // Input list
    : "a0", "a1", "a2", "a7"
  );
}

void _start() {
  int ret_code = main();
  exit(ret_code);
}
file2.c

To perform this task, you must, first, create these two files (with their respective contents) on your computer.

Once the compilation is complete, you must:

  • Use the disassembler tool to inspect the contents of the object and executable files. You'll notice that it contains the sequence of instructions listed in the function write from file2.c and the names of functions main, _start, and write.
  • Compare the contents of file1.s assembly file with the output generated by the disassembling tool for the file1.o file.

Notes and Tips

  • Remember to use the RISC-V 32 compilation tools, otherwise you might not be able to correctly compile file2.c (Notice that this file contains assembly instructions for RISC-V processors).