Воробьёвы

(-:

№15. Повторение - мать учения. ИZDранное из RTFM_Helpers

КОЛОНКА РЕДАКТОРА

В спорах рождается истина... будь она проклята... (С) АБС.

Замахиваться на систему - занятие неблагодарное. Одно дело программировать, а совсем другое - пытаться что-то кому-то объяснить... да не просто объяснить, а объяснить популярно. Объяснить так, чтобы это поняли даже абсолютные профаны в программировании...

Я допускаю, что мое видение некоторых вопросов может быть весьма далеким от истинного. Более того, мне свойственно обманывать себя тем, что мои "ошибки" - это сознательное "абстрагирование", целью которого является увеличение "понимаемости" рассматриваемой темы за счет "умалчивания" некоторых несущественных на данный момент деталей... Ах, как легко в это вериться! Особенно если поверить так хочется... (С) ???

...

Чтож... я по прежднему буду "умалчивать". Благо мне есть чем утешится - огромное количество писем, приходящее на мой почтовый ящик, лишний раз свидельствует о том, что изучать асм по этой рассылке намного проще и интереснее, чем по многочисленным завернутым учебникам... Это радует :).

Но есть и обратная сторона медали. "Абстрагируясь", я зачастую не совсем верно освещаю те или иные моменты...

...

Знакомтесь: новый член команды HI-TECH, Хемуль Советикус, (в девичестве Бильбо Ленивчатый), наш технический редактор.

Прошу любить и жаловать! Рекомендую с особым вниманием читать рубрику "вдогонку к прошлом номеру", где он строго, но справедливо (и все же иногда субъективно!) будет фиксить идеологические ляпы наших авторов...

"Сенькс и хвала тебе, Хемуль Советикус!!", - закусив нижнюю губу, говорю я...

Да пребудет с тобой Сила!

ВДОГОНКУ К ПРОШЛОМУ НОМЕРУ

Сабж: "Давайте всегда RADIX 16 использовать, а не 10! Это не только настроит вас на дZенский лад (не челове-е-е-еческий, не десяти-и-ичный), но и избавит от целого ряда психоделических глюков... В общем - привыкайте считать по-компьютерному!!"

XC: Хотите приключений на свою ж... пардон, задницу - используйте RADIX, а другим (особенно начинающим) этим голову лучше не морочить. Помимо меньшей понимабельности текста с radix не равным 10, имеем весьма вероятные глюки при переносе фрагментов сорсов в другие места и обратно.

WU: ИМХО правильно. Лучше приучить ставить h, d, b _всегда_. Где надо и где не надо.

S: Хм... Наверное здесь мое ИМХО "сыграло". Ну не могу я спокойно видеть, как в сорце (не в dzebug'e) пишут что-нить наподобие: mov AX,0006h. Просто потом еще круче делают, если прога глючит: 0006h на 0006d меняют... Не знаю... просто мне показалось, что использование radix'а при переходе с дебага на нормальное программирование - как раз то, что нужно. Новичкам - легче, а тем, кто уже умеет программировать - им все равно пофиг...

AF: Ну, radix - безобидная штука. Злоупотреблять не надо и всё будет ок. В любом случае - решение зависит от 2-х вещей: - вкуса (что человеку больше нравится или с чем он лучше работает) и целесообразности (я с radix 16 набивал табличку для обработчика клавы (куча двойных слов для учёта регистра, alt, ctrl) - тут с ним было лучше кусочек сделать.

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

WU: Угу. Причем не только в дебаге. В любом низкоуровневом отладчике. И в hiew/qview. И в IDA. И по F3 в Нортоне... Ну ИМХО HEX на порядок удобнее чем DEC. _ИМХО_. В любом случае, если мы идем туда, куда мне кажется, мы идем ;) то нефиг извращаться - с DEC потом придется много мучится, особенно на логических операциях, когда надо будет в уме в BIN переводить. HEX переводить нечего, а вот DEC :(...

XC: Примечание: "приключения" - выражение не фигуральное. В руководстве по TASM проблемам, возникающим при использовании radix, посвящён целый раздел, который вы, видимо, не читали.

S: Ладно... проехали... Резюме: radix 16 must die. Да здравствует HEX! Так что ли?

Сабж: "CODESG segment".

XC: В TASM на такой (маленькие программы и обучение) случай имеются директивы .model, .code, .data, .stack.

S: По моему глубочайшему убеждению использование таких деректив на стадии обучения является большой методологической глупостью. Не спорьте! Покусаю...

WU: При обучении - _ни_в_коем_случае_ нельзя этого делать. Только нормальное определение сегментов. А вот когда чел уже понимает, что это, зачем и как, тогда можно сказать, что "такой вариант можно заменить на..." Начинать учиться ездить верхом на лошади надо без седла короче говоря.

Сабж: " Сегмент, он, как известно, может быть и сегментом кода, и cегментом данных, и сегментом стека... Как нам "указать", что это ИМЕННО сегмент кода?? Это нам позволяет сделать директива ASSUME :). Она "привязывает" сегмент с каким-либо "именем собственным" к определенному регистру.

XC: Неверная информация. Директива assume _только информирует_ ассемблер, какой сегментный регистр адрес какого сегмента _должен_ содержать, и генерить ли директивы при использовании имён переменных/меток в коде.

WU:) "привязывает" и "информирует" в данном случае ИМХО одно и то же :)

