Operating System Experiment 5: Preliminary cognitive tasks of protection mode (help: how to use other commands to replace or simulate retf commands)

Source: Internet
Author: User
Tags clear screen

Ask the assembler experts for help:

In this experiment, you need to use the retf command to return the result after calling the door task. However, the yc09 compiler does not support the retf command. However, I cannot jump back correctly using the RET command.

Because I am not familiar with assembly, I still cannot solve the problem after trying a lot of methods. However, I had to directly modify the machine instruction code after compiling the code. I hope some passing experts and Daniel will tell me how to solve this problem without changing the compiler.

 

Use the retf command to report an error:

Pm32.c (123): Error c2065: 'retf': Undeclared identifier -- 209

 

Baidu once explained that the difference between RET and retf is as follows.

Ret-> pop IP
Retf-> pop IP
Pop CS

 

I tried to replace retf with Pop IP and pop CS, but the compiler reported an error for these two commands.

Error message:

Pm32.c (123): Error c2065: 'IP': Undeclared identifier -- 205
Pm32.c (124): Error c4606: impossible combination of opcode and oprands

 

Content of this experiment: In protection mode, according to the door task registered in gdt, jump to the door task without privilege conversion, print a message and return.

 

Steps for using a portal task:

1. Compile a test function that is used to test the door task. The function is to display a string. (It is best to test whether or not the code can be called directly after compilation)

2. Register a logstore task on gdt: You need to set four parameters, namely, sub, offset, number of parameters, and attribute.

(Because the data structure of the portal task is different from that of gdt, a new macro function needs to be defined in PM. H .)

3. Define a selection task pointing to the logstore task registered in gdt.

4. In protection mode, use call to select a sub-call door task through the door task.

 

The experiment code is as follows:

 

Code: Run. C (add a function to change ret to retf machine command: void ret_to_retf (byte * imgbuffer, int size), and call it in the compilefile function)

 

