29.12.2024
| Главная | Поиск | Регистрация | Профиль | Вход | Выход |
Реклама
Реклама
Интересное
Главная » Статьи » Программирование на Ассемблере » Программирование на Ассемблере

Введение в машинный код_3 часть

1.10. Разборка с процедурами

  #1. В разделе 1.7. #4 мы сделали глупую линейную программульку, выводящую окошки. Обещали, что в следующей главе сделаем ее менее "тупой", да отвлеклись почему-то на циклы и стек. То есть я-то знаю, ПОЧЕМУ, но вот вам об этом - не скажу! Догадайтесь сами. Итак, поехали...

  Шаг первый. Внимательно посмотрев на "линейную" прогу из 1.7. #4 и прочитав "условие задачи" из главы 1.7. #1, вы обязаны возмутиться - зачем мы использовали команду MOV, если и ежу понятно, что отличия следующего окошка от предыдущего можно выразить более лаконично: BH=BH+10, CH=CH+1, CL=CL+1, DH=DH-1, DL=DL-1? И не нужно напрягать мозги, подсчитывая новое значение регистра вручную.

  Если вы так подумали, то оказались совершенно правы! Программу из #4 запросто можно было представить в таком вот виде:

:0100 XOR AL,AL ;окошко первое 
:0102 MOV BH,10
:0104 MOV CH,05
:0106 MOV CL,10
:0108 MOV DH,10
:010A MOV DL,3E
:010C MOV AH,06
:010E INT 10
:0110 ADD BH,10 ;окошко второе
:0113 ADD CH,01
:0116 ADD CL,01
:0119 SUB DH,01
:011C SUB DL,01
:011F INT 10
:0121 ADD BH,10 ;окошко третье
:0124 ADD CH,01
:0127 ADD CL,01
:012A SUB DH,01
:012D SUB DL,01
:0130 INT 10
:0132 ADD BH,10 ;окошко четвертое
:0135 ADD CH,01
:0138 ADD CL,01
:013B SUB DH,01
:013E SUB DL,01
:0141 INT 10
:0143 ADD BH,10 ;окошко пятое
:0146 ADD CH,01
:0149 ADD CL,01
:014C SUB DH,01
:014F SUB DL,01
:0152 INT 10
:0154 INT 20 ;конец программы

  И несмотря на то, что размер ее оказался несколько большим, она тоже будет работать правильно :).

  Но тут любой более или менее наблюдательный программер возмутится повторно - да что это за программа такая? В ней целых четыре раза повторяется один и тот же кусок:

:0143 ADD BH,10
:0146 ADD CH,01
:0149 ADD CL,01
:014C SUB DH,01
:014F SUB DL,01
:0152 INT 10

  И знаете что? Этот наблюдательный программер будет прав! А если он еще и нехорошо выразится по поводу такого "неправильного" стиля программирования - будет прав... или почти прав...

  Есть такой процесс - оптимизация, одной из особенностей которой является уменьшение параметризации (параметризация - вставка процедур в место вызова или фиксация значения отдельных параметров) и развертка циклов. То, что обычно такими вещами должен заниматься компилятор, суть меняет не сильно - тем более, что ассемблер оптимизацией сам не занимается :). Но до ассемблера мы с вами еще не добрались, поэтому говорить об этом пока еще рано.

  Внимательно всмотритесь в полный текст программы и в этот выделенный кусок. И помедитируйте над ним до полного просветления текущей "обстановки"...

  #2. Итак, у нас есть ПОВТОРЯЮЩАЯСЯ ЧАСТЬ программы. А еще у нас есть пальцы, которым, как правило, лень набивать длинные "простыни" программного кода. Это одна из многочисленных причин, по которым и придумали такого "зверя" как ПОДПРОГРАММУ (она же - ПРОЦЕДУРА, она же - ФУНКЦИЯ). Остальные причины мы рассмотрим попозже, а вот на счет "лени" поговорим прямо сейчас:

  Если мы возьмем наш "часто повторяющийся" кусок программы и допишем в конец команду RET, то получится у нас именно ПРОЦЕДУРА - во всей своей красе:

