Submit Delphi "Chapter 3 Win32 Time and Space

xiaoxiao2021-03-31  191

Chapter III Win32 Time and Space

My old father looked at the little grandson who played toys, and then said to me: "This child is like an hour, I like to disassemble things, I have seen it." Think about me, I often take the toy car, a small alarm clock, music box, and so on, and I often have been reprimanded by my mother.

My first understanding of the basic principle of the computer is related to the music box I have ever. That is a comic book at high school, a white beard old man explaining the theory of the smart machine, a uncle who stays eight characters is talking about computer and music boxes. They said that the central processor of the computer is the row of music reeds used to pronounce in the music box. The computer program is the bump of the small cylinder in the music box, and the rotation of the small cylinder is equivalent to the central processor. The natural movement of the instruction pointer, and the tap-controlled bump control music reed vibration pronunciation is equivalent to the instruction of the central processor execution program. The music box makes a wonderful melody, which is the music spectrum performance of the craftsman. The computer has complex processing, which is implemented according to the programmer pre-prepared program. After going to college, I knew that white beard old man is the scientific master Tuling. His limited self motivated theory promotes the development of the entire information revolution, and the uncle's husband's uncle is the father of the computer. Nosman, Feng The computer architecture is still the main system of the computer. The music box is not white, the mother can be wrapping.

There is deep and simple understanding to create a deep and simple creation. This chapter we will discuss the basic concepts related to our programming in Windows 32-bit operating systems, establish the correct time and space in Win32. I hope that after reading this chapter, we can understand the procedures, processes, and threads, understand the principles of executive files, dynamic connection libraries, and running packages, see the truth of global data, local data, and parameters in memory.

Section 1 understanding process

Due to historical reasons, Windows is from DOS. In the Dos era, we have been only the concept of programs, but there is no process. At that time, there were only the regular army of the operating system, such as UNIX and VMS, etc., there were only the concept of the process, and the multi-process means that small machines, terminals, and multi-users also means money. Most of my time can only use relatively low-cost microcomputers and DOS systems, just start contacting processes and small machines when learning the operating system.

After Windows 3.x, Microsoft is only in the graphical interface operating system, and I am also the concept of formal facing multitasks and processes at this time. Previously under DOS, only one program can be executed at the same time, and multiple programs can be implemented at the same time at Windows, which is multitasking. While running a program in DOS, you cannot perform the same program, and under Windows, the same program can have more than two copies at the same time, and each running program copy is a process. More specifically, any program is run to generate a task, and each task is a process.

When the program and the process are placed together, you can think that the program is static, a typical program is a static code and data consisting of several DLL files by an Exe file or an EXE file. The process is an operation of the program, which is a dynamically running code and dynamically changed data in memory. When the static program requires running, the operating system will provide a certain memory space for this run, transfer the static program code and data into these memory spaces, and relocate the program's code and data, it is in this space. Internal execution program, there is a dynamic process.

Two copies running simultaneously with the same program means that there are two process spaces in the system memory, but their program function is the same, but in different dynamic changes.

From the time of the process run, the processes are executed simultaneously, and the professional terminology is called parallel execution or concurrent execution. However, this is mainly the operating system to give us the surface feeling. In fact, the processes are performed in time, that is, the procedures for performing the process of the process by turning the CPU. For a CPU, only one process in the same time is executed. The operating system is the behind-the-scene manipulator of the schedule process, which continuously saves and switches the current state executed in the CPU, so that every scheduling process is considered to be complete and continuous. Since the process is scheduled very fast, it is the feeling of the process to run at the same time. In fact, it is true that there is only a hardware environment in multi-CPU. Sowing of the thread section later, we will find that the truly process is running, and the process is more important to provide the process space. From the space occupied by the process, each process space is relatively independent, and each process runs in its own stand-alone space. A program includes both code spaces and data space, code, and data to occupy process space. Windows assigns actual memory for the data space required for each process, and generally uses sharing means for code space, map a program of one code to multiple processes of the program. This means that if a program has 100K code and requires 100K data space, it is a total of 200K process space, and the first time the operation system will allocate 200K process space, and the second operation of the running program When the process, the operating system only assigns 100K data space, and the code space shares the space of the previous process.

What is mentioned above is the basic time and space of the process in the Windows operating system. In fact, the 16-bit and 32-bit operating systems of Windows have great differences in the time and space of the process.