// File: Run. C <br/> // function: Compile the experiment code of the operating system, create IMG, generate the bochs configuration file, and run bochs. <Br/> // Note: The experiment code consists of a 16-bit pilot program and a 32-bit pilot program. <Br/> // place the 16-bit Bootstrap program in the first half of the boot sector, 0 ~ 79 bytes <br/> // 32-bit boot program is placed in the second half of the boot sector, 80 ~ 509 bytes <br/> // 510, 511 bytes put the boot program end mark: 0x55, 0xaa <br/> // run: Use the yc09 compiler to compile and run the program. <Br/> // prepared by Miao <br/> // time: </P> <p> # define fdisk_size 1474560 // image size: 1.4 MB </P> <p> // VM Settings <br/> char * pmsrc = <br/> "Megs: 32/N" <br/> "romimage: file = BIOS-bochs-Latest, address = 0xf0000/N "<br/>" vgaromimage: VGABIOS-elpin-2.40/N "<br/>" floppya: Drawing 44 = PM. IMG, status = inserted/N "<br/>" Boot: A/N "<br/>" log: PM. out/N "<br/>" Mouse: enabled = 0/N "<br/>" keyboard_mapping: enabled = 1, map = x11-pc-us.ma P/N "; </P> <p> // this function is used as a temporary solution because the yc09 compiler does not support long return instruction retf. <Br/> // when the retf command is required in the assembly code, use the ret nop command instead of the three consecutive commands. <br/> // After the code is compiled, call this function to change the machine instruction of the RET instruction to the machine instruction of the retf. <Br/> // imgbuffer: size of the compiled binary file: the size of the file in bytes <br/> // compare the Assembly with the machine command: ret = 0xc3 retf = 0xcb NOP = 0x90 <br/> void ret_to_retf (byte * imgbuffer, int size) <br/>{< br/> If (size <4) return; <br/> size-= 2; <br/> while (-- size) <br/> If (imgbuffer [size] = 0xc3) <br/> If (imgbuffer [size + 1] = 0x90 & imgbuffer [size + 2] = 0x90) <br/> {<br/> imgbuffer [size] = 0xcb; <br/> printf ("change a ret to retf. /n "); <br/>}</P> <p> // Compile the specified code file and place it in the specified Image Location <br/> // filename: name of the file to be compiled imgbuffer: saved to the image buffer <br/> // startindex: specify the starting position limitsize: The program size after compilation <br/> // isneed: if it is true, call the ret_to_retf function detection code and replace RET with the retf machine code <br/> int compilefile (char * filename, byte * imgbuffer, int startindex, int limitsize, bool isneed) <br/>{< br/> char * tempbuffer; // Save the temporary buffer of some Bootstrap programs </P> <p> // compile this Bootstrap program, put the result in tempbuffer <br/> int length = yc_compilecpp (& tempbuffer, filen Ame, 0, 0); <br/> If (length <= 0 | length> = limitsize) <br/>{< br/> printf ("file: some errors exist in % s or the file is too large (more than % d bytes): % d byte/N ", filename, limitsize, length); <br/> return 1; <br/>}< br/> printf ("file: % s compiled successfully, size: % d bytes. /N ", filename, length); </P> <p> If (isneed) <br/> ret_to_retf (imgbuffer + startindex, length ); </P> <p> // place this part of the boot program to the specified starting position in the image Boot Sector buffer <br/> memcpy (imgbuffer + startindex, tempbuffer, length ); <br/> free (tempbuffer); </P> <p> return 0; <br/>}</P> <p> int main (INT argc, char ** argv) <br/>{< br/> char * filepath = argv [0]; // current folder path <br/> char filename [max_path]; // used to cache various file names <br/> // remove the complete path of the executable file from the file name and retain the folder path <br /> For (INT I = strlen (filepath); filepath [I]! = '//'; I --) <br/> filepath [I] = '/0'; <br/> byte * imgbuffer = new byte [fdisk_size]; // image buffer </P> <p> _ start: <br/> // compile the 16-bit pilot program and place it in the first half of the boot sector, 0 ~ 79 bytes <br/> If (compilefile ("pm16.c", imgbuffer, 0, 80, false) <br/> goto _ restart; <br/> // compile the 32-bit boot program and place it in the second half of the boot sector, 80 ~ 509 bytes <br/> If (compilefile ("pm32.c", imgbuffer, 80,512-80-2, true) <br/> goto _ restart; </P> <p> // The end length of the fat guide sector [0th sectors] marked with 55 AA is 200 h (512) byte <br/> imgbuffer [510] = 0x55; <br/> imgbuffer [511] = 0xaa; // mark the boot end of a floppy disk </P> <p> // create an OS image PM. IMG <br/> If (yc_writefile ("PM. IMG ", imgbuffer, fdisk_size )! = Fdisk_size) <br/>{< br/> printf ("error occurred during file write: % S. /R/N ", filename); <br/> goto _ restart; <br/>}</P> <p> printf ("/n % s is created successfully. /N ", filename); </P> <p> // generate the virtual machine configuration file PM of the operating system. SRC <br/> yc_writefile ("PM. SRC ", pmsrc, strlen (pmsrc); <br/> // run the VM <br/> yc_winexec (strcat (strcpy (filename, filepath)," bochs.exe "), "-Q-f pm. SRC "); </P> <p> _ restart: <br/> printf ("/n click the Enter key to re-compile and run the program! /N "); <br/> while (getchar ()! = '/N'); <br/> goto _ start; <br/> return 0; <br/>}< br/>

 

 

Code: PM. H (a new macro (gate) is added for gdt in pm32.c)

