问题
I have just started to read about intel 8086 and have a question concerning its memory.
I read that the address bus is 20-bit wide, which means the address space is 1MB, and this space is divided into segments.
the question is:
the four segment registers,
CS,DS,SSandES, are they read only or I can set their values, and which are their default values?I saw the following assembly tutorial:
ORG 100h MOV AX, 0B800h ; set AX = B800h (VGA memory). MOV DS, AX ; copy value of AX to DS. MOV CL, 'A' ; CL = 41h (ASCII code). MOV CH, 01011111b ; CL = color attribute. MOV BX, 15Eh ; BX = position on screen. MOV [BX], CX ; w.[0B800h:015Eh] = CX. RET
Concerning the first line, does that mean this code will exist in address 0x100 in code segment space or in the whole address space
and the line:
MOV [BX], CX
Does that mean every time I reference an address in the MOV instruction, the address should be estimated from the start address of the data segment? (as he wrote that the destination is the value + the value in the data segment reg)
回答1:
First, I feel compelled to point out that you appear to be talking here about 8086 "real mode" addressing, which is a very old way of doing things which almost nothing uses anymore. Pretty much all modern operating systems operate in "protected mode", which supports many enhancements (such as flat 32- and 64-bit memory space addressing, virtual memory, etc.) which changes how all of this works substantially.
As far as I know, most operating systems nowadays don't even have any way to run code such as this (in real mode) anymore, so if you're interested in learning assembly for the purposes of programming modern PCs, you might want to find some more recent sources to learn from.
That having been said, assuming you do have some reason to want to do this (such as working with certain embedded processors), or are just curious for historical purposes:
Yes, the 8086 real-mode segment registers can be modified. The instructions and options for doing this are a bit more limited than modifying the more general-purpose registers (for example, there's no instruction to just load a value directly into a segment register, which is why in the code you quoted, the value is first loaded into
AX, and thenAXis loaded intoDS), and can also vary depending on which segment register you're working with.In general, you would never want to modify
CS(the "code segment") register directly, as that would result in immediately changing what code the processor is running (probably in a way you really don't want). The usual way to modifyCSis with a "long jump" or "long call" instruction, which will update bothCSandIP(the instruction pointer) at the same time. Likewise,SS(the "stack segment") is usually set at the beginning of program execution and never changed (but it technically could be if you had some really compelling reason to do so).DSandESare general-purpose data segment registers and it was fairly common for programs to change these however they wanted to best access the memory they wanted to work with (as your example code above demonstrates).As for the initial values for these registers, those were typically determined by the operating system prior to calling the program's code. Traditionally, in MS-DOS, there were two ways to write programs, as .COM files or as .EXE files. (The
ORG 100hline in the code above suggests that it was intended to be run as a COM program.) In the COM case, MS-DOS would initially set all of the segment registers to be the same asCS(that is, they'd all point to wherever DOS had decided to load the program in memory) before invoking the program. The EXE file format was somewhat more sophisticated, and allowed specifying a separate "data segment", in which case the OS would setDSandESto point to that segment before starting the program instead. In EXE programs, DOS would also typically set up a separate stack segment (SS) for them as well.The ORG 100hline tells the assembler "assume that the following code will be loaded at address 100h". In real-mode code, addresses such as this are always relative toCS(so the program could actually be loaded many places in memory, as long asCSis set to the correct value to make the code be at 100h relative toCS).Most addresses for data operations (such as
MOV) will be calculated relative toDSby default (for some instructions, you can change that by explicitly specifying a different segment to use, but whether and how you can do that depends on the opcode and the way you're using it). There are, however, a few instructions which are designed to use other segments by default. In summary, it's really best to read the docs for each opcode you want to know about to determine how it uses which segment registers.
回答2:
Get an intel 8088/86 manual. this is all explained in there.
yes you can change them, you would have to be able to change them for them to be useful. The obvious segments are used by default (code for code, data for data), but there are places where you can specify other segments on a data instruction.
The org 0x100 means this code (or data that follows an org directive) starts at address 0x100 within the segment.
来源:https://stackoverflow.com/questions/18837627/what-is-the-value-of-segment-registers-in-8086