From time, the 16-bit Windows operating system, such as Windows 3.x, etc., process management is very simple, it is actually just a multi-tasking management operating system. Moreover, the operating system is passive to the scheduling of the task. If a task does not give up the processing of the message, the operating system must wait. Since the 16-bit Windows system is defective in management process, the CPU resources are fully occupied by a process. In that era, for 16 Windows can have the opportunity to schedule other tasks, Microsoft strongly praises developers who develop Windows applications are broad programmers, which makes them willing to write a few rows of grace gifts. Instead, Win32 operating system, such as Windows 95 and NT, etc., is the ability to have real multi-process and multitasking operating systems. The process in Win32 is completely scheduled by operating system. Once the process runs, the operating system will actively switch to the next process regardless of whether the process is still processing data. Strictly speaking, the 16-bit Windows operating system is not a complete operating system, while the 32-bit Win32 operating system is a true operating system. Of course, Microsoft will not say that Win32 makes up for 16 Windows shortcomings, but claims that Win32 has achieved a advanced technology called "preemptive multitasking", which is a commercial means.

From the space, the process space in the 16-bit Windows operating system is relatively independent, but the process can be easily accessible to each other's data space. Because these processes are actually different data segments in the same physical space, and improper address operations can easily cause errors to read and write, and make the operating system crash. However, in the Win32 operating system, each process space is completely independent. Win32 provides a 4G virtual for each process and is a continuous address space. The so-called continuous address space means that each process has the address space from $ 000000 to $ fffffff, instead of the segments of 16-bit Windows. In WIN32, you don't have to worry about your read and write operations unintentionally affect the data in other process space, nor do you have to worry about nothing to harass your work. At the same time, Win32 provides a continuous 4G virtual space provided by your process. It is the operating system to map the physical memory to you with the support of hardware. Although you have such a broad virtual space, the system will never waste a byte. Physical memory. Second section process space

When we write Win32 applications with Delphi, rarely care about the internal world of the process at runtime. Because Win32 provides 4G continuous virtual process space for our process, the largest application in the world may only use part of the space. It seems that the process space is infinite, but the 4G process space is virtual, and the actual memory of your machine may be far from this. Although the process has such a vast space, some complex algorithms are still unable to operate because stack overflows, especially programs that contain a large number of recursive algorithms.

Therefore, in depth, understand and understand the structure of these 4G process space, and its relationship with physical memory, etc., will help us understand the Win32's time and space, which can be used in actual development work. The worldview and methodology solve a variety of problems.

Below, we will understand the internal world of Win32's process space through simple experiments. This may require some knowledge of CUP registers and assembly languages, but I try to illustrate it with a simple language.

When starting Delphi, a project1 will be automatically generated, and we will take it with it. Set a breakpoint in any location of the Project1.dpr's original program, for example, set a breakpoint at BeGin. Then run the program, which is automatically stopped when the program is running to the breakpoint. At this time, we can open the CPU window in the debug tool to observe the internal structure of the process space. The current instruction pointer register EIP is stopped in $ 0043E4B8, the maximum number of two 16-based number of addresses where the address where the program instruction is located, can be seen that the current program is in the address location of the 4G process space, which occupies $ 00000000 to $ Fffffff is a quite little address space.

In the instruction box in the CPU window, you can view the contents of the process space. When you look at the space content less than $ 00400000, you will find a string of question marks "????", because the address space is not mapped to the actual physical space. If you are at this time, you will find that it is also $ 00400000 for the 16-enumerated value of the global variable Hinstance. Although Hinstance reflects the handle of the process instance, it is the start address value that the program is loaded into the memory, as is the same in the 16-bit Windows. Therefore, we can think that the procedure is loaded from $ 00400000, that is, the space from 4M in the 4G virtual space begins to be a space loaded.

