How to set up smartphones and PCs. Informational portal
  • home
  • news
  • Creation of the operating system kernel. UNIX-like operating system: writing the kernel in C

Creation of the operating system kernel. UNIX-like operating system: writing the kernel in C

Semantic Core is a scary name that SEOs have come up with to refer to a fairly simple thing. We just need to select the key queries for which we will promote our site.

And in this article I will show you how to correctly compose the semantic core so that your site quickly reaches the TOP, and does not stagnate for months. It also has its own "secrets".

And before we move on to compiling the SY, let's take a look at what it is and what we should eventually come to.

What is the semantic core in simple words

Strange as it may seem, but the semantic core is a regular excel file, which contains a list of key queries for which you (or your copywriter) will write articles for the site.

For example, this is how my semantic core looks like:

I have marked in green those keywords for which I have already written articles. Yellow - those for which I am going to write articles in the near future. And colorless cells - this means that it will come to these requests a little later.

For each key request, I have determined the frequency, concurrency, and came up with a "catchy" heading. You should get about the same file. Now my SN consists of 150 keywords. This means that I am provided with "material" for at least 5 months in advance (even if I write one article a day).

Below we will talk about what to prepare for if you suddenly decide to order the collection of the semantic core from specialists. Here I will say briefly - you will be given the same list, but only for thousands of "keys". However, in SA, it is not quantity that is important, but quality. And we will focus on this.

Why do you need a semantic core at all?

And in fact, why do we need this torment? You can, after all, just write quality articles and attract an audience by this, right? Yes, you can write, but you won't be able to attract.

The main mistake 90% of bloggers make is just writing high-quality articles. I'm not kidding, they have really interesting and useful content. But the search engines don't know about it. They are not psychics, they are just robots. Accordingly, they do not put your article in the TOP.

There is another subtle point here with the title. For example, you have a very high-quality article on the topic “How to do business in a“ mordo book ”. There you describe everything about Facebook in great detail and professionally. Including how to promote communities there. Your article is the highest quality, useful and interesting article on this topic on the Internet. Nobody was lying next to you. But it still won't help you.

Why high-quality articles fly out of the TOP

Imagine that your site is not visited by a robot, but by a live inspector (assessor) from Yandex. He realized that you have the coolest article. And rukami put you in first place in the search results for the request "Promotion of the community on Facebook."

Do you know what happens next? You will fly out of there very soon. Because on your article, even in the first place, no one will click. People enter the request “Community promotion on Facebook”, and your headline is “How to do business in a“ mordobook ”correctly. Original, fresh, funny, but ... not on request. People want to see exactly what they were looking for, not your creative.

Accordingly, your article will idle to occupy a place in the TOP of the SERP. And a living assessor, an ardent admirer of your creativity, can beg the authorities as much as they want to leave you at least in the TOP-10. But it won't help. All the first places will be occupied by articles, empty, like the husks of seeds, which were copied from each other by yesterday's schoolchildren.

But these articles will have the correct "relevant" title - "Promoting the Facebook community from scratch" ( step by step, in 5 steps, from A to Z, free etc.) Offensive? Still would. Well, fight against injustice. Let's put together a competent semantic core so that your articles take the first places they deserve.

Another reason to start making up SJ right now

There is one more thing that for some reason people think a little about. You need to write articles often - at least every week, and preferably 2-3 times a week in order to gain more traffic and faster.

Everyone knows this, but almost no one does it. And all because they have "creative stagnation", "they can not force themselves in any way", "just laziness." But in fact, the whole problem is precisely in the absence of a specific semantic core.

I entered one of my basic keys - "smm" into the search field, and Yandex immediately gave me a dozen tips, what else might be of interest to people who are interested in "smm". I just have to copy these keys into a notebook. Then I will check each of them in the same way, and collect clues for them as well.

After the first stage of collecting SN, you should have a text document containing 10-30 wide basic keys, with which we will work further.

Step # 2 - Parsing Base Keys in SlovoEB

Of course, if you write an article for the request "webinar" or "smm", then a miracle will not happen. You will never be able to reach the TOP for such a broad request. We need to split the base key into many small queries on this topic. And we will do this with the help of a special program.

I am using KeyCollector but it is paid. You can use a free analogue - the SlovoEB program. You can download it from the official website.

The most difficult thing in working with this program is to configure it correctly. I am showing how to properly configure and use Slovoeb. But in that article, I focus on the selection of keys for Yandex Direct.

And here, let's take a step-by-step look at the features of using this program for compiling a semantic core for SEO.

First, we create a new project, and name it according to the broad key that you want to parse.

I usually give the project the same name as my base key so I don't get confused later. And yes, I will warn you of one more mistake. Don't try to parse all base keys at the same time. Then it will be very difficult for you to filter out “empty” keywords from gold grains. Let's parse one key at a time.

After creating the project, we carry out the basic operation. That is, we actually parse the key through Yandex Wordstat. To do this, click on the "Vorstat" button in the program interface, enter your basic key, and click "Start collection".

For example, let's parse the base key for my "contextual advertising" blog.

After that, the process will start, and after a while the program will give us a result - up to 2000 key queries, which contain "contextual advertising".