S: Я ж и написал не привязывает, а "привязывает". О чем базар?

XC: Например, если assume говорит, что адрес сегмента, в котором описана метка variable, находится в CS, а не в DS, то для инструкции mov ax,[variable] ассемблер сам, автоматически сгенерит префикс смены сегмента (напомню: по умолчанию переменные берутся из сегмента DS). Соответственно, если в assume указаны для сегментных регистров значения, отличающиеся от тех, которые они получат при загрузке программы, и мы не озаботимся загрузкой соответствующих значений в сегментные регистры, то программа не будет работать. В смысле, работать верно.

AF: Можно согласиться и/или сделать чуть более подробное описание назначения ASSUME или... или не делать. точнее сделать, но потом, попозже - не всё сразу.

WU: Мы еще не проходили сегменты настолько далеко, чтобы морочить ученикам голову. Это первый пример, пусть просто привыкнут и посмотрят.

Сабж: Напишите assume CS:CODESG и компилятор благополучно переведет это в цепочку "шестнадцатеричных циферек" и скажет процессору, что это код.

ХС:Ассемблер ничего процессору не говорит. Более того, assume, также как и proc, никакого кода не генерит. Эти директивы только могут повлиять на генерацию кода. Соответственно, интерпретация сегмента (код/данные) зависит только от того, в какой регистр будет загружен (при старте программы или нами) адрес сегмента. При том, что адрес сегмента может быть загружен сразу во все регистры (собственно, для .COM файлов это именно так).

WU: А кто-то с этим спорил ? :-/

S: Я - точно не спорил... я просто это объяснить пытался... образно ;)... но наверное, не совсем удачно получилось... Так что, реплей, пожалуй, сделать стоит: Напишите assume CS:CODESG и компилятор благополучно переведет это в цепочку "шестнадцатеричных циферек" и "навесит" на них табличку, где зеленым по черному :-P будет написано: "ЭТО - КОД".

Сабж: Напишите assume DS:CODESG и компилятор безуспешно попытается перевести это в цепочку шестнадцатеричных циферек и подсунуть их процессору как данные... То есть мало сказать компилятору, что ЭТО СЕГМЕНТ. Нужно еще и уточнить, КАКОЙ при помощи директивы ASSUME.

ХС: Неверно. Читате описание опций директивы segment, описание директивы GROUP, и правила загрузки сегментных регистров при старте программы.

WU: Следующим примером сделать Hello world, причем .ехе, где показать, как ставится ds. Потом что нибудь строковое, показать, что es еще есть. И что по идее, в маленькой проге их как правило удобно выставить в одно значение. Потом взять прогу с большим массивом данных, чтобы в один сегмент не влезали. И строковыми командами _туда-сюда_ погонять. Со сменой ds/es. Блин ! На начальном этапе если все сказать, как есть, они же умрут! Сейчас ИМХО бесполезно это рассказывать больше, чем Serrgio рассказал. И вообще больше, чем надо для написания этого комушника.

Сабж: Далее у нас следует директива org 100. Нужна она нам для того, чтобы компилятор понял, что мы хотим получить именно COM-файл.

