8086中CS寄存器的修改与访问方法问询:加载器如何加载内容至CS?
Great question! You’re absolutely correct that you can’t directly update the CS register with a straightforward MOV CS, SOME_VALUE instruction—8086’s instruction set deliberately restricts this to avoid accidental crashes caused by misaligned code segment access. Let’s break down the valid ways to modify CS, how loaders handle this, and the role of the IP register.
Valid Instructions to Modify CS
Since you can’t use MOV, you have to rely on instructions that update both CS and IP simultaneously (more on why this is mandatory later):
Far Jump (
JMP far ptr): This is the most direct way to set a new CS:IP pair. For example:JMP 0x2000:0x0010This instruction sets
CS = 0x2000andIP = 0x0010, immediately transferring execution to the address0x2000 * 16 + 0x0010 = 0x20010.Far Call (
CALL far ptr): Similar to a far jump, but first pushes the current CS:IP onto the stack (so you can return later). This is used to call subroutines in a different code segment:CALL 0x3000:0x0500After executing this, CS becomes
0x3000, IP becomes0x0500, and the original CS:IP is saved on the stack for theRETinstruction.Far Return (
RET far): When you’re done with a far-called subroutine, this instruction pops the saved IP and CS from the stack, restoring them to their previous values. This indirectly modifies CS by reloading the old segment value.Interrupt (
INT) and Interrupt Return (IRET): TheINTinstruction pushes the current FLAGS, CS, and IP onto the stack, then loads a new CS:IP pair from the interrupt vector table.IRETreverses this by popping FLAGS, IP, and CS back into their registers, effectively modifying CS to its pre-interrupt value.
How Loaders Set CS for Programs
Loaders (like DOS’s system loader or early bootloaders) need to transfer control to the program they’ve loaded into memory, which means setting the correct CS and IP. Here’s how they do it:
Once the program’s code is loaded into a specific memory segment, the loader executes a far jump to the program’s entry point (defined in the executable header, like .EXE or .COM files). For example, if the program’s code starts at segment 0x1500 with offset 0x0000, the loader runs:
JMP 0x1500:0x0000
This directly sets CS to the program’s code segment and IP to the starting offset, handing over execution to the program.
Do You Need the IP Register to Modify CS?
Yes—you cannot modify CS without also modifying IP, and there’s no way around this. Here’s why:
The 8086 uses a segmented memory model where CS * 16 + IP gives the absolute physical address of the next instruction to execute. A CS value alone is meaningless because the CPU has no idea where in that segment to start running code. Intel designed the instruction set to enforce this pairing, which is why direct MOV operations on CS are prohibited—they would leave IP pointing to an arbitrary (and likely invalid) offset in the new segment, leading to crashes or undefined behavior.
内容的提问来源于stack exchange,提问作者Amitay Tsinis