:011E ADD BH,10 ;"точка входа"; она же - начало "тела".
:0121 ADD CH,01
:0124 ADD CL,01
:0127 SUB DH,01
:012A SUB DL,01
:012D INT 10 ;конец "тела"
:012F RET

  Красота ее вот в чем заключается - процедуру можно "вызвать" командой CALL :)))

  Все более чем просто. Когда в программе встречается CALL с указанием АДРЕСА-НАЧАЛА-ПРОЦЕДУРЫ (в нашем случае это 011E), то компьютер "идет" по этому адресу и выполняет все команды, расположенные между "точкой входа" (включительно) и командой RET, то есть так называемое "тело" процедуры.

  RET - это тоже команда, но к "телу" (адреса 11E... 12D) она не относится. Она является "ОРГАНИЗАТОРОМ" этого "тела". Процессор, встретив команду RET, возвращает управление обратно после последнего CALL (т.е. "перепрыгивает" на строчку ниже "вызвавшего" данную процедуру CALL'а)...

  Короче, CALL XXXX означает - "выполнить процедуру, начинающуюся по адресу XXXX". А RET означает - "конец процедуры" и, соответственно, переход на строчку ниже вызвавшего его CALL'а.

  Если же говорить более формально и строго, то процедура - это средство обобщения, когда некоторая общая последовательность действий получает "имя", и потом при необходимости ПОВТОРНОГО ИСПОЛЬЗОВАНИЯ данного кода к нему просто идет обращение по "имени" (напомним, что в отличие от языков высокого уровня и даже ассемблера, в машинном коде от имен остаются одни только адреса, а язык, принимаемый DEBUG, является промежуточным между машинным кодом и ассемблером). Более того, следующим логическим шагом после обобщения является параметризация, когда некоторые части общего кода зависят от передаваемой извне информации (параметров), с чем очень хорошо знакомы программисты на языках высокого уровня. Но о параметризации и ее применении в ассемблере мы поговорим в другой раз.

  Не ругайтесь. Мы знаем, что вы ни черта не поняли. А по сему набьем в debug'е эту прогу и посмотрим, что она делает.

  Те, кто читал внимательно, могут отметить, что инструкция CALL по своему действию очень похожа на инструкцию генерации прерывания INT, с той лишь разницей, что аргументом CALL является адрес процедуры, а не индекс в таблице "векторов прерываний", где и хранится адрес обработчика прерывания (той же процедуры). А для особо продвинутых отметим, что в ранних моделях процессоров от Intel при подаче запроса на обработку от внешнего устройства контроллер прерываний, помимо собственно сигнала прерывания, посылал в процессор инструкцию CALL.

  #3. Кстати, вы уже поняли, почему мы называем debug "до боли любимой программой"? Нет? Неужели вы еще не полюбили это произведение программерского гения всеми фибрами своей души? Еще нет? М-да... мы в вас разочаровались.

  А по сему: - НАБИВАЕМ! - злобно кричим, брызгая слюной на эргономичный коврик:

:0100 XOR AL,AL ;первое окошко рисуем, как и раньше...
:0102 MOV BH,10
:0104 MOV CH,05
:0106 MOV CL,10
:0108 MOV DH,10
:010A MOV DL,3E
:010C MOV AH,06
:010E INT 10
:0110 CALL 011E ;четыре раза вызываем подпрограмму,
:0113 CALL 011E ;начинающуюся по адресу 011E
:0116 CALL 011E
:0119 CALL 011E
:011C INT 20 ;выход из программы...
:011E ADD BH,10 ;начало процедуры
:0121 ADD CH,01
:0124 ADD CL,01
:0127 SUB DH,01
:012A SUB DL,01
:012D INT 10
:012F RET ;конец процедуры

  Не правда ли, красиво получилось?

  Первое, что вас может смутить - это то, что команда выхода (INT 20) расположена не там, где вы привыкли, то есть не в конце программы.

  Ну что я вам могу на это ответить? Концы - они-то разные бывают! Последняя строчка в листинге вовсе не означает, что последней будет выполняться именно она. И это не должно вас смущать! А если все же смущает - смотрим, как работает эта прога из-под отладчика.

  Итак, до адреса 0110 вам все должно быть понятно, мы это рассматривали. Трассируем дальше...

  - Что значит "трассируем"? - попросите вы напомнить.

  Мысленно мы ругаем вас нехорошими словами (ну сколько раз повторять-то можно!), а вслух скажем: Команда "T" и Enter. Команда "T" и Enter. Команда "T" и Enter…

  Команда CALL 011E по адресу 0110 говорит процессору: "Дальше мы не пойдем, пока не выполним простыню, начинающуюся по адресу 011E". И далее, естественно, следует переход на этот адрес.

  Входим в тело процедуры, начиная с 011E, и выполняем команды до 012D включительно...

  А теперь внимательно смотрим, на какой адрес нас "перекинет" команда RET.

  На 113-й? И это правильно! По 113-му адресу у нас какая команда? Да вот опять CALL 011E!

  Опять процедура с адреса 011E, опять RET[URN] на строку ниже, то есть на 116...

  И так далее, до того момента, пока следующей строчкой не окажется INT 20 - собственно, на этом и программе конец.

  Ну оно и ежу понятно, что, несмотря на то что INT 20 - не в конце программы, последним выполнится именно он.

  Короче, куда бы вас не посылали всяческие "столбы с указателями", конец вашего пути только один... А плутать вокруг да около этого конца вы можете сколько вам заблагорассудится...

  Кстати, именно это и является одной из многочисленных тайн программинга.

  Кто после этого скажет, что программисты - недZенствующие люди?

  #4. Те, кто внимательно ознакомились с циклами, они и на этом не остановятся! Посмотрев на адреса 110...119, они вообще возьмут и возомнят себя воистину крутыми парнями! Знаете, что они напишут? А вот что (предвидим!):

:0100 XOR AL,AL 
:0102 MOV BH,10
:0104 MOV CH,05
:0106 MOV CL,10
:0108 MOV DH,10
:010A MOV DL,3E
:010C MOV AH,06
:010E INT 10
:0110 MOV CX,0004
:0113 CALL 011A
:0116 LOOP 0113
:0118 INT 20
:011A ADD BH,10
:011D ADD CH,01
:0120 ADD CL,01
:0123 SUB DH,01
:0126 SUB DL,01
:0129 INT 10
:012B RET

  То бишь еще и CALL в цикл при помощи MOV CX,4 и LOOP'а "закрутят". И что? А попробуйте!

  Что, не "пашет"? А что надо делать, если "не пашет, а должно бы"? Правильно! Смотреть из-под отладчика!

  Смотрим? Если посмотрите, то сразу же и "загвоздку" увидите - CX, использованный в качестве "счетчика" циклов, "перебивает" тот же CX, но используемый как "координаты верхнего левого угла окна". И что с этим делать прикажете?

  Вот вы и столкнулись с одной из самых больших проблем. В процессорах фирмы Intel есть только 4 регистра общего назначения (и то в большинстве случаев - специализированных). Помните, мы вам говорили об этом?

  А теперь попробуйте выкрутиться из этой нехорошей ситуации с использованием стека :). Кстати, весьма "мозгопрочищающая" задачка :).