Also, next to each request there will be a "dirty" frequency - how many times this key (+ its word forms and tails) was searched per month through Yandex. But I do not advise you to draw any conclusions from these numbers.

Step # 3 - Collecting Accurate Key Frequencies

Dirty frequency won't show us anything. If you focus on it, then do not be surprised later when your key for 1000 requests does not bring a single click per month.

We need to bring out the pure frequency. And to do this, we first select all the keys found with checkmarks, and then click on the "Yandex Direct" button and start the process again. Now Slovoeb will search for the exact frequency of the request per month for each key.

Now we have an objective picture - how many times a request was entered by Internet users in the last month. Now I propose to group all key queries by frequency, so that it is more convenient to work with them.

To do this, click on the "filter" icon in the "Frequency" column! ", And specify - to filter out keys with the value" less than or equal to 10 ".

Now the program will show you only those queries, the frequency of which is less than or equal to the value "10". You can delete these queries or copy them for the future to another group of key queries. Less than 10 is very little. Writing articles for these queries is a waste of time.

Now we need to choose those keywords that will bring us more or less good traffic. And for this we need to find out one more parameter - the level of concurrency of the request.

Step # 4 - Checking Competitive Queries

All "keys" in this world are divided into 3 types: high-frequency (HF), mid-frequency (MF), low-frequency (LF). They can also be highly competitive (VC), medium competitive (SK) and low competitive (NK).

As a rule, HF requests are simultaneously received by VC. That is, if a request is often searched for on the Internet, then there are a lot of sites that want to promote it. But this is not always the case, there are happy exceptions.

The art of compiling a semantic core lies precisely in finding such queries that have a high frequency, and their level of competition is low. It is very difficult to determine the level of competition manually.

You can focus on indicators such as the number of main pages in the TOP-10, the length and quality of texts. the level of trust and particles of sites in the TOP of the issuance on request. All of this will give you some idea of ​​how tough the battle for positions is for this particular query.

But I recommend that you take advantage of service Mutagen... It takes into account all the parameters that I mentioned above, plus a dozen more that neither you nor I have probably even heard of. After analysis, the service gives the exact value - what is the level of competition for this request.

Here I checked the query "setting up contextual advertising in google adwords". The mutagen showed us that this key has a competitiveness of "more than 25" - this is the maximum value that it shows. And this query has only 11 views per month. So it definitely doesn't suit us.

We can copy all the keys we picked up in Slovoeb and do a bulk check in Mutagen. After that, we will only have to look at the list and take those requests that have a lot of requests and a low level of competition.

Mutagen is a paid service. But you can do 10 checks a day for free. In addition, the cost of verification is very low. For all the time I have worked with him, I have not yet spent even 300 rubles.

By the way, at the expense of the level of competition. If you have a young site, then it is better to choose queries with a competition level of 3-5. And if you have been promoting for more than a year, then you can take 10-15.

By the way, at the expense of the frequency of requests. We now need to take the final step, which will allow you to attract a lot of traffic even for low-frequency requests.

Step # 5 - Collecting Tails for Selected Keys

As it has been proven and verified many times, your site will receive the bulk of traffic not from the main keys, but from the so-called "tails". This is when a person enters strange keywords into the search box, with a frequency of 1-2 per month, but there are a lot of such requests.

To see the "tail" - just go to Yandex and enter your chosen keyword in the search bar. Here's what you will see roughly.

Now you just need to write out these additional words in a separate document and use them in your article. Moreover, you do not need to always put them next to the main key. Otherwise, search engines will see "over-optimization" and your articles will drop in the search results.

Just use them in different places in your article, and then you will receive additional traffic from them as well. I would also recommend that you try to use as many word forms and synonyms as possible for your main keyword query.

For example, we have a request - "Setting up contextual advertising". Here's how to reformulate it:

  • Customize = customize, make, build, run, run, enable, host ...
  • Contextual advertising = context, direct, teaser, YAN, adwords, cms. direct, adwords ...

You never know exactly how people will look for information. Add all these additional words to your semantic core, and use them when writing texts.

So, we collect a list of 100 - 150 keywords. If this is your first time compiling the semantic core, it may take you several weeks.

Or maybe well, break his eyes? Maybe there is an opportunity to delegate the preparation of the CL to specialists who will do it better and faster? Yes, there are such specialists, but you don't always need to use their services.

Should I order a CJ from specialists?

By and large, the specialists in compiling the semantic core will only take you steps 1 - 3 from our diagram. Sometimes, for a large additional fee, steps 4-5 will also be done - (collecting tails and checking the competitiveness of requests).

After that, they will give you several thousand keywords that you will need to work with in the future.

And the question here is, are you going to write articles yourself, or hire copywriters for this. If you want to focus on quality, not quantity, then you have to write yourself. But then it won't be enough for you just to get a list of keys. You will need to choose topics that you know well enough to write a quality article.