From $ 00400000, it is primarily the address space of the program code and the global data before the $ 0044d000. In the stack box in the CPU window, you can view the address of the current stack. Similarly, you will find the address space of the current stack from $ 0067B000 to $ 00680000, with a length of $ 5000. In fact, the smallest stack space size is $ 5000, which is obtained by adding $ 1000 based on the MIN STACK SIZE value set in the Linker page in Project when compiling the Delphi program. The stack is grown by the high-end address to the bottom end. When the stack of the program is not enough, the system will automatically increase the size of the stack space to the ground address direction, which will map more actual memory to process space. When compiling the Delphi program, control the maximum stack space can be increased by setting the value of the Max Stack Size in the Linker page in Project. In particular, in a program containing deep subroutine calls or using a recursive algorithm, it must reasonably set the value of the max stack size. Because the calling subroutine requires a consumption stack space, and after the stack is exhausted, the system will throw "Stack Overflow" error. It seems that the process space after the stack space should be free space. In fact, Win32's related information said that the 2G space after $ 80000000 is the space used by the system. It seems that the process can really have only 2G space. In fact, the process can really have the space that is 2G, because the 4M space from $ 000000 to $ 00400000 is also a restricted area.

But no matter what, our process can be used very vast. In particular, the stack space is between $ 80000000, the main battlefield of the process space. The process from the system allocated memory space will be mapped to this space, the process loaded dynamic connection library will be mapped to this space, and the thread stack space of the new thread will also map to this space, almost all related to allocation of memory. Both will be mapped to this space. Please note that the mapping here means that the actual memory and the virtual space correspondence, the process space that is not mapped to the actual memory is unused, just like the string of the CPU window instruction box when debugging " ???? ".

Section 3 EXE and DLL

We have a certain understanding of the process and process space. Here we will discuss the difference between the execution of the file EX and the dynamic connection library DLL, and the relationship with the process space.

Typical Windows applications are generally consisting of an EXE file and several DLL files. The Windows operating system itself is this structure, which is a well-known content. However, do you really understand EXE and DLL? If you are convinced that you are well known for the connotation of Exe and DLL, skip this section. If you haven't finished EXE and DLL, please listen carefully.

A correct EXE file is a program that can be run directly. The Windows operating system creates a process space for the program, and the program is running within the process space. The process space is the basic environment of the application running, and there is no program in the process space.

In the exe file, the program's data reference relationship and process call relationship is represented by the relative address. When the program is loaded into the absolute address in the process space, the operating system needs to adjust the reference and call relationship of the relative address to the absolute The address of the address is referred to as "relocation". The place where relocation is called a relocation item, which is stored in the header information of the EXE file.

The operation of the program is a need for stack because the stack is the basic facility that must be available in the process call. It is also a place where the local data and process parameters are dead. The operating system determines the address location and size of the stack space based on the stack size value recorded in the EXE file head, and first maps the part of the memory space. If, an Exe program has a fixed reference relationship with some DLLs, and the operating system will transfer the relevant DLL programs to the current process space. The reference or call relationship between EXE and DLL and DLL is described in the introduction table and the extraction table, which also saves the header information of the file of the EXE or DLL. The operating system connects the reference and call between the program module based on the introduction table and the introduction table information, which is called "dynamic connection".

A DLL file is just a part of the program, which is not a complete executable program. Therefore, the DLL cannot be run separately, and Windows will not create a process space for the DLL module. A DLL module must be loaded into a process space for an Exe program to exert its programming.

A DLL file also contains relocation information, and the operating system then loads the DLL module to relocate the DLL module. If the loaded DLL has a fixed reference relationship with other DLL files, the DLL module is loaded and the DLL module is loaded simultaneously and the running motion connection process is completed.

The stack size recorded in a DLL file is always zero because the DLL is just a process service, and when calling the DLL module, use the stack of the process. For single-threaded applications, only one stack is only a stack used by the main thread of the process. For multi-threaded applications, each running thread has its own stack. In the case of multi-thread, the DLL module is called in that thread, and the DLL uses the stack of the thread. But all this is still in the same process space.

If you use the Windows API's LoadLibrary function to dynamically load a DLL file, the value of the module handle is to point to the address value of the DLL loaded into the process space. If you repeatedly call LoadLibrary loading the same DLL, you will find that the module handle value they returned is the same, and Windows only adds the DLL reference count. In fact, between different Windows processes, the DLL is shared, just, there are different mapping addresses in different process spaces.

The file extension of a DLL module is not necessarily * .dll. Like the Delphi's BPL package file, the ActiveX object's OCX file, and the DRV and VXD files of the device driver are DLL. Of course, the file extension of an EXE module is not necessarily * .exe, just, non-* .exe executable can not be executed by double-click the mouse, need to be transferred and run by writing program statements.

The DLL can only be running within the process space, this is a basic principle, please keep in mind.