1.11. Переходы

  #1. "Переходы" бывают разные. Если вы пришли в гости, а вас просто послали к черту - такой переход называется "безусловный". А нежели вам сказали: "Если без пива - то иди к черту, а если с пивом - тогда проходи", - то это уже "условный" переход.

  Соответствено, для успешного перехода необходимо указать: ПРИ КАКОМ УСЛОВИИ выполнить переход, КУДА ПЕРЕЙТИ, ну и, наконец, сам пинок под зад нужно СДЕЛАТЬ, чтобы переход "гостя" в заданном направлении все-таки "состоялся".

  Безусловный переход у нас "делает" мнемоническая команда JMP, после которой следует указать адрес, на который "компьютер" должен пойти "на" ;). В данном случае УСЛОВИЕМ у нас будет "при любых обстоятельствах": хоть пустой, хоть с пивом, хоть с ... все равно. Когда рисовали окошки, вы уже использовали эту команду для создания "спецдефекта". Если кто еще не понял, что делает эта команда - к нему (см. 1.7 #4) и отсылаю. Сделайте "спецдефект" и посмотрите на него под отладчиком. Когда до вас дойдет, почему мы там не предусмотрели выхода (INT 20h) - можете переходить к п.2 текущей главы.

  #2. Условный переход у нас организуется в два шага. На первом шаге мы вычисляем условие ("принес ли пиво?"), на втором шаге "посылаем" или не "посылаем" - в зависимости от результатов вычислений. Можно привести такую аналогию - на первом шаге два груза кладутся на весы, сравнивающие их массу. Соответственно, возможны только три их положения: наклон влево (груз в левой чашке тяжелее), наклон вправо (груз в правой чашке тяжелее) и равновесие. На втором шаге мы предпринимаем действия в зависимости от положения весов.

  Например, на первом шаге можно использовать как "аптекарские весы" инструкцию CMP, которой обязательно нужно указать, ЧТО и С ЧЕМ она будет сравнивать.

  Пишем, например,

CMP AX,BX

  В зависимости от значений регистров у нас возможны следующие состояния: "наклон влево" (AX &tt; BX), "наклон вправо" (AX > BX) и "равновесие" (AX = BX). Таким образом ВЫЧИСЛЕНИЕ УСЛОВИЯ у нас уже организовано :). Только условие не бинарное, а есть еще и "серединный вариант" (и даже несколько других!). Это нормально. Это для того сделано, чтобы мы могли выражения типа "больше-или-равно", "меньше-или-равно" да и просто "равно" в своих программах использовать...

  Итак, УСЛОВИЕ есть. Теперь решаем, что нам делать при том или ином условии. Вот далеко не полный список возможных "прыг-скоков":

  • JE - переход если равно;
  • JNE - переход если не равно;
  • JA - переход, если больше;
  • JAE - переход, если больше или равно;
  • JB - переход, если меньше;
  • JBE - переход, если меньше или равно...
  • и т.д.

  Естественно, что после мнемоники ("прыгнуть, если") должен стоять АДРЕС, куда нужно "прыгнуть", если условие соблюдено. Если же условие не соблюдено, то прыжок не происходит, и выполняется нижеследующая строка программы.

  Задание на медитирование - зрительно представьте себе "весы правосудия". И побросайте на их чашки разную шестнадцатеричную дрянь в различных "пропорциях" и "комбинациях". Просветлиться вы должны следующим образом - в какую бы сторону эти ваши "весы" ни склонялись, вы все равно заставите систему работать так, как ЭТО вам угодно! "Весы" - они только констатируют факт. А вот "приговор" выносят судьи. Хе... и пусть после этого только кто-нибудь скажет, что программерам чужда политика - дело, как известно, весьма грязное.

  А о чем это мы? Ах да, переходы...

  #3. Продолжим программировать, что ли? Напишем что-нибудь красивое и неизменно тупое? С использованием условных и безусловных переходов?

  Поехали! Слабаем мы сейчас что-то наподобие графического редактора :)). Не верите?

  У-у-у... Сложная задачка! Если въедете, что да как - значит, молодцы! Значит, разобрались-таки с дzебагом! Значит, подключились-таки к программерскому эгрегору и более или менее привели в порядок свои мозги :)... А это сложная штука, мы вам скажем - мозги в порядок приводить! Особенно когда есть куча инструментов, которые "порядок в коде" сами как бы наводят :).

  Думаете, вы по нашим текстам программировать учитесь? По-настоящему программировать мы еще не начали! Все, чем мы пока занимаемся - это приводим в порядок свои мозги и тренируемся на кнопки клавиатуры нажимать :)). А вот ско-о-оро НАЧНЕМ... тогда "прощай, здоровье" будет настоящее!

  Итак, сначала рассмотрим прерывания, которые в нашем "графическом редакторе" будут использоваться. Их три штуки, и все - BIOS'овские:

mov AH,00 ;функция 0 прерывания 10h устанавливает "режим видео"
mov AL,04 ;"на входе" (в регистре AL) - номер режима .
int 10h ;если AL=4, то устанавливается цветной 320х200 графический режим
mov CX,64h ; CX и DX - координаты точки
mov DX,64h
mov AH,0Ch; функция 0Ch (в регистре AH!) прерывания 10h рисует точку.
mov AL,1Bh ;в AL - "код цвета" этой точки.
int 10h

  Опять-таки - подробности о координатах и "кодах" цвета ищите сами!! Благо, знаете, где искать.

mov AH,00 ;функция 0 прерывания 16h
int 16h ;"читать код нажатой клавиши"

  Эта функция считывает код сканирования и код символа (клавиши на клавиатуре и соответствующий ей ASCII-код) из буфера клавиатуры (есть такой). Если в буфере ничего нет - она ждет, пока там что-нибуть появится. То есть ЖДЕТ, чтобы вы нажали на какую-нибудь клавишу, код которой будет занесен в регистр AX. Причем в AL - "символ", а вот в AH - так называемый "код сканирования"...

  Кодами вы пока голову не забивайте. Достаточно знать, что после нажатия клавиши Up в AH "попадет" значение 48h, Down - 50h, Left - 4Bh, Right - 4Dh.

  Как работает последний кусок кода, обязательно проверьте под отладчиком, это полезно :).

  #4. И лезем, лезем в наш горячо любимый DZEBUG, дабы набить там драгоценные строчки машинного мнемонического никому-кроме-вас-непонятного кода!

