КОНЦЕПЦИЯ MOV AX,CS и MOV DS,AX

Может кто-нибудь объяснить функции этих трех инструкций?

  ORG 1000H 
  MOV AX,CS
  MOV DS,AX

Теоретически я знаю, что такое код, данные и дополнительные сегменты, но:

  1. Как они реализованы в этой программе?

  2. Почему весь сегмент перемещен в другой? (MOV AX,CS и MOV DS,AX)

Что эти две инструкции фактически делают?

Я могу понять значение любой другой инструкции в этом коде, кроме выделенных трех инструкций.

(Программа работает нормально. Она принимает ввод до тех пор, пока не будет достигнуто 0 — есть mov ah,01h и int 21h, затем она сравнивает al с '0', и если al равно '0', она переходит к last, в противном случае она переходит к 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

(Примечание редактора: .com программы загружаются со смещением 100h, при этом все сегментные регистры установлены равными друг другу. org 1000h, вероятно, является опечаткой для org 100h, потому что это выглядит как программа .com. Эта программа не ломается, потому что не использует никаких абсолютные адреса, только относительные переходы.)


person Muthu Ganapathy Nathan    schedule 19.03.2011    source источник


Ответы (3)


Чтобы действительно объяснить концепцию, мы должны вернуться к основной идее сегментов и тому, как x86 их использует (в реальном режиме).

8086 имеет 20-битную адресацию, но только 16-битные регистры. Для генерации 20-битных адресов он объединяет сегмент со смещением. Сегмент должен находиться в регистре сегментов (CS, DS, ES или SS). Затем вы генерируете смещение (как непосредственное значение или содержимое другого регистра или двух.

Итак, чтобы сгенерировать адрес, 16-битный сегментный регистр сдвигается влево на четыре бита, а затем к нему добавляется 16-битное смещение в каком-то другом регистре, и объединенная сумма фактически используется в качестве адреса. К большинству инструкций прикреплен сегмент по умолчанию — push, pop и все, что относится к bp, будет использовать ss. Прыжки и тому подобное используют cs. Некоторые строковые инструкции es (например, scans) и некоторые используют два сегмента — например, movsd копирует данные из [ds:si] в [es:di]. Большинство других инструкций используют ds. Вы также можете использовать переопределения сегментов, чтобы явно указать адрес, например es:bx.

В любом случае, прежде чем вы сможете осмысленно использовать сегментный регистр, вы должны сначала загрузить в него (верхние 16 бит) адрес нужных вам данных. Типичная программа «малой модели» начинается с чего-то вроде:

mov ax, @Data
mov ds, ax

В крошечной модели вы используете один и тот же сегмент для данных и кода. Чтобы убедиться, что это относится к правильному сегменту, вы хотите получить 16 бит от CS и скопировать их в DS. Как уже упоминалось рядом других, нет инструкций по перемещению CS непосредственно в DS. В вопросе упоминается одна возможность; еще один распространенный:

push cs
pop ds
person Jerry Coffin    schedule 19.03.2011

ORG 1000H сообщает ассемблеру, что следующий за ним код должен располагаться по смещению 1000H в образе кода.

Две другие инструкции копируют CS в DS. Это не копирование самого сегмента, а просто обновление указателя на сегмент данных. Для небольшой программы (‹64K) статические данные (строковые литералы в исходном коде, таблицы непрямых переходов) могут быть размещены вместе в одном сегменте с кодом. Базовый указатель сегмента необходимо загрузить в DS перед доступом к статическим данным. Загрузчик (часть ОС, которая считывает программу с диска в память и запускает ее) должен установить CS, чтобы он мог запустить программу, но не может установить DS, поэтому программа копирует CS в DS при запуске.

Последовательность из двух инструкций необходима, потому что "MOV DS, CS" не является допустимой инструкцией 8086.

person Andy    schedule 19.03.2011
comment
Я. Я новичок в сборке. Можете ли вы объяснить вещи в деталях. (Если вы не возражаете) - person Muthu Ganapathy Nathan; 19.03.2011
comment
@Muthu: похоже, вам следует просто прочитать некоторые стандартные ресурсы по этому вопросу. Ответы SO отлично подходят для ответов на конкретные четко определенные вопросы, но не в том случае, если вам нужно подробно объяснить все. Не просите других учиться за вас - person jalf; 19.03.2011

ты не можешь сделать

MOV DS, CS

это недопустимая операция (masm 32: error A2070: invalid instruction operands).

MOV AX, CS
MOV DS, AX

Эти 2 инструкции работают так же, как mov ds, cs (что недопустимо). Таким образом, ассемблер доволен и не жалуется. Но я не могу вам сказать, почему программист хочет, чтобы сегмент данных был таким же, как сегмент кода.

person BlackBear    schedule 19.03.2011
comment
Да, можете ли вы объяснить мне значение MOV AX, CS и MOV DS, AX - person Muthu Ganapathy Nathan; 19.03.2011
comment
Я могу понять MOV DS, CS не разрешен. Но не могли бы вы рассказать мне о концепции MOV AX, CS? - person Muthu Ganapathy Nathan; 19.03.2011
comment
@Muthu: Идея заключается в том, чтобы просто скопировать значение регистра cs в регистр ds. Это все, что делает mov. Какая его часть непонятна? - person jalf; 19.03.2011
comment
@MuthuGanapathyNathan Инструкцию MOV нельзя использовать для загрузки регистра CS. Попытка сделать это приводит к исключению недопустимого кода операции (#UD). Чтобы загрузить регистр CS, используйте дальнюю инструкцию JMP, CALL или RET. - person Keith Ape; 14.09.2016