XC: Неверно. Эта директива вовсе не означает, что у нас .COM файл (.EXE также могут иметь код, _адресация_ которого начинается со 100h). В математике это (ORG 100h для .COM) называется "необходимым", но вовсе не "достаточным" условием.

AF: org 100h лучше называть обязательным для .COM. они ж ещё ничего не знают - куды им впихивать столько инфы? не спорю, можно и вообще EXE в COM переименовать (или наоборот?) и будет так же работать, но ведь это изврат... :)

S: Хм... я знал, что это случиться... ваш покорные слуга в очередной раз оказался между Сциллой абстрагирования и Харибдой "правильного истолкования"... с одно стороны, если не абстрагироваться, то ведь не поймут нихрена, а с другой стороны - грань между оным и "неверным толкованием" больно уж тонка... Из двух зол я выбираю Сциллу (т. к. авторы большинства учебников почему-то выбирают Харибду).


В драке участвовали:
DZ Хемуль Советикус (ХС),
DZ Serrgio (S),
DZ WhiteUnicorn (WU)
DZ AlexFru (AF) 

ИZDРАННОЕ ИЗ RTFM_HELPERS

Dreamer (явно передZенствовал) вопрошает:

- При компиляции программ отладчик выдает код A2034: "must be in segment block" как избавиться от этой ошибки?

BELTSY aka Moderator-и-Отвечающий-На-Вопросы-Новичков отвечает:

- Во-первых, отладчик программы НЕ КОМПИЛИРУЕТ, этим занимается КОМПИЛЯТОР!!! Следовательно, при компиляции ОТЛАДЧИК НЕ может НИЧЕГО выдавать! Во-вторых, что ОН (разберитесь кто все-таки выдает компилятор или отладчик!!!) выдает???? какой-такой код???? Если компилятор, то он обычно выдает только ошибки и предупреждения, ну еще информацию о том как скомпилировалось. В-третьих, я не знаю как Вы пишете программы, поэтому не знаю кто и почему выдает ошибки!!! ВОПРОС НОРМАЛЬНО СФОРМУЛИРУЙТЕ!!! АГА???

Знаете, почему BELTSY так много восклицательных знаков лепит? А потому что достали его уже! Этот вопрос еще ничего... А то ведь и такой был:

"Скажите, пожалуйста, я написал программу... а она почему-то не работает... Что мне делать?"

И знаете, что он ответил? А догадайтесь сами...

McRas был одним из многих, спросивших:

- Почему, если адрес доступной RAM находится по адресу 40:14, мы пишем команду dump "d 0:413 L 2", а не "d 40:14 L 2"? Кстати, если ввести именно такую команду, то комп выводит 02 80, т.е. 640, без всяких обратных Hex.

BELTSY в очередной раз пишет:

- Это просто опечатка, надо вводить: "d 0:414 L 2" или "d 40:14 L 2".

Ну и вторая часть вопроса ("про обратный кехс") отпадает сама собой... Народ "Вдогонку к прошлому номеру" не читает. Это плохо. Надо читать!

Евгений Олейников в непонятках:

- Ваш ход мыслей мне нравится, изложение материала достаточно понятное. Но, поскольку, я самоучка, то и вопросы мои соответствуют. Из #9 (РАЗБОРКИ С ПРОЦЕДУРАМИ, п.3):

...

:0110 CALL 011E ;четыре раза вызываем подпрограмму, начинающуюся по адресу 011E...

...

Вот тут у меня вопрос: как мне узнать этот адрес 011E? Ведь когда я пишу программу, я не знаю точного адреса начала будущей подпрограммы.

Хороший вопрос и хороший ответ by BELTSY:

- На самом деле, мы все тут самоучки! :-)) В школе этому не учат :-(( Когда Вы пишете программу, Вы используете метки (label), а ассемблер их уже переводит в эти цифры. Узнать же адрес совсем не сложно. Зная, что программа начинается со сдвига 100h и количество байт которые занимает каждая команда, пишем программу и подщитываем. Думаю, про метки Serrgio еще будет говорить в рассылке.

Говорилось уже... чтоб самому последние мозги на высчитывании адресов не сжигать - используем TASM... ну или MASM... ну или NASM... ну или собственного производства компилятор... Это мы уже проехали в прошлом номере...

Анастезиолога наш гнилой базар вконец достал:

- Досталu, unsubscribe me!!!!!!!!!!!!!!!!!!! - орет.

- :-p.

Ну а че ему еще ответить?

А тут и повториться не грех: :-p

"Членство" "в группе" - дело добровольное. Сам подписался - сам и отписывайся. Пустым мылом по тому же адресу. Только к subscribe добавь un - и все путем будет...

Некто под именем "Северо-Западная МИС" явно хотит нарушить чье-то копилефт:

- Существует ли какой нибудь декомпилятор Виндовых *.hlp файлов? Если да, подскажите где взять.

Некто Димон (обкурившись, наверное) отвечает:

- Самый распростаненний *.hlp фалыз компилятор, словечко (ака Microsoft WORD), подготавливаеш *.rtf файл и ищи эксорт либно save as *.hlp долно быть, ну или у меня есть.

Это что ж за ворд у тебя такой навароченный? Уже 3000-й, штоль? Прям со стола Била-Гейтса ты его скомуниздил? А текст как java-апплет он у тебя сохранять умеет? Если умеет, то слышь, пропей ты мне этот ворд. Я давно ищу здоровую альтернативу своему JБилдеру... Собираемся, понимаешь ли, несколько фенечек для сайта залабать :)... информер какой-нить, например... или эвристический матюгальник по мотивам RTFM... Да чего уж там! С таким вордом горы воротить можно!! Пропей, а?

Северо-Западная МИС! Отправляю тебя... нет, не на три веселых буквы, а на сайт REVERSING.NET. Там есть замечательная конфа как раз по подобным вопросам... Кстати, этот дZенский сайт мы еще будем обозревать...

А вот почти что ксакепский вопрос Stepan Yar zадает:

- Каким образом можно записать BOOT-сектор? Может какое прерывание есть под это?

- BOOT сектор это всего-лишь самый первый сектор на диске, т.е. самые первые 512 байт. Поэтому писать в него можно темже прерыванием, что и в любой другой, т.е. биосовским 13h, функция ah=03.

BELTSY у нас не только модератор, но и ваще чел универсальный. Как-то: учащийся, кракер, программист, математик... Ну еще и "справочной системой по прерываниям" может быть... как оказалось... Как говорил поросенок Фунтик в минуты душевного аффекта: "У меня много всяких талантов"...

А вот еще один один абсолютно правильный вопрос от WarOrc'а:

- Я читаю сейчас на 5-й раз 4-й выпуск рассылки и так не могу понять, почему при выводе дампа и подсчете колличества RAM'а, мы меняли значения наоборот, т.е. там было написанно 81 32h, а переводить и складывать мы должны были 32 81h, ведь когда вы присваиваете регистру AX=27f4h Вы же присваеваете AH=27h, а AL=f4h и в регистре эти значения не меняются местами, по-крайней мере у вас там так написанно.

На что уставший BELTSY отвечает кратко:

- В регистрах числа хранятся в нормальном не перевернутом виде, а в памяти в перевернутом. Так компьютер устроен.

Но Yoshi этот ответ не нравится и он решает дополнить (совершенно верно, кстати, решает!):

- По данному случаю, хочу дать небольшой совет. Запомни, в памяти данные хранятся: МЛАДШИЙ БАЙТ ПО МЛАДШЕМУ АДРЕСУ. Например, мы определили в ассемблере слово:

... dw 1234h

Здесь 12h - старший байт, 34h - младший. Следуя принципу "младший байт по младшему адресу", выходит, что в памяти это слово будет храниться как 34 12 (проверь в отладчике!). Если к этому слову обращаться как к "слову", то все буден нормально, а если обращаться побайтно, то вот тут уже придется менять их местами. А с AX все в порядке: AH - старшая часть, AL - младшая. Присваивая AX значение 1234h (mov ax,1234h), AH присваивается 12h, AL присваивается 34h.

Хе... BELTSY... скажешь тоже... "так компьютер устроен"... Выражение из ряда "неисповедимы пути господни" :( Господни-то может и неисповедимы, а вот галимая логика создателей "первых IBM-совместимых" компьютеров вполне исповедима...

А вот тут целая дискуссия расгорелась! Это радует :)

Воинствующий Орк вопрошает:

- Чем отличается файл типа .com , от файла типа .txt, имхо, когда я смотрел в NC, то я никакой разницы в коде не заметил, но компьютер-то определяет, что этот надо интерпретировать как код для выполнения, так вот в чем различия, разъясните мне, плз.?

И дзенствующий Zero-Q начинает делиться своими дзенскими (однозначно!) соображениями:

- Создаем в любом ДОСовском текстовом редакторе файл со следующим содержимым:

  Alt+049,
  Alt+0192,
  Alt+064,
  Alt+0205,
  Alt+032

Сохраняем его, например как, 1.txt. Запускаем уже полюбившийся нам дZебургер, даем команды:

  -n 1.txt
  -l
  -g

и видим:

Нормальное завершение работы проги.

Даем команду:

  -u100

и видим:

  :0100 xor ax,ax
  :0102 inc ax
  :0103 int 20

Даем команду:

  -d100

и видим:

  :0100 31 C0 40 CD 20

Открываем файл 1.txt в встроенном редакторе NC видим туже самую последовательность хексовых цифр.

Вывод: разница между .com и .txt - в расширении имени. Программы можно писать и таким образом.

Мораль: никогда не пишите так программы. Читайте рассылку.

P.S. После проделанной процедуры, Билл Гей тс, по сравнению с Вами, покажется девственником.

Не вызывает сомнений! Это я про девственника...

А к вопросу от "привязывании прграммера к среде разработки" я целиком и полностью разделяю мнение Zero-Q: нормальному DZ - ему пофиг, где писать. Если под рукой только Лексикон - то можно и в Лексиконе (то, что удобнее все же на каком-нить языке - это уже совсем другой вопрос!)

BELTSY, испугавшись, что WarOrc ничерта из рассказанного Zero-Q не поймет, объясняет на пальцах:

- Короче так. По сути между txt и com никаких различий НЕТ. Шо там набор цифр, шо там тоже самое. Более того, был у нас txt, а мы его переименовали в com и стал он com-ом! Попробуй сделать так, ну и запусти его. Потом нажимай сразу на Reset и читай дальше. МС-ДОС не смотрит на код, а только на расширение. Если в конандной строке введешь С:\>aaaa.txt и нажмешь , то она ничего не сделает, а как-тока переименовали - все пошло... на Reset жми. В коде различий НЕТ!!! для ДОСа тока в расширениях. А вот в других операционках, например UNIX, расширений вообще нету. Надеюсь с расширениями разобрались...

Не знаю, как в юниксе (не видел), а вот в некоторых дистрибутивах линукса "исполнимость" файла определяется по следующий сигнатуре: 77 69 6E 64 6F 7A 65 20 6D 75 73 74 20 64 69 65 (шутка).

Но, как говориться, надейся на лучшее, а готовься к худшему...

А именно, что с тобой не согласятся...

А именно - не согласится Yoshi:

- Не совсем согласен. MS-DOS, все-таки, смотрит на код при определении формата файла. Например, если дос увидит в сигнатуре файла (сигнатура - здесь первые два байта файла) код 5A 4D, то есть "MZ" или "ZM", то этот файл дос определяет как EXE, если что-то другое, то COM. Можете проверить (правда для этого нужно правильно указывать заголовок EXE файла формата MZ).

Пример: Файл COMMAND.COM в windows имеет размер 95,192 Кб.

Как это COM файл имеет размер более 65,536 Кб??? Да просто это самый настоящий EXE, который переименован в COM.

MZ - это вам не версия винды, в мбр прошитая. Были личности и поамбициознее Гейтса! Например автор-создатель спецификации EXE намного круче поступил! Это мы, убогие, думаем, что MZ - это сигнатура. На самом деле MZ - это его инициалы :)). Ну и сигнатура, впрочем, тож... но это вторично...