-a
:0100 MOV AH,00 ;устанавливаем графический режим
:0102 MOV AL,04
:0104 INT 10
:0106 MOV CX,0064 ;координаты Первой Точки
:0109 MOV DX,0064
:010C MOV AH,0C ;рисуем точку!
:010E MOV AL,1B
:0110 INT 10
:0112 MOV AH,00 ;ждем нажатия на клавишу
:0114 INT 16
:0116 CMP AH,4B ;а не нажат ли у нас Left?
:0119 JE 012A ;если да - то "прыг"!
;если нет - то следующая строчка
:011B CMP AH,4D ;а не нажат ли у нас Right?
:011E JE 012D
:0120 CMP AH,48 ;а не нажат ли у нас Up?
:0123 JE 0130
:0125 CMP AH,50 ;а не нажат ли у нас Down?
:0128 JE 0133
:012A DEC CX ;задаем новые координаты, в зависимости
:012B JMP 010C ;от нажатой клавиши - и скок в начало!
:012D INC CX
:012E JMP 010C
:0130 DEC DX
:0131 JMP 010C
:0133 INC DX
:0134 JMP 010C

  Тут один из автору вставили шпильку:

  "Не хватает проверки и выхода (со сбросом видеорежима!) по Esc - такие действия должны быть обязательным атрибутом, а не домашним заданием."

  Совершенно верная шпилька, товарищи! Но все равно - пусть это будет домашним заданием.

  Если вы все ввели правильно - должно заработать! Полюбуйтесь плодами своей медитации... Красиво?

  #5. А сейчас мы это все дело прокомментируем:

  • адреса 100...200 - устанавливаем графический режим, указываем функцию (100), указываем номер режима (102) и вызываем прерывание (104);
  • адреса 106...109 - инициализируем координаты первой точки. Координаты последующих точек будут определяться "динамически" - в зависимости от нажатой клавиши;
  • адреса 10С...110 - рисуем точку. Первый раз - в координатах, инициализированных командами по адресам 106 и 109. Все последующие разы - по координатам, "инкрементированным" или "декрементированным" (во словеса!) по адресам: 12A, 12D, 130 и 133;
  • адреса 112...114 - ждем нажатия на клавишу;
  • адреса 116...128 - "щемим" нужные нам клавиши. "Взвешиваем". На каждую из курсорных клавиш по адресам 12A...134 приготовлены "обработчики". Если найдена "нужная клавиша", то делаем прыг на "обработчик" этой клавиши;
  • aдреса 12A...134 - в этом блоке определяется, что делать с координатами следующей точки. После чего - прыжок на "рисуем точку" :).

  Правда, здорово получилось?