But sometimes, a DLL itself in Windows is already a complete program that lacks the running process space. At this time, Windows uses the Rundll32 command to run the DLL program. Rundll32 is a simple EXE file, in the Windows directory, which only provides runoffs for DLL programs.

In addition, in the development of multilayer architecture applications, the business objects in the DLL module are also required to run the process. If, your client application and DLL application server are in the same machine, the business object in the DLL application server is running in the process space of your client program, which is the in-process mode. For Out-of-Process object call modes, the application server is generally required to be an executable EXE file.

Of course, if the application server and client program are in different machines, the application server must have a process space to work. For example, you cannot connect DLL application servers on remote machines through direct DCOM, because DLL has no running process space. However, you can connect the DLL application server on the remote machine via Socket because the DLL is actually running in the process space of SCKTSRVR.exe, while Scktsrvr.exe is a service program that listens to the Socket connection. In MTS mode distributed multi-layer application development, all business objects must exist in the application server of the DLL file. The commercial objects in these DLLs are common in the MTS process space, so MTS can scheder and manage these business objects in their own process space to complete powerful features such as transaction control, object buffer, and connection sharing.

Section 4 Where is the data and code?

Where is the data and code?

As the saying goes, people will be thirty years old, and will not think about "why people are alive?" These issues. But I have compiled more than a dozen years or like "why do I want to compile?", Why do you want to run? "," Is the program or my thoughts? " . . . . . Although I have already gone. This kind of thinking is never result, which is just the most wasteful life in the program career. This kind of suffering is also sent, often makes my soul more integrated into the world. The program has my soul, and the personality running seems to have my style. I have benefited from me, and there is my program.

Today, you will have the problem of data and code of everyone. This topic is still inseparable from the concept of processes, because all code and data of the program exist in the process space. So what are the data and code in the process space?

Let's take a look at what areas in the process space.

A process space, the area related to our programming has roughly there are such four: static data area, dynamic data area, stack area and code area. There are several memory areas such as several blocks in the process space, which is dynamically changed as the program runs. There is a new area for a while, and some areas will disappear. If the process space is imagined into the sea, these memory areas are the islands in the sea, with the tide of the tide, the island is hidden. Each island has an actual memory of operating system maps as reliance. The blank area without mapping the actual memory is deeply seen in the bottom of the bottom, and the program is accessible to these blank areas to be drowned.

These four memory areas have each use. The static data area is where you define global variables, constants, thread variables, and the like. The dynamic data area is where you dynamically allocated data space and dynamically created object survive. The stack area provides a subspace that stores the returned address for the sub-program call, and provides temporary space for local variables, parameter variables, and return values. The code area is the area of ​​the storage program instruction, and the CPU is to extract the instruction from here to execute the program.

The generation and disappearance of these memory regions and the loading and unloading of the program module, and the creation of threads is related to demise.

What we are here is here to refer to the physical file module of the Windows application, namely the module concept represented by the HMOdule handle in Windows. Typically, the EXE file is a module file, and various DLL files are also a module file. An application is typically consisting of an Exe file and several types of DLL files. This file is called a PE file in Windows (Portable Executable file). It contains a PE information head, which is important information that loads the program module.

When a physical file module is loaded into a process space, the Windows operating system will arrange the data of the module according to the information of the module PE header, and the size of the code in the process space. Such loading includes execution loading of the EXE program, also includes timely loading the DLL in time, and the program subsequently loads the DLL process.

The module is loaded into the process space, which will generate several still data regions required by the module, and will also generate a number of instruction code regions of the module. If the module is dynamically allocated and released during the operation, the dynamic data area will be generated and released accordingly. You can think that the code area of ​​the module is fixed, because the general code does not change during the execution (unless you are writing a variant function ...), this will not affect the understanding of the execution process. But the code area of ​​the module may also be changed frequently, which is the ghost behind Windows.

Imagine load a program module with a few togas or dozens of mega code into the process space, is the program's startup speed slow? Will this create a huge code area in the process space? It is possible, but Windows will try not to happen. When the CPU is used to use an instruction of a block code area, the code area is transferred from the disk file into the process space and executes. At the same time, if some code blocks have not been executed for a long time, it will release the memory space occupied by these code spaces. When these released code is again used by the CPU, the code will be loaded again (of course, the location of the load may vary). Therefore, even if it is loaded and running a huge module file, the speed will not be significantly reduced, and the space will not increase significantly.