Тему "про расширения" добивает-таки BELTSY:

- Согласен, но не со всем. Возьми переименуй ехе-ный файл в тот же txt. Ну введи его в командной строке. запустит??? а фиг запустит!!! так что в первую очередь дос смотрит на расширение, а уж потом на все остальное!!!

Хе... а какой вопрос простой был... "про расширения"... и как его DZ братья замутили... Правильной дорогой идете, товарищи!! Наш КПСС (Крутой Парти Смертельно Совращенных) это весьма и весьма одобрям-с...

WarOrc, не иначе, всерьез принялся дZенствовать (это мы тож одобрям-с):

- Кста что значит комманда jnz, мы ее не проходили, а в 13 выпуске в оптимизированном коде графического редактора она есть, или это очередная очепятка и это вовсе не jnz, jne? Было бы еще хорошо, если бы в каждом выпуске если появляется новая комманда разъясняли, что она делает, а то я вот долго думал на какие такие 3 буквы нужны комманды dec и inc и что они делают, потом подумалось, что одна отнимает из значения хранящегося в стеке 0001h, другая прибавляет 0001h.

Грешен WarOrc, вопрошающий справочную информацию... (хе, а любопытная у него гипотеза на счет стека!)

Грешен и Yoshi, отвечающий на этот риторический вопрос...