// File: PM. h <br/> // function: Public header files of pm16.c and pm32.c <br/> // run: run.exe automatically compiles pm16.c and pm32.c, generates IMG, and CALLS bochs to run the program. <br/> // Note: Use yc09to compile the run.c file and generate the run.exe program. <br/> // check the effect, click press enter to compile and run again <br/> // prepared by Miao <br/> // time: 2010-2-3 </P> <p> // defines the gdt attribute <br/> # define da_32 0X4000 // 32-bit segment <br/> # define da_drw 0x92 // value of the read/write data segment <br/> # define da_drwa 0x93 // The value of the accessed data segment type <br/> # define da_cr 0x9a // run the readable code snippet attribute value <br/> # define da_c 0x98 // an existing executable readable code snippet attribute value <br/> // define the LDT attribute <br/> # define da_ldt 0x82 // Local Descriptor Table type value <br/> # define sa_til 0x4 // set Ti position 1, LDT Selection Sub-<br/> // defines the door attributes <br/> # define da_1_cgate 0x8c // 386 call the door type <br/> # define da_dpl0 0x00 // DPL = 0 </P> <p> typedefunsigned int t_32; // 4 bytes <br/> typedefunsigned short t_16; // 2 bytes <br/> typedefunsigned char T_8; // 1 byte <br/> typedefint t_bool; // 4 bytes <br/> typedef unsigned int t_port; // 4 bytes </P> <p> // storage segment descriptor/system segment descriptor <br/> struct descriptor // a total of 8 bytes <br/> {<br/> t_16 limit_low; // limit 2 bytes <br/> t_16 base_low; // base 2 bytes <br/> T_8 base_mid; // base 1 byte <br/> T_8 attr1; // P (1) DPL (2) dt (1) type (4) 1 byte <br/> T_8 limit_high_attr2; // G (1) D (1) 0 (1) AVL (1) limithigh (4) 1 byte <br/> T_8 base_high; // base 1 byte <br/> }; <br/> # define Descriptor (Bas, Len, ATTR) {/<br/> (LEN) & 0 xFFFF,/<br/> (BAS) & 0 xFFFF, /<br/> (BAS)> 16) & 0xff,/<br/> (ATTR) & 0xff,/<br/> (ATTR)> 8) & 0xf0) + (LEN)> 16) & 0x0f),/<br/> (BAS)> 24) & 0xff}/</P> <p> # define gate (slector, offset, dcount, ATTR) {/<br/> (offset) & 0 xFFFF, /<br/> slector,/<br/> (dcount) & 0x1f,/<br/> ATTR,/<br/> (offset)> 16) & 0xff,/<br/> (offset)> 24) & 0xff}/<br/>

 

 

Code: pm16.c

// File: pm16.c <br/> // function: Switch to protection mode and jump to a 32-bit code segment <br/> // description: I tried to write protection mode-related experiments only in the boot sector, so I reduced this program a lot. <Br/> // It only redirects to the protection mode, and other work is completed in pm32.c. <Br/> // pm16.c occupies only the first half of the boot sector 0 ~ 79 bytes. <Br/> // The pm32.c part is loaded to the memory 0x7c50. <Br/> // run: run.exe automatically compiles pm16.c and pm32.c, generates IMG, and CALLS bochs to run the program. <br/> // The prompt is displayed: compile the run.c file with yc09and generate the run.exe Program <br/> // modify the code in pm16.cand pm32.c. run run.exe directly and press enter to compile and run the program again. <br/> // prepared by Miao <br/>/Time: 2010-1-30 </P> <p> # define ycbit 16 // tell the compiler to compile the program in a 16-bit format <br/> # define ycorg 0x7c00 // tell the compiler, load the program at 7c00 <br/> # include "PM. H "</P> <p> // gdt boundary, which only redirects to the protection mode, the new gdt <br/> descriptor label_gdt [] = <br/> {<br/> // Segment Base Address segment boundary attribute <br/> Descriptor (0, 0, 0), <br/> Descriptor (0x7c50, 0 xfffff, da_cr | da_32), // 32-bit code segment (pm32.c), executable readable <br/> }; <br/> // select a child for gdt, set the Offset Value Based on the gdt boundary <br/> # define selectorcode32 8*1 // point to a 32-bit segment </P> <p> # pragma pack (1) <br/> struct gdt_ptr <br/>{< br/> unsigned short size; <br/> void * ADDR; <br/> }; <br/> # pragma pack () <br/> gdt_ptr gdtptr = {sizeof (label_gdt), (char *) label_gdt}; // segment boundary, base address </P> <p> ASM void main () <br/> {<br/> mov ax, CS <br/> mov ds, ax <br/> mov es, ax </P> <p> // clear screen <br/> mov ah, 06 h // screen initialization or upper volume <br/> mov Al, 00 h // Ah = 6, Al = 0 h <br/> mov BX, 1110 H // blue background color <br/> mov CX, 0 // upper left corner: (0, 0) <br/> mov DL, 4fh // 0th columns <br/> mov DH, 1fh // 0th rows <br/> int 10 h // display interruption </P> <p> lgdt gdtptr // load GDTR </P> <p> CLI/Guanzhong disconnected </P> <p> // open the address line A20 <br/> in Al, 92 h <br/> or Al, 00000010b <br/> out 92 h, Al </P> <p> // switch to the protection mode, set the PE bit of Cr0 to 1 <br/> mov eax, Cr0 <br/> or eax, 1 <br/> mov Cr0, eax </P> <p> // truly enters the protection mode <br/> jmp dword selectorcode32: 0x0 <br/>}</P> <p>

 