Imagine, if a module file is loaded, the file will be taken away, and Windows can also correct the code to use from the disappeared file. Of course! Therefore, when the Windows loads the module file, it is forced to lock the file, and you can't modify and delete it. Unless the module is loaded is the module on the floppy disk, you have to force the floppy drop away.

Similarly, the creation and release of threads also cause changes in memory regions. When thread is created, the Windows system opens two memory regions for this thread in the process space. One is a global static data area relative to the thread, one is a stack area required for thread run. Among them, the stack area is the basic facility that thread runs must be in close correlation. A thread will have a stack, and a stack must correspond to a thread. After a thread is released, its related static data area and stack disappear.

The static data area of ​​the module is generally where you define global variables, constants, etc. The access addresses of these data elements are relative to the module. That is, these data elements identification methods and structural relationships are programs relative to the module. Other module programs outside the module are programs that cannot directly identify and interpret these data elements defined in this module unless the address of these data elements is passed from the module to other modules. For example, let's take a look at the two module programs below:

Program exemodule;

Function Thevariable: Pointer; External 'DLLModule.dll';

Begin

// avariable: = 56789; // cannot directly identify and access data elements in another module.

Integer (thevariable ^): = 56789; // You can only access its data elements by accessing the address from another module.

End.

This program will generate an Exemodule.exe module file after compiling. Of course, it needs DLLModule.dll when it starts.

Library DLLModule;

VAR

Avariable: integer;

Function thevariable: Pointer;

Begin

Result: = @ avariable;

END;

Exports thevariable;

Begin

Avariable: = 12345;

End.

The second program will generate a DLLModule.dll module file after compiling it after it is compiled. Although a global variable Avariable is defined in the DLLModule module, the program of the Exemodule module cannot directly identify and find the variable. You can only access the Avariable variable after the Avariable address pointer is obtained by calling the DLLModule module. Have a friend, if you put avariable in a separate Pascal unit file, then use this unit in the main program of the two modules, can you visit each other? Let's take a look at these program files below.

This is a Varunit.PAS unit file:

Unit varunit;

Interface

VAR

Avariable: integer;

IMPLEMENTATION

End.

This is an exemodule.dpr file, which will generate an exemodule.exe file:

Program exemodule;

Uses

Varunit;

Begin

Avariable: = 56789;

End.

This is a dllmodule.dpr file, which will generate a DLLModule.dll file:

Library DLLModule;

Uses

Varunit;

Begin

Avariable: = 12345;

End.

These two modules reference Varunit units. If the two modules are in the same process space, then the Avariable variable accessed in the Exemodule module and the Avariable variable accessed in DLLModule really the same variable?

the answer is negative!

It turns out that the Avariable variable accessed in Exemodule is in the static data area of ​​its own module, and the Avariable variable accessed in DLLModule is also all of themselves. Although the module references variables in the same unit, these variables have a separate copy in different modules. In the discussion of the running package compilation mode, we will also discuss the problem of shared unit variables.

Therefore, we have to remember: In non-running compilation mode, various global variables and objects in Delphi, such as Application, Screen, Session, Printer, etc., there is a copy of your own in every EXE and DLL modules. Not the same thing.

So, what is the global variable relative to the thread?

Thread global variables are global variables defined with extended reserved word Threadvar. Threadvar can only be used to define global variables and cannot be used to define local variables. The global variables it defined have a copy in each thread, exists in the global static data area of ​​their respective threads. Thread variables defined with Threadvar are unique to each thread, and can be used with confidence within the thread. The global variable defined using the VAR reserved word is thread sharing, and it is necessary to pay attention to sharing and mutually exclusive issues.

Next we want to discuss partial variables, parameter variables, and return values.

These three types of data elements are some things on the sub-process or function, and the scope is only temporary in the subroutine. They are self-destruction in the thread's stack area. As the subroutine call is generated in the stack, we will die as the return of the subroutine call. The thread's stack area is challenged with the in-depth and returning of the subroutine layer, which is growing and reduced. Local variables, parameter variables and return values ​​are like small creatures on the reef, and there will be a batch of life birth, and they will die. When the tide is coming, it is another new life world, and there is no memory from the world. Life may be like this.

In a program containing a recursive algorithm, the thread's stacked area will have a very interesting phenomenon. There will be many amazing similarities in the history of growth in the stack area. Every recursive call, a group of similar partial variables, parameter variables, and return values ​​will appear once, and the stack growth is very fast. Therefore, pay attention to the problem of stack space when writing a program containing a recursive algorithm. Let's take a look at the situation in the dynamic data area.