1.12. Данные

  #1. Работать с кодом мы с вами научились. Сейчас поучимся заставить наш код обрабатывать данные...

  Итак, запускаем DZEBUG и вводим следующую команду:

-e cs:115

  Которая означает: "набиваем память всяким дерьмом начиная со смещения 115".

  В ответ он вам выплюнет:

17B3:0115 00.

  Что означает: байт по смещению 115 равно 00. И точка. Но это не простая точка - это приглашение ввести НОВОЕ ЗНАЧЕНИЕ этого байта. Когда вы его ввели, нужно нажать на пробел.

  Если вы вознамеритесь последовательно ввести 1,2,3,4,5, то это будет выглядеть приблизительно так:

17B3:0115 00.1 75.2 AD.3
17B3:0118 66.4 FF.5 [Enter]

  А теперь делаем дамп памяти и смотрим, что за дрянь у нас получилась...

  А ведь получилoсь же!!

  #2. Мы запросто умеем "присваивать" регистру любое значение (mov AL,1C какой-нить), запросто можем "копировать" содержимое одного регистра в другой (mov AL,BL например)... А сейчас мы с вами научимся при помощи той же команды MOV еще и с данными из памяти работать.

  Все проще пареной репы... Если мы напишем

MOV AL,[115]

  то в результате выполнения этой команды в регистр AL "внесутся" две шестнадцатеричные циферки (байт), которые по адресу 115 находятся. То есть в нашем случае AL станет равным 1.

  А теперь посмотрите, что делает "обратная" команда:

mov AL,55
mov [115],AL

  В первой строчке мы присвоили AL значение 55, а второй строчкой "скопировали" значения регистра в байт по адресу 115. Правда, проще некуда?

  Обязательно посмотрите на этот процесс под отладчиком!

  #3. А еще вот какой изврат с этим можно делать:

mov BX,115
mov AL,[BX]

  Сие присваивает регистру AL значение байта по адресу 115 :). Ну... через посредника "BX" присваивает! Который у нас "переменная", как известно :).

mov AL,1C
mov BX,115
mov [BX],AL

  А этот кусок кода у нас "записал" 1C в сегмент данных по адресу 115 :). Ну, и извращения наподобие:

mov AL,[BX+1]

  и

mov [BX+1],AL

  Тоже весьма и весьма полезны в программерском деле :).

  Короче: все, что в квадратных скобках, - это адрес в памяти, с которым вы собираетесь "работать". Другой вопрос, что этот адрес может быть "составным"...

  #4. Низкоуровневый Paint мы с вами уже писали. Сегодня напишем низкоуровневый дZенский EXCEL.

  Задание простое... Есть у нас табличка типа:

1 8 ?
2 9 ?
3 1 ?
4 2 ?
5 2 ?

  в которой данные в формате HEX. И все, что нам нужно с ними сделать - это просуммировать каждую "строчку", а сумму занести в третий "столбец"... В EXCEL'е это делается элементарно... А на машинном уровне, в общем-то, не намного сложней!!

  Для начала мы наберем "исходные данные" и зарезервируем место (например, забьем нулями) под третий столбец, в который собираемся помещать результат...

  Набиваем блок данных, начиная с адреса, например, 115:

-e ds:115
17EA:0115 01.1 08.8 02.0
17EA:0118 09.2 02.9 00.0 03.3 03.1 00.0 04.4 04.2
17EA:0120 00.0 05.5 05.2 00.0

  Вот так это у меня в DZEBUG'е выглядело :). Только я еще дамп посмотрел, правильно ли я ввел:

17EA:0110 03 E2 F3 CD 20 01 08 00-02 09 00 03 01 00 04 02 .... ...........
17EA:0120 00 05 02 00 6A 87 04 FF-76 FE 57 57 9A 5C 6C 87 ....j...v.WW.\l.

  Вроде правильно :)). Ну а программу я вот какую придумал:

17EA:0100 BB1501 MOV BX,0115
17EA:0103 B90500 MOV CX,0005
17EA:0106 8A07 MOV AL,[BX]
17EA:0108 024701 ADD AL,[BX+01]
17EA:010B 884702 MOV [BX+02],AL
17EA:010E 83C303 ADD BX,3
17EA:0111 E2F3 LOOP 0106
17EA:0113 CD20 INT 20

  В BX я занес адрес начала блока данных (он же - верхний левый угол нашей таблицы). В CX внес 5, чтобы столько раз цикл выполнился (LOOP по адресу 111). А тело цикла вообще простое:

  Команда по адресу 106 забирает в AL цифирь из первого столбца.

  108 - суммирует "цифирь из первого столбца с цифирью из второго столбца" (сумма, само собой, в AL'е остается).

  10B - записывает сумму в третий столбец :).

  Ну и ADD BX,3 для перехода на следующую строчку :).

  И все на этом...

  Сделайте трассировку (внутрь INT 20 залезать не надо) и посмотрите на дамп нашего блока данных :)

  Я и говорю: ПРОЩЕ ПАРЕНОЙ РЕПЫ!! ;)

  #5. Видите? В качестве переменных "в компьютере" можно использовать не только регистры, но и "куски" памяти! А уж там вы можете клепать свои переменные в почти неограниченном количестве! Единственное, что нужно иметь ввиду: с переменными-регистрами компьютер работает намного быстрее, чем с переменными-в-памяти :).

  Кстати, если вы хотите сохранить плод своих сегодняшних трудов на веник, то имейте ввиду, что вы и сегмент данных тоже должны сохранить! То есть: вам нужно сохранить весь "диапазон" от адреса 100 до 123 включительно :).

  Ну и, само собой, при попытке дизассемблирования с адреса 115 у вас абракадабра пойдет... мы об этом уже говорили и упоминали один из принципов фон Неймана.

Диагноз

  Полагаю, вы уже поняли, что значит "выучить язык ассемблера" :) и теперь с удовольствием кинете грязью в того, кто скажет вам, что это сложно ;)

  Что значит "выучить язык", и что значит "программировать"? А проводите сами границы между этими понятиями! Только имейте в виду, кто скажет "выучить - значит все команды запомнить - тот дурак :((.

  Слова и понятия извращать можно по-всякому. Переопределите собственный тип и носите свежеобмоченные пеленки в полной уверенности, что это носки... В моем понимании "знать ассемблер" и "изучить на ассемблере" - синонимы (хотя лингвисты могут придраться, но мне это пофиг). Согласно границам, которые провел для себя (гы... ну и для вас немножко) автор курса, ассемблер вы уже знаете, а вот программировать на нем пока еще не умеете...

  Да о чем это я, в общем-то? (Утомлен кофием, поэтому речь несвязна)? Просто хотел сообщить вам, что первая часть курса закончилась. Вооружившись справочником команд и прерываний, вы уже можете программировать под дос. Если вы внимательно штудировали предыдущие главы, то идеология этого дела (под дос) вам уже должна быть понятна как 2х2=100b.

  [C] Serrgio / HI-TECH

Категория: Программирование на Ассемблере | Добавил: MalCer (30.07.2009)
Просмотров: 966 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Реклама
Кабинет

Читать ЛС ()

Гость, мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизуйтесь!



Фраза дня:
Кто с нами

Сегодня были:
Статистика
Партнеры
Graffiti Decorations(R) Studio (TM) Site Promoter Mnogo-softa.net.ru-Софт,срипты,шаблоны и др. MEGA-ToP-ТОП раскрутка раскрутка сайтов. Рейтинг лучших сайтов
описание