Well, I am trying to find an assembly instruction that moves whole instructions to a specific address(which is independent of the size of the instruction). If there is no such instruction, could anybody give me some ideas on how multithreading could be achieved without system calls or other software? In other words, let's suppose that I am making my own operating system, how can I enable multithreading with efficient code in assembly?
-
Why would you think multithreading *requires* the instructions to have been moved in a single instruction? – EOF Jun 05 '17 at 21:39
-
@EOF how this could be achieved? – Anastassis Kapetanakis Jun 05 '17 at 21:45
-
1It's pretty easy on some architectures that have fixed-size instructions, like ARM (A32 and AArch64), POWER MIPS and the like. On such an architecture you simply load/store a 32-bit fixed-point number. Again, how this could *possibly* be relevant to multithreading is unclear from your question. – EOF Jun 05 '17 at 21:48
-
@EOF I am just trying to find a way to do multithreading and that was the first idea that came up on my mind...it's pretty complex...supposing that we want to move an instruction with no-fixed-size from one address to other, regardless the multithreading, how could we do this? – Anastassis Kapetanakis Jun 05 '17 at 21:51
-
1Why would you move single instructions *at all*? – EOF Jun 05 '17 at 21:55
-
1@EOF I am just wondering if there is such instruction... – Anastassis Kapetanakis Jun 05 '17 at 21:56
-
mov, but there is no reason for the processor to have an instruction that knows the size of instructions so all you are asking I hope is how do I move data from one address to another (the data being instructions in this case). But here again what could this possibly have to do with multithreading? no reason whatsoever to move anything, you want to multithread/task you simply jump or more correctly return from an interrupt into a different thread, every so often a timer interrupt comes and you switch threads again, by returning to a different one, where it was interrupted in the past – old_timer Jun 05 '17 at 22:45
-
You want to look into TSS. You don't need to move instructions at all. – David Hoelzer Jun 05 '17 at 23:30
1 Answers
Re the question of how to achieve multithreading in raw assembly: Modern 32-bit x86 processors have hardware support for task switching. You can use this to implement multitasking (multiple processes with distinct address spaces) and/or multithreading (multiple execution threads in a single process).
This functionality is documented in the Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3, Chapter 7, Task Management. NOTE: Reading & understanding this ridiculously dense 4700 page document is likely to require 12 lifetimes.
Using this hardware support is the most straightforward way to get something running but probably not the most efficient. x86-based operating systems early on moved away from this to manual task switching. This allows the system to implement switching features not provided by the CPU and also to perform optimized switches when a full switch would be overkill. The approach became so universal that the 64-bit long mode of x86 processors dropped hardware task management support. Modern operating systems use manual task switching.
Re the idea of moving instructions as a way to achieve multithreading, I think your concept here is to move code around the address space when switching to new code is necessary. There are 2 alternative techniques that eliminate the need to do this.
First, instead of moving code you can jump to code at a different location. Early multitasking operating systems such as Unix on the PDP-11 used this technique. You can load all active programs into memory at different locations, set up a periodic interrupt to drop control to your system software every so often, and on each interrupt choose the next program to jump to. The system should keep track of where each program stops so it can resume at the same place.
The second approach depends on virtual memory. There is still a single physical memory space. On top of that, multiple "virtual" memory spaces are defined. At any given time only 1 virtual memory space is active. Whenever memory is accessed the system translates the virtual address into some physical address. The program accessing memory only sees its own virtual address space.
Each task is given its own address space. When switching to a new task the system activates its private address space then resumes execution wherever it was last paused in the private address space. Instead of moving things around the single shared address space, or even jumping from one place to another in the shared address space, you actually define a whole set of separate address spaces. You shift into new spaces as necessary.
Modern multithreading depends heavily on this approach. Each process will have a private address space; the system shifts between them as necessary. A process will have 1+ threads. Every thread in a process shares the same address space. Then all you store per thread is where execution was last paused. Switching to a new thread in the same process keeps the current address space and just jumps within it to wherever the new thread was last paused.
Re the question of how to move instructions, assembly languages don't provide such an ability. It's not a common thing to do. If you wanted to operate on machine code in memory you would likely want to use a library like the Intel X86 Encoder Decoder library. A library like this has knowledge of the instructions that exist and the byte format of machine code. This enables it to interpret a sequence of bytes as an instruction.
Once you're aware how large the following instruction is, moving that number of bytes is an easy task in assembly. In x86 you would use the mov
instruction.
-
You mentioned the periodic interrupt! How can I do that? I mean how to enable the cpu to run a specific bunch of code(interrupt) every 5milliseconds(for example)? – Anastassis Kapetanakis Jun 06 '17 at 09:10
-