Almost all objects in Delphi are existing in the dynamic data area. Although their object pointers may be a global variable, a thread global variable, a local variable, a parameter variable, or a return value, but the object's instance is allocated in the dynamic data area (unless you overload TOBJECT classes Method NewInstance, allocate the object instance space in other parts).

This situation in Delphi is not the same as the standard C . When a global object is defined in standard C , its instance exists in a global static area of ​​the program. Delphi is to create dynamically when the program is running, for example, created in the code of the unit file initialization section.

In the early programming concept, dynamically allocated data area is also called "heap". At that time, because the machine's addressable space is small, "heap" often and "stack" share a piece of space. The part of this space starts to grow downwards is "heap", and the part starting from the bottom is called "stack". So, this space is collectively referred to as "stack". Now the programming space is very broad, the concept of "stack" seems to have been outdated, and the "stack" is closely linked to the concept of multi-threaded. Therefore, the word "stack" is now used in the stack used by the specified thread.

Finally, let's take a look at the code.

In Delphi, a module file of an EXE or DLL is generally compiled by a project file (* .dprise) and several direct or indirectly referenced unit files (* .pas). In the absence of optimizing compilation options, writing all code and data in the project file and unit files are compiled into the physical module file. If you open the compiled optimization option, only the code and data used are compiled into the physical module file.

Typically, your application consists of multiple physical file modules, typically consisting of an EXE module and several DLL modules. When we write module programs, there are always some units to be shared. The shared unit is referenced in a module's compilation project and is referenced during the compilation process of another module. Unfortunately, the code and data in the module share cells will be compiled in each of the modules that reference the unit. These modules of the application are loaded into the process space, and the unit's code instructions and data will exist multiple copies.

Although we can independently, we can compile a DLL module to share a copy of code and data. But this will make the division of the program module become very complicated, and it is difficult to manage, it is difficult to travel during the actual development process.

Now, we have basically clear the problem of where the data and the code will be. As I said, such exploration and thinking are a bitter road. Because, we understand some truth in hard thinking, but there will be new problems. This world is always perfect!

Delphi's great place is that she can make many complex problems very simple! Then we will see how the running package compilation mode provided by Delphi is how to solve this problem.

Section 5 Delphi's operating package

.... I am sorry, I haven't finished writing .... Skip ...

Section 6 Dream of Objects

One time, I dreamed that I became an object in the computer space world. With the continuous development of the computer world, these objects have no longer busy with the resources of the original era. Our thoughts are unprecedented, not only think about why we have to survive and run in the computer world, but also boldly research and explore unknown mystery in the computer world. We already know that the entire computer world is composed of bytes this basic particles, and the byte is composed of eight finer bit particles; we also know that the substance is not destroyed, that is, the death of any object, only means The disintegration of the object structure does not reduce any bytes or particles in the computer world, and these materials may become part of other objects; even, we also know that the world we are in a sphere, because Crossing the longitude $ fffffff again returns to the location of the origin $ 00000000. The famous physicist Object Newton has long found a universal connection between the various objects, and has proposed a famous theory with the relationship between the subject size - Newtonia. However, this object later did not understand what the power was invisibly pushed in invisibly. Therefore, he believes that God creates the movement of the entire computer world in promoting various objects. Later he became the most devout believers of God. Shortly after the Newton object, our computer world has born a greater object. Based on the execution of the first code, he has the result of the result of this basic cause, proposes the time and space of the process movement is relatively theory. He believes that it is not absolute in a moving process space, time and space in the process space in a sport, and the space will be bent. Moreover, any subject speed is absolutely impossible to exceed the speed of the CPU, and the CPU speed is the light speed in our computer world. The name of this great scientific object is Einstein, and his relativity is not understood by the object, but later scientific explorations have proven the correctness of this theory. His proposed code energy and data substance can be converted by each other, and then it has been verified in large-scale destructive virus nuclear weapons manufactured. In the world of dreams, I am very happy. I changed my attribute for a while, and I moved my way for a while, and I felt a lower incident. Yes, I am really a real object! After a while, I suddenly understood that I was an object, but this object became the real world in the dream ...

转载请注明原文地址:https://www.9cbs.com/read-130880.html

New Post(0)