Can someone please explain the functions of these three instructions?
ORG 1000H
MOV AX,CS
MOV DS,AX
I know what the code, data, and extra segments are in theory, but:
How they are implemented in this program?
Why is the entire segment moved into another? (MOV AX,CS
and MOV DS,AX
)
What do these two instructions actually do?
I can understand the meaning of every other instruction in this code, except for the highlighted 3 instructions.
(The program works fine. It accepts input till 0 is hit -- there's a mov ah,01h
and an int 21h
, then it compares al
to '0'
and if al
is '0'
, it jumps to last
, otherwise it jumps into back
.)
ASSUME CS:CODE
CODE SEGMENT
ORG 1000H
MOV AX,CS
MOV DS,AX
BACK:
MOV AH,01H
INT 21H
CMP AL,'0'
JZ LAST
JMP BACK
LAST:
MOV AX,4C00H
INT 21H
CODE ENDS
END
(Editor's note: .com
programs are loaded at offset 100h
, with all segment registers set equal to each other. org 1000h
is likely a typo for org 100h
because this looks like a .com
program. This program doesn't break because it doesn't use any absolute addresses, only relative jumps.)
To really explain the concept, we have to back up to the basic idea of segments, and how the x86 uses them (in real mode).
The 8086 has 20-bit addressing, but only 16-bit registers. To generate 20-bit addresses, it combines a segment with an offset. The segment has to be in a segment register (CS, DS, ES, or SS). You then generate an offset (as an immediate value, or the contents of another register or two.
So, to generate an address, a 16-bit segment register is shifted left four bits, and then a 16-bit offset in some other register is added to that, and the combined total is actually used as the address. Most instructions have a default segment attached to them -- push
, pop
and anything relative to bp
will use ss
. Jumps and such use cs
. Some of the string instructions es
(e.g., scans
) and some use use two segments -- for example, movsd
copies data from [ds:si]
to [es:di]
. Most other instructions use ds
. You can also use segment overrides to explicitly specify an address like es:bx
.
In any case, before you can make any meaningful use of a segment register, you first have to load it with the (top 16 bits of) the address of the data you care about. A typical "small model" program will start with something like:
mov ax, @Data
mov ds, ax
In tiny model, you use the same segment for the data and the code. To make sure it's referring to the correct segment, you want to get the 16 bits from CS and copy it to DS. As a number of others have mentioned, there's no instruction to move CS directly to DS. The question mentions one possibility; another common one is:
push cs
pop ds