LAB1 The main content of the experiment is familiar with the assembly, C language pointers and GDB debugging, as well as understanding the Jos start-up process and what to do, why do these processing
Physical memory allocation for a typical PC
An early 16-bit processor can address up to 1MB of memory space
And the area that can actually be used as RAM is from 0 to 640KB.
And from 640KB to 1MB where is reserved for special purposes, the most important is the BIOS
After upgrading to 32-bit, the low address of 1MB space is still reserved for the original purpose, should be forward-compatible
But now it's time to leave the BIOS at the top of the 32-bit address space.
The boot loader
After the BIOS starts, do some system check and initialization work, then will go to the disk to find boot sector, once found, the area is loaded into the memory specific location, after the load is completed, then jump to the location, that is, the control is transferred to the bootloader
The first sector of the disk are Boot.s and boot.c, start the Boot.s first, and then start the Bootmain function in the C file, and the kernel image starts with the second sector of the disk
Boot Loader is mainly doing two things:
- Converts from 16-bit real mode to 32-bit protected mode, which is implemented within the Boot/boot.s file
- Reads the kernel from the hard disk device and transfers control to the kernel
The following is the code in BOOT.S
As you can see, starting from the 0X7C00 address, the first is to initialize the stack segment register, and there is no kernel stack at the BIOS stage, so GDB has no way to use commands such as Next and step
Re-established kernel data segment registers after switching to 32-bit protected mode
Boot. s file has done two things mainly
- Switch to 32-bit mode
- Load the Bootmain function in the C file
Boot. C File after takeover control
Reads the kernel from the disk file into physical memory, then executes the entry function of the disk, which is to give control to the kernel
Note the following two paragraphs of code, the macro definition ELFHDR is actually a pointer to force an actual physical address into an elf pointer, that is, to put an elf-type structure to the address
A few questions from MIT
- Since when does the 32-bit mode start
Go to the Boot.asm file and switch to the 32-bit mode in the lower position.
From the above sentence, the previous address identification is changed, is no longer the CS:IP mode
- Last bootloader Instruction
The last line of code in the BOOTMAIN.C function
- Where is kernel's first instruction?
As can be seen from the above, the entry position of the kernel is the Elfhdr->e_entry function
And ELFHDR is a structure in the 0x10000 place, E_entry is a pointer, is a variable of the structure, so how much is not good-looking, can be disassembled to see where the specific
Starting position in 0x0010000c position
Make a breakpoint at that location, and look at what's specific.
And it's the same in Kern/entry.s.
The assembler code I first saw in the Boot.asm file was like this.
I started silly, always thought jump to the address is 0x10018, did not see the front there is a * number, actually 0x10018 location is a function pointer ...
- This question is answered in the next section.
The process of generating an elf file:
- Compile all C files first and generate a series of. o Files
- The linker combines all the. o files into a single binary image file
The first is a fixed-length elf header file, followed by some variable-length program headers, which list each application area that needs to be loaded, each containing contiguous code and data structures, and the well-known need to load the specific memory address
Bootloader is loaded directly at the given memory address without modification
Here is the objdump to the kernel information, these are the contents of the header file
In particular, VMA and LMA are important to note.
VMA is the virtual address, where the program wants to be loaded, and the LMA is the actual loaded address
In boot, VMA and LMA are the same
So why is the link address in kernel different from the load address?
The main reason is that the modern operating system usually runs in the high address of the virtual memory, while leaving the low address of the virtual memory to other programs
The reason for doing this is that the next experiment will reveal ...
For example, in the above kernel, the VMA of a program segment is in 0xf0100000 position, but some machines actually do not have so much memory
That is, the ability to use the CPU-provided memory mapping
There's a little experiment here.
is to look at the following phenomena in order to see what is the difference between a human mapping and a map
As shown, just leave bootloader, enter kernel to execute the first statement, and observe the ox00100000 position is all in the right place.
The following is the content of the previous two positions given before executing the sentence
Can see is not the same, 0xf0100000 content is random, no content
And the content of the 0x0100000 location is the kernel code
After executing a given line of code, it becomes the following result
The contents of the two locations are the same, that is, the artificial memory mapping is successful.
Next is the completion code problem
This code is changed inside the lib/printfmt.c
Because there are already 10 binary 16 in the notation, and so on,
Code reading issues
Ask what the following code means
It's actually quite simple, crt_pos represents the position of the cursor on the screen, and crt_size refers to the size of the entire screen.
If you find that the entire screen is currently full, move everything from line 2nd to the last line to the second line from the first line to the penultimate row, then empty the last line and write again
The following is a problem with the system stack
Initialize here
And the location is Bootstacktop, this value has been given in the following
Next is a series of introductions
Words than a picture, on the caspp!!!!!!
See the most clearly, every time a function is called, if the function has n parameters, then starting from the nth parameter, until the first argument, press the stack, and then press the return address into the stack
The caller's frame pointer is then pressed into the top of the stack, and the caller's frame pointer points to the top of the current stack, and the rest is the other specific work
In the I386_init function, there is a test system stack, Test_backtrace function, recursive call this function 5 times, observe what happens
First on the code
Called when X is 5, recursively calls 5 times
See the corresponding assembly code again
And the thought is the same, first put the caller's frame pointer on the stack, and then update the frame pointer, here is one more will ebx also press stack
Then the parameters of the function, the return address, a total of four times the stack, 32-bit system, the stack is a total increase of 16 bytes
The actual operation also validates this conclusion.
The difference between the stack pointers up and down two times is exactly 16 bytes
Supplemental BackTrace Procedures
Add a program that can display the frame pointer and return address of all functions of the first function from the beginning of the current program to the initial system start stack initialization, and 5 parameters
It's the same as the one in the previous Csapp, where the current frame pointer is where the caller's frame pointer is stored, which is equivalent to forming a chain
So go back along this chain and you'll find the original caller.
Here's a question of how to know who the original caller is, which needs to look at the assembly code
In other words, at the very beginning, the frame pointer is a null pointer, and the assignment is zero, so it's good to write
At the same time, Jos provides an interface Debuginfo_eip (addr, eipdebuginfo*) that, depending on the address of the given instruction, can find the number of rows of which function in which file the instruction belongs.
So you can write it down like this.
Make grade, 50 points scored 40 points, as if the program name output format is problematic, but the program must be written in the right
MIT 6.828-jos-xv6-lab1:booting a PC