Предыдущий раздел ПРОГРАММИРОВАНИЕ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ Следующий раздел

3.2. Сложение двух чисел

Теперь мы перейдем к написанию и выполнению с помощью Debug программы на машинном языке. Простейшая такая программа состоит всего из одной  машинной команды. Допустим, что эта команда  выполняет сложение двух чисел, предварительно записанных в регистры.

Допустим, что мы хотим сложить числа 3А7h и 92Аh. Запишем эти числа соответственно в регистры АХ и ВХ, воспользовавшись командой R Debug. Для суммирования содержимого АХ и содержимого ВХ будем использовать машинную команду:

D801

Данная машинная команда имеет длину два байта. Старший байт команды – D8, а младший – 01. Для лучшего восприятия человеком используется ассемблерная (мнемоническая) форма записи этой же самой команды:

add ax, bx

Для того чтобы данная машинная команда была исполнена ЦП, необходимо выполнить четыре действия:

1)выбрать место в ОП для размещения машинной команды;

2) выполнить запись команды на выбранное место;

3) сообщить ЦП о том, где расположена наша машинная команда;

4) запустить ЦП для того, чтобы он исполнил команду.

Первое из перечисленных действий заключается в том, что мы должны выбрать из огромного числа ячеек (байтов) ОП всего два соседних байта для размещения нашей двухбайтовой команды. Мы не будем сильно "блуждать" по ОП, а ограничимся той областью памяти, которую нам рекомендует использовать Debug. Данная область (сегмент) имеет длину 65536 байт (64 кбайт). Напомним, что эта длина обусловлена тем, что 65535 – максимальное число, которое можно записать  в шестнадцатибитовое слово.

Где расположен в ОП предоставляемый нам сегмент? Для этого достаточно прочитать содержимое регистра CS, воспользовавшись командой R Debug. Напомним, что регистр CS называется регистром сегмента кода и содержит номер параграфа, с которого начинается сегмент. Для того чтобы получить номер (реальный адрес) первой ячейки параграфа, достаточно его номер умножить на 16. На практике такое умножение выполняется очень просто – к номеру параграфа в шестнадцатеричном  коде (он и содержится в CS) справа приписывается 0.

Из 64 кбайт сегмента, на который указывает CS, нам надо выбрать всего два байта. В принципе можно взять любое смещение, меньшее, чем 65535, относительно начала сегмента. Но чаще всего берут смещение l00h. Ячейки сегмента с меньшими внутрисегментными адресами резервируют для служебной информации, помещаемой туда DOS.

После того, как мы выбрали место для размещения нашей машинной команды в ОП,  з а п и ш и т е  ее туда с помощью команды Debug Е (от "Enter"), предназначенной для исследования и изменения памяти:

_Е 100

3756:0100  Е4.01

_Е 101

3756:0101  85.D8

В результате числа 0lh и D8h расположены по адресам 3756:0100 и 3756:0101. Числа E4h и 85h представляют собой старое содержимое указанных ячеек ОП, которое осталось от ранее выполнявшихся программ. Номер начального параграфа сегмента, который вы увидите, возможно, будет другим, но это различие не будет влиять на нашу программу. Обратите внимание, что младший байт команды (0lh) записан нами в ячейку с меньшим адресом, а старший байт (D8h) – с большим адресом. Заметим, что для записи нескольких соседних байтов мы можем использовать всего одну команду Е, разделяя пробелом уже записанный байт от следующего:

_Е 100

3756:0100   Е4.01  85.D8

Прежде, чем идти дальше,  п р о в е р ь т е  результат наших предыдущих действий с помощью команды R:

_R

AX=03A7 BX=092A СХ=0000 DX=0000 SF=FFEE ВР=0000 Sl=0000 DI=0000 DS=3756 ES=3756 SS=3756 CS=3756 IP=0100 NV UP DI PL NZ NA PONC 3756:0100   01D8   ADD AX,BX