- JNZ значит абсолютно то же, что JNE.

JNE - это мнемокод ассемблера (NASM/MASM). При ассемблировании она "превращается" в JNZ.

JNZ (Jump if Not Zero) и JNE (Jump if Not Equal) - абсолютно одинаковы. Попробуй в debug'e ассемблировать эти две команды - увидишь. Эти команды определяют, надо ли делать переход по значению флагов процессора (О флагах в следующих выпусках рассылки, как говорил Serrgio).

Например, команда cmp ax,12h проверяет, равенство AX на 12h путем вычитания одного операнда из другого. После этой операции она устанавливает нужные флаги. Если AX действительно равен 12h, то Zero Flag (флаг нуля) установится в единицу. Команды JNE и JNZ, в зависимости от значения этого флага делают переход. Если ZF = 0, то переходят, если ZF = 1, то не переходят. JE и JZ - наоборот, если ZF = 0, то не переходят, если ZF = 1, то переходят. DEC - декрементирует (уменьшает на единицу значение ее операнда) INC - инкрементирует (увеличивает на единицу значение ее операнда)

  xor ax,ax ; AX = 0
  inc ax ; AX = 1
  inc ax ; AX = 2
  dec ax ; AX = 1
  dec ax ; AX = 0.

WarOrc! Обрати внимание, как ради тебя народ распинается! Надеемся, ты оправдаешь "высочайшее доверие партии и правительства! ;)

WarOrc и рад стараться доверие оправдывать:

- Что делает комманда XOR? - вопрошает.

- Выполняет операцию xor. есть такая операция в математике, как сложение, вычитание, а это xor!" - эт BELTSY отвечает.

Как говаривал В. И. Ульянов-Ленин в минуты душевного... хм, это уже было выше?... В общем, говоривал он "формально верно, а по существу - издевательство!". С одной стороны - это такая же глупость, что и "скажите пожалуйста, что делает команда "+". Но с другой стороны... не всех же в школе булевой алгебре учили!

Так что прав все же Yoshi, ответивший:

- XOR - побитовая операция логического исключающего ИЛИ над двумя операндами, результатом которой является "истина", если только один из двух операндов имеет значение "истина". И "ложь", если оба операнда имеют значение "ложь" или "истина". (Короче, если биты разные, то результат - 1, а если одинаковые, то результат - 0).

Таблица истинности:

  A B C
  ====
  0 0 0
  0 1 1
  1 0 1
  1 1 0

С помощью XOR можно инвертировать биты:

  xor ax,ax  ;очистили ax
  xor al,01h ;инвертировали первый бит, теперь al=0001b
  xor al,01h ;инвертировали первый бит, теперь al=0000b .

А еще Zero-Q поведал о том, как он дZенствовал над, прямо скажем, непростой и мозгопрочищательной задачкой:

- Привет All, в девятом выпуске, всем нам известной рассылки "Низкоуровневое программирование для ДZенствующих", в пункте четвертом [4] есть пример программы, где мы с Вами рисуем окошки на дисплее. Я не стал лениться и нарисовал тринадцать таких окошечек при помощи следующей последовательности нуликов и единичек:

  :0100 mov ax,0600
  :0103 mov bh,70
  :0105 mov cx,0000
  :0108 mov dx,184f
  :010B int 10
  :010D call 0133
  :0110 call 0133
  :0113 call 0133
  :0116 call 0133
  :0119 call 0133
  :011C call 0133   -65 байт.
  :011F call 0133
  :0122 call 0133
  :0125 call 0133
  :0128 call 0133
  :012B call 0133
  :012E call 0133
  :0131 int 20
  :0133 sub bh,10
  :0136 add,cx,0101
  :013A sub dx,0101
  :013E int 10
  :0140 ret

далее пораскинув немного мозгами и строго следуя советам многоуважаемого SERRGIO, а также АБСОЛЮТНО правильным программерам, захотел я было CALL LOOP-ом закрутить, да вот загвоздка, а точнее КОНКУРЕНЦИЯ, на CX претендуют сразу и INT 10 и LOOP. Но решил я не отчаиваться и закрутить все это еще через СТЕК. Думал я долго и кипели мозги (все как по прогнозу SERRGIO), и придумал. Ура! Кричу я, брызгая слюной на свой дисплей, а тут как кирпичом по голове (наверное это и имеет ввиду SERRGIO);

В СТЕК? В СТЕК? Да тут на стек этот тоже своего рода КОНКУРЕНЦИЯ. Когда выполняешь CALL но пихает в стек адрес следующей за ним команды, для последующего возвращения по этому адресу командой RET (будь она неладна). Не это не кирпичом по голове, а прямо как-то веслом по плечу. Вообщем дZенствовал долго и на дZенствовал я следующее:

  :0100 mov ax,0600
  :0103 mov bx,700C
  :0106 mov cx,0000
  :0109 mov dx,184f
  :010C int 10
  :010E push cx
  :010F jmp 0113
  :0111 mov bl,cl
  :0113 pop cx
  :0114 add cx,0101  -42 байта.
  :0118 push cx
  :0119 sub dx,0101
  :011D sub bh,10
  :0120 int 10
  :0122 xor cx,cx
  :0124 mov cl,bl
  :0126 loop 0111
  :0128 int 20

Во как закрутил! Вы представляете! И эта штука работает! Да к тому же так как хотелось. Хотя хотелось CALL LOOP-ом завернуть. Через некоторое время получилось следующее:

  :0100 mov ax,0600
  :0103 mov bx,7000
  :0106 mov cx,0000
  :0109 mov dx,184F
  :010C int 10
  :010E cmp bl,0C
  :0111 jz 0124        ;кстати я пишу в своем дZебургере je, а он сам
  :0113 add cx,0101    ;переводит на jz. Кто знает подскажите почему?
  :0117 sub dx,0101
  :011B sub bh,10
  :011E inc bl -38 байт.
  :0120 int 10
  :0122 jmp 010E
  :0124 int 20

А CALL LOOP-ом я так не закрутил. Дался он мне и все тут. Может у кого получалось разрешить такую вот заморочку. Пишите.

Правильной дорогой идешь, Zero-Q!

А еще Zero-Q вот какой вопрос донимает (вначале - небольшая пламенная речь даже!):

- Мы. То бишь программисты. Будь мы начинающими или с опытом. Все мы связаны, так сказать одной цепью - числами. А именно, то с десятичными, то с хексовыми (позвольте мне их так называть, т.к. так короче), и др.

А вот я не знаю как мне произносить данное число:

1С0BF или 2014h.

То есть я знаю, что это за число, а вот как мне его произносить (например последнее) точно не могу Вам сказать.

2014h - то ли это две тысячи четырнадцать, то ли это два ноль один четыре.

Или вот например, смещение:

:0100

я говорю: - смещение сто.

Или, например:

- программа типа .com загружается в память начиная со смещения сто, или со смещения один ноль ноль?

Как правильно?

Или же когда об этом говорят программисты, то они всегда поймут друг друга?

То есть они знают о чем в данный момент идет речь?

Уважаемые дZенствующие братья и сестры подскажите, есть ли какая-нибудь разница в произношении чисел хексового ряда!

Тута даже я (Serrgio) не выдерживаю:

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

Радует, что народ уже самостоятельно что-то писать начинает :). Это сразу видно!

Alexey_A Bochkaryov вот чего спрашивает:

- Возник у меня вопрос: ну,например, есть у меня в DX циферки (кол-во кластеров или еще что-то); как их вывести на экран? Ведь это не байт,а слово! Я пробовал пересылать в сегмент данных, а потом - через mov ah,09 int 21h выводить на экран. Что-то не получается. Подскажите!

2k (2048 то бишь) ему отвечает:

- Необходимо:

1. перевести циферки (в DX) в буковки :) т.е. в соответствующие символы :

  0 --> 48 ( ASCII 48 = '0' )
  1 --> 49
  ..
  9 --> 57

2. сформировать строку из этих символов

3. вывести :

  mov ah,09
  int 21h

Ну , короче, вот что получилось:

;========================================
  MODEL tiny
  DATASEG
    stro db 5 dup (' '),'$' ; тут формирование строки
  CODESEG
   STARTUPCODE
   
    mov dx,12334 ; выводимое число (по условию в DX)
   
    mov ax,dx
    mov bp,4
    mov bx,0Ah ; для перевода в dec

   n_ch:
    xor dx,dx
    div bx ; ax=ax/bx , dx -- остаток
    add dx,48 ; можно так : or dx,30h
    mov [stro+bp],dl ; очередной символ
    dec bp ; подготовка к следующ. символу
    cmp ax,bx ; может хорош уже делить?
    jg n_ch ; если ax>10, то еще немножко поделим

    add al,48 ; перевод последнего числа
    mov [stro+bp],al ; ну и запись

    lea dx,stro ;
    mov ah,9 ; вывод
    int 21h ;

    int 20h ; выход

  END
;========================================  

ЭТО вполне можно еще оптимизировать...

2k!! Молодец!! Честь тебе и хвала!! Только с такими знаниями ник 2k не очень подходит. Как минимум - 2G нужно! ;).

Некто Ян предлагает свои услуги:

- Сдравствуйте. Пригласите пожалуйста меня переводчиком.

Естественно, Модератора это садит на коня:

- В ДАННУЮ ГРУППУ ДОЛЖНЫ ПОСТУПАТЬ ТОЛЬКО(!) ВОПРОСЫ И ОТВЕТЫ СВЯЗАННЫЕ С АССЕМБЛЕРОМ, ПРОГРАММИРОВАНИЕМ И Т.П. !!!!!!!!!!!!! ПОДОБНЫЕ СООБЩЕНИЯ НЕ В ТЕМУ!!!!!!!!!!

Дорогой Ян! Мы хотели на твое письмо ответить в привате, но наш сервер заматерился, что адреса такого адреса (твоего) в природе не существует... Так что перезвони, плиз, при прочтении оного. Только чур не в группу!

Эх... ну какой же программер не любит математику? :)

2k спрашивает:

- Расскажите кто знает как извлечь корень. Это вообще можно сделать не применяя разложение в ряд?

BELTSY:

- да, вполне можно. вообще этих способов до фига. ну вот, че первое приходит в голову, метод Герона (или Ньютона, где как): если хотим вычислить x=a^(1/2), a>0, x>0, то X = (a/X + X) / 2 - индекс, x0 - на глаз выбераешь. пример: 2^(1/2), x0 = 1.5, получим x1 = 1.417.... x2 = 1.414216..., x3 = 1.41421635624..... при хорошем x0 сходимость не плохая...

А что? Вполне дZенский диалог!

А вот следующие вопросы так и остались без ответа:

Олег Плуток:

- Разрабатываю платку ввода информации по шине PCI на базе PLX9050. Может кто подскажет, как работать с локальной памятью, если адрес 32 разрядный (под DOSом)? Вот например, нужно мне залить данные в память по адресу 0xE4001000. Как это сделать ? Если можно то подробнее .

Stepan Yar:

- Где можно подробнее прочитать про программирование 3D-графики? .

- Люди, по какому адресу находиться видеопамять в режиме 640x480?

Yoshi:

- Не подскажет ли кто, как поменять контрольную сумму CMOS после отключения пароля командами

  mov al,5Eh
  out 70h,al
  xor al,al
  out 71h,al

Заранее благодарен!

Ну что, народ!! Кто ответит??

АНОНС

В следующее воскресенье... тоже что-нибудь будет... ЕСЛИ.