And this is where the question arises - why, then, are we actually needed specialists in SY? Agree, parsing the base key and collecting the exact frequencies (steps # 1-3) is not at all difficult. It will take you literally half an hour of time.

The most difficult thing is to select RF requests, which have low competition. And now, as it turns out, you need HF-NK, on ​​which you can write a good article. This is exactly what will take you 99% of your time working on the semantic core. And no specialist will do this for you. Well, is it worth spending money on ordering such services?

When the services of a specialist in CN is useful

It's another matter if you initially plan to attract copywriters. Then you do not need to understand the subject of the request. Your copywriters will not understand it either. They will simply take a few articles on this topic and compile their own text from them.

Such articles will be empty, squalid, almost useless. But there will be many of them. On your own, you can write a maximum of 2-3 high-quality articles per week. And the army of copywriters will provide you with 2-3 shit text a day. At the same time, they will be optimized for requests, which means they will attract some kind of traffic.

In this case, yes, feel free to hire a specialist in YA. Let them also compose TK for copywriters at the same time. But you understand, it will also cost some money.

Summary

Let's go over the main points in the article again to consolidate the information.

  • The semantic core is simply a list of keywords for which you will write articles on the site for promotion.
  • It is necessary to optimize the texts for the exact key queries, otherwise your even the highest quality articles will never go to the TOP.
  • SN is like a content plan for social media. It helps you not to fall into a "creative crisis" and always know exactly what you will be writing about tomorrow, the day after tomorrow and in a month.
  • To compile the semantic core, it is convenient to use the free Slovoeb program, you just need it.
  • There are five steps to compiling a CL: 1 - Selecting base keys; 2 - Parsing base keys; 3 - Collecting the exact frequency for requests; 4 - Checking the concurrency of keys; 5 - Collection of "tails".
  • If you want to write articles yourself, then it is better to make the semantic core yourself, for yourself. The CL compilers will not be able to help you here.
  • If you want to work for quantity and use copywriters to write articles, then it is entirely possible to involve delegate and compilation of the semantic core. If only there was enough money for everything.

Hope this tutorial was helpful to you. Save it to your favorites so as not to lose it, and share with your friends. Don't forget to download my book. There I show you the fastest way from zero to the first million on the Internet (extract from personal experience for 10 years =)

See you later!

Your Dmitry Novosyolov

Let's write a simple kernel that can be loaded with the x86 GRUB bootloader. This kernel will display a message on the screen and wait.

How does an x86 system boot?

Before we start writing the kernel, let's understand how the system boots and transfers control to the kernel.

In most of the processor registers, at startup, certain values ​​are already found. The register pointing to the address of instructions (Instruction Pointer, EIP) stores the memory address at which the instruction being executed by the processor lies. EIP defaults to 0xFFFFFFF0... Thus, x86 processors at the hardware level start working at 0xFFFFFFF0. This is actually the last 16 bytes of the 32-bit address space. This address is called the reset vector.

Now the chipset memory card ensures that 0xFFFFFFF0 belongs to a specific part of the BIOS, not RAM. At this time, the BIOS copies itself into RAM for faster access. Address 0xFFFFFFF0 will only contain an instruction to jump to an address in memory where a copy of the BIOS is stored.

This is how the BIOS code starts executing. First, the BIOS looks for a device to boot from, in a preset order. Looking for a magic number that determines whether the device is bootable (511th and 512th bytes of the first sector must be equal to 0xAA55).

When the BIOS finds a boot device, it copies the contents of the first sector of the device into RAM, starting at the physical address 0x7c00; then navigates to the address and executes the loaded code. This code is called bootloader.

The bootloader loads the kernel at a physical address 0x100000... This address is used as the starting address in all large kernels on x86 systems.

All x86 processors start in a simple 16-bit mode called real regime... GRUB bootloader switches mode to 32-bit protected mode by setting the lower bit of the CR0 register to 1 ... Thus, the kernel boots in 32-bit protected mode.

Note that in the case of the Linux kernel, GRUB sees the Linux boot logs and loads the kernel in real mode. The kernel automatically switches to protected mode.

What we need?

  • x86 computer;
  • Linux;
  • ld (GNU Linker);

Setting the entry point in assembler

As much as I would not like to limit myself to one C, I have to write something in assembler. We will write a small file on it that will serve as the starting point for our kernel. All it will do is call an external function written in C and stop the program flow.

How can we make sure that this code is exactly the starting point?

We will use a linker script that links the object files to create the final executable. In this script, we will explicitly indicate that we want to load data at 0x100000.

Here is the assembler code:

;; kernel.asm bits 32; nasm directive - 32 bit section .text global start extern kmain; kmain is defined in the c file start: cli; block interrupts mov esp, stack_space; set stack pointer call kmain hlt; halt the CPU section .bss resb 8192; 8KB for stack stack_space:

The first instruction, bits 32, is not an x86 assembly instruction. This is a directive to the NASM assembler to generate code for a processor running in 32-bit mode. In our case, this is not necessary, but generally useful.

The section with the code begins on the second line.

global is another NASM directive that makes source code symbols global. Thus, the linker knows where the start symbol is located - our entry point.

kmain is a function that will be defined in the kernel.c file. extern means the function is declared somewhere else.

Then comes the start function, which calls the kmain function and stops the processor with the hlt instruction. That is why we disable interrupts in advance with the cli instruction.

Ideally, we want to allocate some memory and point to it with a stack pointer (esp). However, it looks like GRUB has already done this for us. However, you will still allocate some space in the BSS section and move the stack pointer to its beginning. We use the resb instruction, which reserves the specified number of bytes. Immediately before calling kmain, the stack pointer (esp) is set to the desired location with the mov instruction.

Core in C

In kernel.asm, we made a call to the kmain () function. Thus, our "cish" code should start execution with kmain ():

/ * * kernel.c * / void kmain (void) (const char * str = "my first kernel"; char * vidptr = (char *) 0xb8000; // video mem begins here. unsigned int i = 0; unsigned int j = 0; / * this loops clears the screen * there are 25 lines each of 80 columns; each element takes 2 bytes * / while (j< 80 * 25 * 2) { /* blank character */ vidptr[j] = " "; /* attribute-byte - light grey on black screen */ vidptr = 0x07; j = j + 2; } j = 0; /* this loop writes the string to video memory */ while(str[j] != "\0") { /* the character"s ascii */ vidptr[i] = str[j]; /* attribute-byte: give character black bg and light grey fg */ vidptr = 0x07; ++j; i = i + 2; } return; }

All our kernel will do is clear the screen and print the string "my first kernel".

First, we create a vidptr pointer that points to the address 0xb8000... "Video memory" begins from this address in protected mode. For displaying text on the screen, we reserve 25 lines of 80 ASCII characters, starting at 0xb8000.

Each character is displayed not with the usual 8 bits, but 16. The first byte contains the character itself, and the second - the attribute-byte. It describes the formatting of a symbol, such as its color.

To display a green s character on a black background, we write this character in the first byte and the value 0x02 in the second. 0 means black background, 2 means green text color.

Here is the color chart:

0 - Black, 1 - Blue, 2 - Green, 3 - Cyan, 4 - Red, 5 - Magenta, 6 - Brown, 7 - Light Gray, 8 - Dark Gray, 9 - Light Blue, 10 / a - Light Green, 11 / b - Light Cyan, 12 / c - Light Red, 13 / d - Light Magenta, 14 / e - Light Brown, 15 / f - White.

In our kernel, we will be using light gray text on a black background, so our byte attribute will be 0x07.

In the first loop, the program outputs an empty character over the entire 80x25 zone. This will clear the screen. In the next cycle, characters from the null-terminated string “my first kernel” with an attribute byte equal to 0x07 are written to the "video memory". This will print the string to the screen.

Connecting part

We have to compile kernel.asm into an object file using NASM; then use GCC to compile kernel.c into another object file. Then they need to be attached to the executable bootable kernel.

To do this, we will use a bind script that is passed to ld as an argument.

/ * * link.ld * / OUTPUT_FORMAT (elf32-i386) ENTRY (start) SECTIONS (. = 0x100000; .text: (* (. text)) .data: (* (. data)) .bss: (* ( .bss)))

First, we will set output format as 32-bit Executable and Linkable Format (ELF). ELF is the standard binary file format for x86 Unix systems. ENTRY takes one argument specifying the name of the symbol that is the entry point. SECTIONS is the most important part. It defines the markup of our executable file. We define how the different sections should be connected and where to place them.

In parentheses after SECTIONS, a period (.) Represents the position counter, which is 0x0 by default. It can be changed, which is what we do.

We look at the next line: .text: (* (. Text)). An asterisk (*) is a special character that matches any file name. The * (. Text) expression means all .text sections from all input files.

Thus, the linker connects all sections of the object file code into one section of the executable file at the address in the position counter (0x100000). After that, the counter value will be equal to 0x100000 + the size of the resulting section.

Similarly, everything happens with other sections.

Grub and Multiboot

All files are now ready to create a kernel. But there is one more step left.

There is a standard for booting x86 kernels using a bootloader called Multiboot specification... GRUB will only boot our kernel if it meets these specifications.

Following them, the kernel should contain the header in its first 8KB. In addition, this header must contain 3 fields, which are 4 bytes:

  • magical field: contains magic number 0x1BADB002 to identify the kernel.
  • field flags: we don't need it, set it to zero.
  • field checksum: if you add it with the previous two, you should get zero.

Our kernel.asm will become like this:

;; kernel.asm; nasm directive - 32 bit bits 32 section .text; multiboot spec align 4 dd 0x1BADB002; magic dd 0x00; flags dd - (0x1BADB002 + 0x00); checksum. m + f + c should be zero global start extern kmain; kmain is defined in the c file start: cli; block interrupts mov esp, stack_space; set stack pointer call kmain hlt; halt the CPU section .bss resb 8192; 8KB for stack stack_space:

Building the core

Now we will create object files from kernel.asm and kernel.c and link them using our script.

Nasm -f elf32 kernel.asm -o kasm.o

This line will run the assembler to generate the kasm.o object file in ELF-32 format.

Gcc -m32 -c kernel.c -o kc.o

The -c option ensures that no hidden linking occurs after compilation.

Ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o

This will launch the linker with our script and create an executable called kernel.

Configuring grub and starting the kernel

GRUB requires the kernel name to match the pattern kernel- ... So rename the kernel. I named mine kernel-701.

Now put it in the directory / boot... This will require superuser rights.

In the GRUB config file grub.cfg add the following:

Title myKernel root (hd0,0) kernel / boot / kernel-701 ro

Don't forget to remove the hiddenmenu directive, if there is one.

Restart your computer and you will see a list of kernels with yours as well. Select it and you will see:

A UNIX-like operating system is interesting to parse, as well as to write your own kernel that will print a message. Well, shall we write?

UNIX-like operating system and booting an x86 machine

What is a UNIX-like operating system? It is an OS influenced by UNIX. But before we get into writing a kernel for it, let's see how the machine boots and transfers control to the kernel.

Most x86 processor registers have well-defined values ​​after power-up. The Instruction Pointer Register (EIP) contains the memory address for the instruction executed by the processor. EIP is hardcoded to the value 0xFFFFFFF0. Thus, the processor has clear instructions at the physical address 0xFFFFFFF0, which is essentially the last 16 bytes of the 32-bit address space. This address is called the reset vector.

The chipset memory card now ensures that 0xFFFFFFF0 maps to a specific part of the BIOS and not to RAM. Meanwhile, the BIOS copies itself to RAM for faster access. This is called shadowing. Address 0xFFFFFFF0 will only contain the instruction to go to the memory address where the BIOS copied itself.

Thus, the BIOS code begins to execute. The BIOS first looks for a boot device according to the configured boot device order. It looks for a certain magic number to determine if the device is bootable (bytes 511 and 512 of the first sector are 0xAA55).

After the BIOS detects the boot device, it copies the contents of the first sector of the device into RAM, starting at physical address 0x7c00; then navigates to the address and executes the code you just loaded. This code is called the bootloader.

The bootloader then loads the kernel at physical address 0x100000. Address 0x100000 is used as the starting address for all large kernels on x86 machines.

All x86 processors start in a simplified 16-bit mode called real address mode. The GRUB boot loader switches to 32-bit protected mode by setting the least significant bit of CR0 to 1. Thus, the kernel boots into 32-bit protected mode.

Note that if a Linux kernel is detected, GRUB will receive the boot log and boot the Linux kernel in real mode. And the Linux kernel will make the switch to protected mode.

What do we need?

  • x86 computer (of course)
  • NASM assembler
  • ld (GNU Linker)
  • Source

Well, it would be nice to have an idea of ​​how a UNIX-like OS works. The source code can be found in the Github repository.

Kernel entry point and launch

First, let's write a small file in x86 assembler that will be the starting point for starting the kernel. This file will call an external C function and then stop the program flow.

How do you make sure this code serves as the starting point for the kernel?

We will use a linker script that links the object files to create the final kernel executable. In this script, we will explicitly indicate that the binary file should be loaded at address 0x100000. This address is where the kernel should be.

Here is the assembly code:

;; kernel.asm bits 32; nasm directive - 32 bit section .text global start extern kmain; kmain is defined in C-file start: cli; interrupt block mov esp, stack_space; set stack pointer call kmain hlt; processor stop section .bss resb 8192; 8KB per stack stack_space:

The first bits 32 instruction is not an x86 assembly instruction. This is a directive for the NASM assembler that states that it must generate code to run on a processor running in 32-bit mode. This is not necessarily required in our example, but it is good practice to specify these things explicitly.

The second line starts with a text section. This is where we will place all of our code.

global is another NASM directive used to set source code symbols as global.

kmain is a custom function that will be defined in our kernel.c file. extern declares that the function is defined elsewhere.

The start function calls the kmain function and stops the CPU with the hlt command. Interrupts can wake the CPU from executing an hlt instruction. Therefore, we first disable interrupts using the cli instruction.

Ideally, you should allocate some memory for the stack and point to it using a stack pointer (esp). However, GRUB does it for us, and the stack pointer is already set. However, to be sure, we will allocate some space in the BSS section and put the stack pointer at the beginning of the allocated memory. To do this, we use the resb command, which reserves memory in bytes. After that, a label remains that points to the edge of the reserved memory chunk. Before calling kmain, the stack pointer (esp) is used to point to this space using the mov command.

Kernel in C

In kernel.asm, we made a call to the kmain () function. Thus, the C code will start executing in kmain ():

/ * * kernel.c * / void kmain (void) (const char * str = "my first kernel"; char * vidptr = (char *) 0xb8000; // video memory starts here unsigned int i = 0; unsigned int j = 0; / * this loop clears the screen * / while (j< 80 * 25 * 2) { /* пустой символ */ vidptr[j] = " "; /* байт атрибутов */ vidptr = 0x07; j = j + 2; } j = 0; /* в этом цикле строка записывается в видео память */ while(str[j] != "\0") { /* ascii отображение */ vidptr[i] = str[j]; vidptr = 0x07; ++j; i = i + 2; } return; }

* kernel.c

void kmain (void)

const char * str = "my first kernel";

unsigned int i = 0;

unsigned int j = 0;

/ * this loop clears the screen * /

while (j< 80 * 25 * 2 ) {

/ * empty character * /

vidptr [j] = "";

/ * bytes of attributes * /

vidptr [j + 1] = 0x07;

j = j + 2;

j = 0;

/ * in this loop, the line is written to the video memory * /

while (str [j]! = "\ 0") (

/ * ascii display * /

vidptr [i] = str [j];

vidptr [i + 1] = 0x07;

i = i + 2;

return;

Our kernel will clear the screen and print the string "my first kernel" to it.

First, we create a vidptr pointer that points to 0xb8000. This address is the start of protected mode video memory. Screen text memory is just a chunk of memory in our address space. Memory card screen I / O starts at 0xb8000 and supports 25 lines of 80 ascii characters each.

Each character element in this text memory is represented by 16 bits (2 bytes), not the 8 bits (1 byte) we are used to. The first byte must have an ASCII character representation. The second byte is the attribute byte. It describes the formatting of the symbol, including various attributes such as color.

To print a character with green on a black background, we store the character s in the first byte of the video memory address and the value 0x02 in the second byte.

0 is black background and 2 is green.

Below is a table of codes for different colors:

0 - Black, 1 - Blue, 2 - Green, 3 - Cyan, 4 - Red, 5 - Magenta, 6 - Brown, 7 - Light Gray, 8 - Dark Gray, 9 - Light Blue, 10 / a - Light Green, 11 / b - Light Cyan, 12 / c - Light Red, 13 / d - Light Magenta, 14 / e - Light Brown, 15 / f - White.

0 - Black, 1 - Blue, 2 - Green, 3 - Cyan, 4 - Red, 5 - Magenta, 6 - Brown, 7 - Light Gray, 8 - Dark Gray, 9 - Light Blue, 10 / a - Light Green, 11 / b - Light Cyan, 12 / c - Light Red, 13 / d - Light Magenta, 14 / e - Light Brown, 15 / f - White.

In our kernel, we will use light gray characters on a black background. Therefore, our attribute byte must be 0x07.

In the first while loop, the program writes an empty character with attribute 0x07 across all 80 columns of 25 lines. This clears the screen.

In the second while loop, the characters of the string "my first kernel" are written to a piece of video memory. For each character, the attribute byte contains the value 0x07.

Thus, the line will be displayed on the screen.

Connecting part

We compile kernel.asm and NASM into an object file and then use GCC to compile kernel.c into another object file. Now our task is to associate these objects with the executable bootable kernel.

To do this, we use an explicit linker script that can be passed as an argument to ld (our linker).

/ * * link.ld * / OUTPUT_FORMAT (elf32-i386) ENTRY (start) SECTIONS (. = 0x100000; .text: (* (. text)) .data: (* (. data)) .bss: (* ( .bss)))

* link.ld

OUTPUT_FORMAT (elf32 - i386)

ENTRY (start)

SECTIONS

0x100000;

Text: (* (. Text))

Data: (* (. Data))

Bss: (* (. Bss))

First, we set the output format of the executable to 32-bit executable (ELF). ELF is the standard binary file format for Unix-like systems on the x86 architecture.

ENTRY takes one argument. It specifies the name of the symbol, which should be the entry point of our executable.

SECTIONS is the most important part where we define the markup of the executable file. This specifies how the different sections should be combined and where they will be placed.

Within the curly braces following the SECTIONS statement, the period character (.) - represents the location counter.

The location counter is always initialized to 0x0 at the beginning of the SECTIONS block. It can be changed by assigning a new value to it.

As mentioned, kernel code must start at 0x100000. Thus, we have set the location counter to 0x100000.

Look at the following line .text: (* (. text))

The asterisk (*) is a special character that will match any file name. That is, the expression * (. Text) means all sections of the input .text from all input files.

Thus, the linker concatenates all the text sections of the object files into the text section of the executable file at the address stored in the location counter. The executable's code section starts at 0x100000.

After the linker places the text output section, the location counter is set to 0x1000000 + the size of the text output section.

Likewise, the data and bss sections are concatenated and placed on the location counter values.

Grub and Multiboot

Now all the files needed to build the kernel are ready. But since we intend to boot the kernel using GRUB, a little more is needed.

There is a standard for booting various x86 kernels using a bootloader called the Multiboot specification.

GRUB will only boot a kernel if it conforms to the Multiboot specification.

According to it, the kernel must contain the header within its first 8 kilobytes.

In addition, this header must contain an additional 3 fields:

  • magic number field: contains the magic number 0x1BADB002, to identify the header.
  • flags field: we don't need it now, just set its value to zero.
  • checksum field: when specified, should return zero for a sum with the first two fields.

So kernel.asm will look like this:

;; kernel.asm; nasm directive - 32 bit bits 32 section .text; multiboot spec align 4 dd 0x1BADB002; magic numbers dd 0x00; dd flags - (0x1BADB002 + 0x00); checksum. mh + f + kc must be zero global start extern kmain; kmain is defined in the external file start: cli; interrupt blocking mov esp, stack_space; stack pointer call kmain hlt; processor stop section .bss resb 8192; 8KB per stack stack_space:

; ; kernel. asm

; nasm directive - 32 bit

bits 32

section. text

; multiboot spec

align 4

dd 0x1BADB002; magic numbers

dd 0x00; flags

dd - (0x1BADB002 + 0x00); check sum. mch + f + ks should equal zero

global start

extern kmain; kmain is defined in an external file

start:

cli; interruption blocking

mov esp, stack _ space; stack pointer

call kmain

hlt; stopping the processor

When you start reading website promotion tutorials, it always starts with creating a semantic core. For beginners, this first step is the most difficult. In addition to the fact that it is not immediately clear what this semantic core is, it is not yet clear what purpose it has and how to create it correctly.

In this article, we will talk about how to correctly create the semantic core of the site. And also you will learn about what it is and why it is made. In fact, there is nothing complicated and difficult in the concept of a semantic core. Let's figure it out.

No one has yet answered the question of what the semantic core is in such simple words as we will do now. So, the semantic core of the site is a list of key phrases by which it will be promoted. Everything! The whole point of the concept in one short, clear sentence. And there is no need to muddy anything with clever terms.

If you go deeper into the term, then semantics is a science that deals with the semantic filling of lexical units. In simple terms, semantics studies the meaning of something. In SEO, the semantic core makes it possible to understand the meaning of the entire site, its any section or a single taken article. This becomes clear to the search engine, the visitor, all the developers who will work with the site.

The semantic core, without exaggeration, is the foundation of all progress.

How to use the semantic core and what it is for

The functions of the semantic core include the following aspects of website promotion:

  • The most important task of the semantic core is to understand the structure of the site and its fullness. Looking at it, you can imagine what sections the site will have, and what articles will be in each section. And thus, all the disadvantages and inconveniences of the structure are immediately visible, and they can be eliminated at an early stage.
  • Semantics defines the content vector. Thanks to a better understanding of the structure of the site, you can choose the most relevant and effective key phrases.
  • The semantic core is the content plan of the site for many years to come. Every time you need to write articles, you can look there and see what content was planned and in which section of the site it should be.
  • If you plan to promote your site on a paid basis, for example, through contextual advertising, then thanks to the semantic core, you can calculate the cost of promotion.

How to make a semantic core

First you need to decide where you will get the key phrases for the kernel. The best source for beginners is the Yandex WordPStat service, which shows how many times a month a particular query was entered into Yandex search. WordStat has a variety of useful features, such as filtering queries by region or device, viewing related queries, and more. And most importantly, it is completely free. More on this.

You can use a variety of paid programs, but WordStat is better suited for beginners, in view of its simplicity. In addition, it is suitable not only for Runet, where Yandex prevails. If you are promoting a site within the CIS, then you can safely use it, and the statistics on Google will be about the same.

The main essence of creating a semantic core is the collection of key phrases that somehow fit the topic of the site. They need to be formalized and systematized somehow. For this, spreadsheets, such as Excel, Google Doc spreadsheets, or similar are best suited.

And for greater efficiency, additional graphs can be added to the semantic core table:

  • Naturally, there should be a graph with the most key phrase.
  • Of course, the column with the name of the site section where this phrase will be used.
  • You can add a column with the titile and description meta tags and immediately write the title and description for the article using the specified key phrase. Firstly, it will be immediately clear what to write an article about, and secondly, then there will be no need to puzzle over and invent it.
  • You can make a column to indicate the number of characters in the article for a given key phrase in order to better understand the content plan.
  • If we are talking about promoting contextual advertising, you need to add the cost of advertising for each request.
  • Everything that should be needed can be safely written into the table of the sematic core. There is no template for this, so you can do whatever you want and it is convenient there.

Common mistakes when creating a semantic core

Now you know how to correctly create the semantic core of the site. Let's take a look at some of the common mistakes beginner SEOs make.

  • If the core provides for the division of the site into categories, then a common mistake is the creation of deep levels of nesting. The second level is recommended and no further. That is, you can create a heading, a sub-heading, and that's all, it is no longer possible to divide it further into smaller headings.
  • Newbies can ignore low-frequency requests, as they think that it is impractical to use them, they still will not bring a lot of traffic. But in fact, the opposite is true. For a new site, it is precisely low-frequency, non-competitive queries that are needed.
  • You cannot completely trust the service with which key phrases will be extracted. And newbies do just that. Machines can be wrong and choose the wrong one.
  • No need to create an article for the sake of a key phrase. If you find the phrases “urgently sell a house” and “sell a house quickly”, then there is no point in making two different articles for them.

This series of articles is devoted to low-level programming, that is, computer architecture, operating system design, assembly language programming and related areas. So far, two habrauzera are engaged in writing - and. For many high school students, students, and professional programmers, these topics turn out to be very difficult to learn. There is a lot of literature and courses on low-level programming, but it is difficult to get a complete and comprehensive picture from them. It is difficult, after reading one or two books on assembler and operating systems, to at least in general terms imagine how this complex system of iron, silicon and many programs - a computer - actually works.

Everyone solves the learning problem in their own way. Someone reads a lot of literature, someone tries to quickly switch to practice and understand along the way, someone tries to explain to friends everything that he is studying. And we decided to combine these approaches. So, in this course of articles, we will demonstrate step by step how to write a simple operating system. The articles will be of an overview nature, that is, they will not contain exhaustive theoretical information, however, we will always try to provide links to good theoretical materials and answer all questions that arise. We do not have a clear plan, so many important decisions will be made along the way, taking into account your feedback.

Perhaps we will deliberately lead the development process to a standstill in order to allow you and ourselves to fully understand all the consequences of a wrong decision, as well as hone some technical skills on it. So you shouldn't take our decisions as the only correct ones and blindly trust us. Once again, we emphasize that we expect readers to be active in discussing articles, which should strongly influence the overall development and writing of subsequent articles. Ideally, we would like to see some of the readers join in the development of the system over time.

We will assume that the reader is already familiar with the basics of assembly and C languages, as well as basic concepts of computer architecture. That is, we will not explain what a register or, say, random access memory is. If you do not have enough knowledge, you can always refer to additional literature. A short list of references and links to sites with good articles are at the end of the article. It is also desirable to be able to use Linux, since all compilation instructions will be given specifically for this system.

And now - more to the point. In the rest of the article, we will write a classic "Hello World" program. Our Hello World will turn out to be a little specific. It will not run from any operating system, but directly, so to speak, "on bare metal." Before proceeding directly to writing the code, let's figure out how exactly we are trying to do this. And for this you need to consider the process of booting your computer.

So, take your favorite computer and press the largest button on the system unit. We see a cheerful splash screen, the system unit beeps happily with a speaker, and after a while the operating system is loaded. As you understand, the operating system is stored on the hard disk, and here the question arises: how did the operating system magically boot into RAM and start executing?

Know this: the system that is on any computer is responsible for this, and its name - no, not Windows, pips your tongue - it is called BIOS. Its name stands for Basic Input-Output System, that is, the basic input-output system. The BIOS is located on a small microcircuit on the motherboard and starts immediately after pressing the large ON button. BIOS has three main tasks:

  1. Detect all connected devices (processor, keyboard, monitor, RAM, video card, head, arms, wings, legs and tails ...) and check them for operability. The POST program (Power On Self Test) is responsible for this. If vital hardware is not found, then no software will be able to help, and at this point the system speaker will squeak something sinister and the OS will not reach the OS at all. Let's not talk about the sad, suppose we have a fully working computer, rejoice and move on to examining the second BIOS function:
  2. Providing the operating system with a basic set of functions for working with hardware. For example, through BIOS functions, you can display text on the screen or read data from the keyboard. Therefore, it is called the basic I / O system. Typically, the operating system accesses these functions through interrupts.
  3. Launching the operating system loader. In this case, as a rule, the boot sector is read - the first sector of the information carrier (floppy disk, hard disk, CD, flash drive). The order of polling media can be set in BIOS SETUP. The boot sector contains a program sometimes called the primary boot loader. Roughly speaking, the bootloader's job is to start the operating system. The boot process of an operating system can be very specific and highly dependent on its features. Therefore, the primary bootloader is written directly by the OS developers and is written to the boot sector during installation. At the moment the bootloader starts, the processor is in real mode.
Sad news: the size of the bootloader should be only 512 bytes. Why so few? To do this, we need to familiarize ourselves with the device of the floppy disk. Here is an informative picture:

The picture shows the surface of a disk drive. The floppy disk has 2 surfaces. Each surface has ring-shaped tracks (tracks). Each track is divided into small, arched pieces called sectors. So, historically, a floppy sector has a size of 512 bytes. The very first sector on the disk, the boot sector, is read by the BIOS into the zero memory segment at offset 0x7C00, and then control is transferred to this address. The boot loader usually loads into memory not the OS itself, but another loader program stored on the disk, but for some reason (most likely, this reason is the size) that does not fit into one sector.And since so far the role of our OS is played by a banal Hello World, our main goal is to make the computer believe in the existence of our OS, even if only on one sector, and run it.

How does the boot sector work? On a PC, the only requirement for the boot sector is that its last two bytes contain the values ​​0x55 and 0xAA - the boot sector signature. So, it is already more or less clear what we need to do. Let's write the code! The above code is written for the yasm assembler.

section. text

use16

org 0x7C00 ; our program is loaded at 0x7C00

start:

mov ax, cs

mov ds, ax ; select the data segment



mov si, message

cld ; direction for string commands

mov ah, 0x0E ; BIOS function number

mov bh, 0x00 ; video memory page

puts_loop:

lodsb ; load the next character into al

test al, al ; null character means end of line

jz puts_loop_exit

int 0x10 ; call the BIOS function

jmp puts_loop

puts_loop_exit:

jmp $; eternal cycle



message:

db "Hello World!" , 0

finish:

times 0x1FE - finish + start db 0

db 0x55, 0xAA ; boot sector signature

This short program requires a number of important explanations. The org 0x7C00 line is needed so that the assembler (I mean the program, not the language) correctly calculates the addresses for labels and variables (puts_loop, puts_loop_exit, message). So we inform him that the program will be loaded into memory at the address 0x7C00.
In lines
mov ax, cs

mov ds, ax
the data segment (ds) is set equal to the code segment (cs), since in our program both data and code are stored in one segment.

Then the message “Hello World!” Is displayed character by character in the loop. The function 0x0E of interrupt 0x10 is used for this. It has the following parameters:
AH = 0x0E (function number)
BH = video page number (don't bother yet, specify 0)
AL = ASCII character code

At the line "jmp $" the program hangs. And rightly so, there is no need for her to execute extra code. However, in order for the computer to work again, you will have to reboot.

In the line "times 0x1FE-finish + start db 0", the rest of the program code (except for the last two bytes) is filled with zeros. This is done so that after compilation the boot sector signature appears in the last two bytes of the program.

We sort of figured out the program code, let's now try to compile this happiness. For compilation, we need, in fact, an assembler - the above mentioned

Top related articles