PA from Scratch - Day 02

By ten of hearts

← Back

My original intention in using a blog to record the process of doing PA was to record some experiences, lessons, and interesting things summarized during the personal project. But so far, everything has been going relatively smoothly, without any points that troubled me too much. Therefore, in this article, I will simply introduce the functions accomplished so far.

So far…

Up to now, the hardware and software involved in my system are still relatively simple: the hardware aspect mainly simulates a simple implementation of registers and memory; the software level mainly implements the first half of a simple debugger.

CPU

The CPU (Central Processing Unit) is the important computing center of a computer. The various functions of the CPU can be called by software through the instruction set, and different instruction sets also correspond to different hardware architectures. In PA, the teachers very kindly provided the freedom to choose one of three different CPU instruction set architectures (x86, mips32, Risc-V32(64)) to implement, and I chose the Risc-V32 Instruction Set Architecture (ISA). It’s worth noting that ISA is neither hardware nor software, but a specification manual; the design of hardware and the writing of software both need to refer to the ISA.

However, for the current task (simple debugger), the choice of ISA is not that important, so I haven’t implemented any functions yet won’t go into more detail for now.

Registers and Memory

Registers are storage devices in computers used to store values related to computing as well as some calculation states. Generally speaking, registers have extremely fast read and write speeds, but their storage capacity is also very small. A register is a highly structured storage component: there are many storage locations holding special meanings, so in PA, we use a struct to implement a register.

Memory is a storage device used to store the data and instructions required during the computer’s running process. It has relatively fast read and write speeds, but also relatively small storage capacity (comparatively speaking). Memory is also a continuous physical storage space in the computer (excluding virtual memory), so in PA, we use an array to simulate memory.

I wonder if classmates who haven’t studied digital circuits have ever been curious about a question: what is the process like when a computer executes a program? Simply put, when we double-click a program on the computer, its binary program is loaded into memory.

A binary program is composed of many instructions, each of which can be further divided into two parts of information: opcode and operand. The opcode defines an instruction that needs to be executed by the CPU, and the operand is the object upon which the CPU executes the instruction, which can be an immediate value or an address. The specific format of the instruction and the specific definition and quantity of opcodes follow the design of the ISA, while how the CPU specifically executes these instructions is the content of the hardware designer’s work.

In brief, software programs, ISA, and hardware can be seen as having the following relationships.

1flowchart TD
2    A[Software Program: Programmer] --Compiler or Interpreter: ISA-->B[Binary Program: ISA]
3    B --CPU: Hardware Designer--> C[Program Execution]

Precisely because ISA encapsulates hardware functions into interfaces, programmers can design code that runs on all machines. At the same time, this also explains why an executable program compiled on an x86 platform cannot run on an arm platform.

After the binary program is loaded into memory, a special register–the PC (Program Counter)–will record the progress of the program’s execution, and will point to the position of the next instruction after one instruction finishes executing. The computer can then execute instructions one by one, thus running the programs we wrote.

It is worth mentioning that in the simple debugger project, the code provides a default program, and this program is quite hard to find. I looked for it for a long time and felt very broken annoyed. Let it be known.

SDB (Simple DeBugger)

SDB is the main program needing to be implemented in PA1. Debugging can help programmers specifically expose problems in the code, and its functions include: breakpoints, single-step execution, stepping in, stepping out, etc. Therefore, for PA, implementing a simple debugger is also very important.

In SDB, we mainly need to reproduce the following GDB instructions:

Command Format Description
Help help Print help information
Continue c Continue running the paused program
Quit q Exit NEMU
Step si [N] Step through N instructions and then pause execution. If N is omitted, defaults to 1.
Info Registers info r Print register states
Scan Memory x N EXPR Evaluate EXPR, use result as starting memory address, and output N consecutive 4-byte values in hexadecimal

We can directly read the binary form of the running instructions by reading the memory that stores the instructions, and thereby verify the correctness of the x command implementation. This is why I had to find the program loaded by default in SDB :-(

Tags: work cs

← Back