Теперь Вам понятно, что содержит последняя строка, выданная Debug. Она содержит: 1) логический адрес в ОП машинной команды; 2) шестнадцатеричный код этой команды, причем младший байт команды изображен слева, а старший справа (содержимое регистров показывается наоборот – старший байт слева, а младший справа); 3) ее мнемоническое представление. Почему именно нашу команду показал Debug? Ответ заключается в том, что Debug высвечивает ту команду, младший байт которой имеет адрес: (CS):(IP).

Напомним, что указатель команды IP содержит внутрисегментное смещение младшего байта той машинной команды, которая будет исполняться следующей на ЦП. В процессе выполнения машинной программы ее команды сами могут изменять содержимое IP. А пока для этой цели мы будем использовать Debug. После своего запуска Debug всегда записывает в IP 100h. В процессе выполнения нашей машинной программы это значение будет меняться. Пользуясь командой R  Debug, мы всегда можем записать в IP требуемое нам значение.

Теперь регистры и ОП готовы для исполнения нашей машинной команды.  П о п  р о с и т е  Debug ее выполнить, используя команду Т (от "Trace"), которая выполняет одну команду за шаг, а затем показывает содержимое регистров. После каждого запуска IP будет указывать на следующую команду, в нашем случае будет указывать на 102h. Мы не помещали никакой команды в 102h, поэтому в последней строке распечатки мы увидим команду, оставшуюся от предыдущей программы:

AX=0CD1 BX=092A СХ=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=3756 ES=3756 SS=3756 CS=3756 IP=0102 NV UP DI PL NZ NA PONC 3756:0102   41     INC  CX

Вот и все. Регистр АХ теперь содержит число CD1h, которое является суммой 3A7h и 92Ah. A регистр IP указывает на адрес 102h, так что в последней строке распечатки регистров мы видим команду, расположенную в памяти по адресу l02h, а не по адресу l00h.

Как отмечалось ранее, указатель команды IP вместе с регистром CS всегда указывает на следующую машинную команду, которую нужно выполнить процессору. Если мы опять напечатаем "Т", то выполнится следующая команда. Но не делайте этого сейчас, – ваш процессор может "зависнуть".

Если мы захотим выполнить введенную машинную команду еще раз, то есть сложить 92Ah и CD1h и сохранить новый ответ в AX, то надо объяснить процессору, где найти следующую команду, и чтобы этой следующей командой оказалась та же "add  ax,bx", расположенная по адресу l00h. Изменить значение регистра IP на l00h можно, используя команду R. После этого:

_R

AX=0CD1 BX=092A СХ=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=3756 ES=3756 SS=3756 CS=3756 IP=0100 NV UP DI PL NZ NA PO NC 3756:0100   01D8   ADD   AX,BX

П о п  р о б у й т е  еще раз ввести команду Debug Т и убедитесь, что регистр АХ содержит число 15FBh.

Следовательно, перед тем, как использовать команду Т, вам необходимо проверить регистр IP и соответствующую его значению машинную команду, располагаемую в нижней части распечатки (листинга), выдаваемой командой R. В результате вы будете уверены, что процессор выполнит требуемую команду.

До этого арифметические действия совершались над шестнадцатибитными словами. Но рассматриваемый процессор может выполнять действия и над восьмибитными байтами.

Напомним, что каждый регистр общего назначения может быть разделен на два байта – старший байт (первые две шестнадцатеричные цифры) и младший байт (следующие две шестнадцатеричные цифры). Название каждого из полученных регистров складывается из первой буквы названия регистра (от "A" до "D"), стоящей перед Х в слове, и буквы Н для старшего байта или буквы L для младшего. Например, DL и DH – регистры длиной в байт, a DX - длиной в слово.

Проверим байтовую арифметику на машинной команде add. В в е д и т е  два байта 00h и C4h, начиная с адреса 0l00h. Внизу листинга регистров вы увидите команду "add ah,al", которая суммирует два байта регистра AX и записывает результат в старший байт AH.

Затем  з а г р у з и т е  в AX число 0102h. Таким образом, вы поместите 0lh в регистр AH и 02h в регистр AL. Установите регистр IP в l00h, выполните команду Т, и вы увидите, что регистр AX теперь содержит 0302. Результат сложения 0lh и 02h будет 03h, и именно это значение находится в AH.

 


Предыдущий раздел В начало Следующий раздел