Code: pm32.c

// File: pm32.c <br/> // function: the 32-bit code segment in protection mode. The function is to load a new gdt, call the door task, and initialize the LDT, jump to the LDT local task <br/> // Description: 32-bit boot program is placed in the second half of the image Boot Sector, 80 ~ The program size cannot exceed the limit of 509 bytes <br/> // run: run.exe automatically compiles pm16.c and pm32.c, generates IMG, and CALLS bochs to run this program <br/> // prompt: Because yc09 cannot recognize the retf command, it is replaced by the ref command, add two NOP commands to the end. <Br/> // when run.exe is run, the RET machine script is automatically changed to the retf machine script. <Br/> // use yc09to compile the run.c file and generate the run.exe Program <br/> // effect. Click "enter" to compile and run the program again. <br/> // prepared by Miao <br/> // time: 2010-1-33 </P> <p> # define ycbit 32 // tell the compiler, compile the program in 32-bit format <br/> # define ycorg 0x0 // This value will generate address base offset for variable functions during compilation, set to 0 <br/> # include "PM. H "</P> <p> # define protecaddr 0x7c50 // The base address of the program that enters the protection mode </P> <p> ASM void ldtcode (); // partial code segment, jump from a 32-bit code segment to the <br/> ASM void codedest (); // door task <br/> ASM void dispstr ();/ /To display a string, set ESI to point to the string address first, EDI points to the start position of the string </P> <p> // LDT boundary <br/> descriptor label_ldt [] = <br/>{< br/> // Segment Base Address segment boundary attributes <br/> Descriptor (protecaddr, 0 xfffff, da_cr | da_32), // 32-bit code segment (pm32.c), executable readable <br/>}; <br/> // LDT select a child, set the Offset Value Based on the LDT limit in pm32.c <br/> # define selectorldtcodea 8*0 + sa_til // point to a 32-bit local task </P> <p> // gdt select child, set the Offset Value Based on the gdt boundary in pm32.c <br/> # define selectorcode32 8*1 // point to a 32-bit Segment segment for readable execution <br/> # define selectorvi Deo 8*2 // point to the first address of the video memory <br/> # define selectordata32 8*3 // point to a 32-bit segment. In this way, variables in the program can be read and written <br/> # define selectorldt 8*4 // point to LDT, use this to jump to the local task <br/> // door Selection Sub-<br/> # define selectorcallgatetest 8*5 // </P> <p> // gdt boundary. Note, this is different from gdt in pm16.c, after redirecting from pm16.c, the new gdt <br/> descriptor label_gdt [] = <br/>{< br/> // Segment Base Address segment boundary attribute <br/> Descriptor (0, 0, 0), <br/> Descriptor (protecaddr, 0 xfffff, da_cr | da_32), // 32-bit code segment (pm32.c), executable readable <B R/> Descriptor (0xb8000, 0 xFFFF, da_drw), // video address segment, readable and writable <br/> Descriptor (protecaddr, 0 xfffff, da_drw | da_32 ), // make the variables of the 32-bit code segment (pm32.c) read and write <br/> Descriptor (0, 0 xfffff, da_ldt), // local descriptor. The base address of the segment is the same as that of the 32-bit code segment, offset <br/> // select the number of sub-offset parameters attribute <br/> gate (selectorcode32, (t_32) & codedest, 0, da_386cgate | da_dpl0 ), <br/> // use selectorcode32 to select a sub-account. Therefore, the memory address is the base address (protecaddr) + function address offset <br/> }; </P> <p> # pragma pack (1) <br/> struc T gdt_ptr <br/>{< br/> t_16 size; <br/> void * ADDR; <br/>} gdtptr = {sizeof (label_gdt), (char *) & label_gdt + protecaddr}; // segment boundary, base address <br/> # pragma pack () </P> <p> char msg1 [] = "this is protect model. "; <br/> char msg2 [] =" this is gate task. "; <br/> char msg3 [] =" This is local model. "; </P> <p> // 32-bit code segment. jump from real-world mode to <br/> ASM void main () <br/>{< br/> lgdt Cs: gdtptr // load the new GDTR </P> <p> mov eax, selectorvideo <br/> MoV Gs, ax // video segment Selection Sub-(Purpose) <br/> mov eax, selectordata32 // make the variable of the 32-bit code segment (printplace) read and Write <br/> mov ds, ax </P> <p> // a string is displayed below (the protection mode information has been reached) <br/> mov ESI, & msg1 // source data offset <br/> mov EDI, (80*0 + 0) * 2) // target data offset. The screen contains 0th rows and 0th columns. <Br/> call dispstr </P> <p> // call selectorcode32: & codedest // test the function and directly jump to the test function codedest () <br/> call selectorcallgatetest: 0 // pass the test and jump to the test function codedest () </P> <p> // set the base address of the ldt on the gdt, then load the Local Descriptor (LDT) <br/> XOR eax, eax <br/> mov eax, & label_ldt + protecaddr <br/> mov word label_gdt + selectorldt + 2, ax <br/> SHR eax, 16 <br/> mov byte label_gdt + selectorldt + 4, Al <br/> mov byte label_gdt + selectorldt + 7, Ah </P> <P> mov ax, selectorldt <br/> lldt ax </P> <p> JMP selectorldtcodea: & ldtcode // jump to a local task <br/>}</P> <p> // door test function <br/> ASM void codedest () <br/>{< br/> // a string is displayed below (information about the arrival task is displayed) <br/> mov ESI, & msg2 // source data offset <br/> mov EDI, (80*1 + 0) * 2) // target data offset. The screen contains 2nd rows and 0th columns. <Br/> call dispstr </P> <p> RET // because yc09 does not support the retf command, <br/> NOP // Replace the three commands, <br/> NOP // The Machine commands that are detected and replaced with retf after compilation. <Br/>}</P> <p> // partial code segment, jumped from a 32-bit code segment <br/> ASM void ldtcode () <br/>{< br/> // a string is displayed below (the protected mode information has been reached) <br/> mov ESI, & msg3 // source data offset <br/> mov EDI, (80*2 + 0) * 2) // target data offset. The screen contains 1st rows and 0th columns. <Br/> call dispstr </P> <p> _ dead: <br/> JMP _ dead <br/>}</P> <p> // display a string. You must set ESI to point to the string address first, EDI points to the start position of the string <br/> ASM void dispstr () <br/> {<br/> mov ah, 14 h // blue background red letter (Ah = 14 h) <br/> // output strings one by one in a loop <br/> _ dispstr: <br/> mov Al, DS: [esi] // readable, to point to the current segment of msg1 with CS <br/> Inc ESI <br/> CMP Al, '/0' // determine whether the string ends <br/> JZ _ Stop <br/> mov GS: [EDI], ax <br/> Add EDI, 2 <br/> JMP _ dispstr <br/> _ stop: // display complete <br/> RET <br/>}< br/>

 

If you want to experiment with the above Code, please note:

 

 

 

1. download and install the yc09 compiler from Yang Xiaobing's blog. It takes about one minute to install the yc09 compiler.

2. Copy the run. C, PM. H, pm16.c, and pm32.c codes in this test to a folder used for an experiment.

3. Find bochs.exe, BIOS-bochs-Latest, VGABIOS-elpin-2.40, x11-pc-us.map in the directory yc09/examplefolder where yc09 is installed to copy the four files to the folder used for the test.

4. Compile and Run. C using yc09

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.