==========================================================================

RusFAQ.Ru Frequently Asked Questions

==========================================================================

Редакция от 13.12.2003                      Copyright (c) 2003 RusFAQ team

 

Данный документ является подборкой ответов на наиболее популярные вопросы, задаваемые пользователями RusFAQ.Ru (раздел "Ассемблер").

Если Вы не нашли здесь ответа на свой вопрос, то попробуйте поискать его в книгах П.Абеля и С.Зубкова, а также в MSDN(в том случае, если вопрос относится к нахождению определенной функции WinAPI). Если же Вы и в них не нашли ответа, то попробуйте задать свой вопрос на сайте www.RusFAQ.ru

Чтобы получить качественные ответы, достаточно ознакомиться со следующей краткой справкой: http://www.bobjohnson.nm.ru/faqus.html#q6

 

==========================================================================

 

Содержание:

 

1.                С чего начать? Какие книги и документацию посоветуете? Где их найти?

2.                Почему я копирую текст из Зубкова, пытаюсь его скомпилировать, но вылетает куча ошибок?

3.                Где найти списки прерываний/ф-цийWinAPI/портов с подробным описанием?

4.                Что такое MSDN?

5.                Какой необходим инструментарий и где его найти?

6.                Как создать COM-файл по ассемблерному исходнику?

7.                Какими оболочками пользоваться?

8.                Можно ли создавать программы для Win32 ДОС-овскими компиляторами.

9.                Пишу программу для ДОС, а вместо русских букв каракули какие-то вылезают...

9.a.  Моя первая программа для ДОС не работает  в Windows XP 

10.            Как мне выводит на экран числа?

11.            Как использовать ассемблерный код в языках высокого уровня?

12.            Зачем нужен ассемблер в наше время? Каковы его преимущества перед ЯВУ?

13.            Что можно сделать на ассемблере? Каковы его возможности?

14.            Как работать с I/O портами, например, с LPT?

15.            Как делать точные временные задержки, не зависящие от мощности машины?

16.            Как завесить машину?

17.            Как перезагрузить машину?

18.        Как мне производить запись в BOOT-сектор?

19.            Где найти исходники вирусов/троянов?

20.            Где взять документацию по SoftICE, IDA и другим отладчикам\дизассемблерам? Сами отладчики?

21.            Как переводить числа из одной системы счисления в другую (D<->H<->B)?

22.            А числа с запятой?

23.            Как использовать прерывания в защищенном режиме? Как работать с графикой\текстом из-под PM?

24.            Как программировать звуковую карту под ДОС? А мышь? НЖМД?..

25.            Киньте, плиз, исходники БИОСа.

26.            Где взять исходники прерываний BIOS\DOS?

27.            Я взял код прошивки BIOS и дизассемблировал его. Фигня получается.

28.            Что такое сопроцесcор. Как с ним работать?

29.            Как работать c ф-циями Sin/Cos/Tg/Ln/ArcSin и пр. ?

30.            Как убрать «моргание» изображения при работе с графикой ?

31.            Как сделать так, чтобы не работали одновременно 2 копии моей программы?

32.            Как выдвинуть лоток CD-ROM'а

33.            Как под Win32 работать с портами/памятью?

34.            Как написать свой драйвер под Win32?

35.            Что такое «кольца защиты» и зачем они нужны?

36.            Как мне корректно подсесть на Ring-0?

37.            Как програмировать под Linux на ассемблере?

38.            Как заставить мой комп(или модем) работать быстрее?

39.            Как «ломать» программы ?

40.            Что такое RTFM, IMHO, AFAIK и другие слова, столь часто употребляемые экспертами RusFAQ.ru?

41.            Что такое “станция BBS"?

42.            Кто и зачем до сих пор использует DOS. Какой смысл сейчас
писать что-то для него?

 

==========================================================================

 

Q: С чего начать? Какие книги и документацию посоветуете? Где их найти?

A: Если Вы начинаете с нуля (т.е. это Ваш первый язык программирования), то лучшим вариантом является книга:

О.Калашников "Ассемблер? Это просто!"

http://www.kalashnikoff.ru

Книга написана живым языком и легко усваивается.

Продолжение для программирования под Win32 лежит на

http://learnasm.narod.ru

а также на

http://subscribe.ru/catalog/comp.prog.assembler

 

Если же Вы являетесь опытным программистом, и уже владеете другими языками программирования, то можно посоветовать книги:

В.Юров "Ассемблер. Учебник" (Издательство Питер).
C
.Зубков "Ассемблер - язык неограниченных возможностей" http://www.bobjohnson.nm.ru/files/zubkov.zip

 

Следующая книга является быстрым и увлекательным способом изучения языка ассемблера:

“Вирусы, "черви", "драконы" и резиденты на службе прогресса при изучении языка ассемблера и системы MS-DOS"

http://kalaidjian.nm.ru/tutori.rar

 

Также часто советуют почитать следующие книги или иметь их под рукой для справки:

П.Абель «Ассемблер и программирование для IBM PC»

http://www.bobjohnson.nm.ru/files/asm-abel.rar

Р.Журден "Справочник программиста на персональном компьютере фирмы IBM"

http://www.dospage.by.ru/files/jourden.zip

Другие популярные книги см. на

http://home.od.ua/~blackw/WinAsm/winasmbooks.html

Тома Библиотеки Системного Программиста можно скачать:

http://hp.vistcom.ru/doc/bsp

 

В процессе изучения да и для дальнейшей работы Вам почти точно понадобятся списки прерываний\портов\карты памяти и пр.справочные данные из архива Ральфа Брауна, а также справочник по WinAPI (если Вы будете программировать под Win32).

 

Для программирования под Win32 часто советуют изучить «туториалы Iczelion'а»

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

http://www.wasm.ru/publist.php?list=1  (Уроки Win32API)

http://www.wasm.ru/publist.php?list=2  (Уроки PE)

http://www.wasm.ru/publist.php?list=3  (Уроки VXD)

http://www.wasm.ru/publist.php?list=4  (Уроки ODBC)

 

Если в процессе изучения у Вас возникли вопросы, и Вы не смогли найти на них ответ, то поищите аналогичные вопросы в архиве вопросов и ответов RusFAQ.ru:

http://rusfaq.ru/cgi-bin/search.cgi

 

Если и там нет нужного Вам ответа, то задайте вопрос экспертам на http://www.RusFAQ.ru

 

==========================================================================

 

Q: Почему я копирую текст из Зубкова, пытаюсь его скомпилировать, но вылетает куча ошибок?

A: Дело в том, что приведенный выше электронный вариант является отсканированной версией книги, а не перепечаткой, поэтому некоторые названия могут быть написаны русскими буквами (например имена регистров). «На глаз» разницы не заметно, а компилятор выдает ошибку.

 

==========================================================================

 

Q: Где найти списки прерываний/ф-цийWinAPI/портов с подробным описанием?

A: Описание прерываний\портов\опкодов и пр.:

http://www.pobox.com/~ralf

 

Справочники по WinAPI можно взять из MSDN, RSDN.

Или скачать: http://learnasm.narod.ru/download/win32.rar

Если у Вас установлен пакет Delpi или C++ Builder, то справочник можно найти в папке C:\Program Files\Common Files\Borland Shared\MSHelp. Правда все эти варианты только на английском. На русском можно прочитать только обрывки:

http://www.bcbdev.ru/winapi.htm, также можно зайти на subscribe.ru и подписаться на рассылку "Win API на русском"

Так что учи английский, мой читатель =)

Справочник по функциям DirectX http://learnasm.narod.ru/download/directx.rar

Справочник по функциям OpenGL http://learnasm.narod.ru/download/opengl.rar

 

==========================================================================

 

Q: Что такое MSDN?

A: MSDN ("Microsoft Developer Network") - на сегодняшний день крупнейший архив разнообразной документации (описание API-функций, различная документация, технические статьи, примеры программ и пр.). Из-за большого количества материала MSDN размещается на нескольких компакт-дисках и требует ~2 Гб дискового пространства для полной установки.
MSDN доступен на сайте Microsoft
(http://msdn.microsoft.com), но просмотр в on-line, как правило неудобен. Microsoft дают возможность подписаться на MSDN и его обновления, (естественно за деньги, при том довольно большие), которые будут поступать по мере выхода. http://msdn.microsoft.com/subscriptions/ Став подписчиком, кроме непосредственно MSDN вы будете получать также некоторые другие продукты M$ (DDK, MASM и т.д.). С января 2002 года MSDN интегрируется c MS Visual Studio.NET Help.

В  общем, MSDN - один из инструментов, которые должен иметь каждый более-менее серьезный программист.

 

==========================================================================

 

Q: Какой необходим инструментарий и где его найти?

A: Для разработки программ стандартным набором является:

 

a)    Прямые руки, растущие из нужного места

b)    Текстовый редактор или интегрированная оболочка для набора текста программы(см. ответ на след. вопрос).

c)    Компилятор+линковщик – набор из программ, переводящих текст Вашей программы в машинный код и собирающих исполняемый файл.

d)    Отладчик – программа, с помощью которой можно пошагово выполнять написанную Вам(и не только Вами =) программу, одновременно следя за изменением содержимого стека, памяти, регистров, флагов и т.д., с целью выявления неочевидных ошибок или просто для наглядного представления выполнения программы. Работать с отладчиком необязательно, но рекомендуется.

 

Для начала может понадобиться пакет TASM или MASM (возможны другие варианты компиляторов, но эти обычно рассматривается наиболее подробно, поэтому лучше с одного из них и начать), а также отладчик TD или AFDPRO(также возможны другие варианты, но эти наиболее простые в освоении).

 

TASM2.0

http://int21.narod.ru/develop/tasm.zip

Доки к нему:

http://blackwolf2.virtualave.net/WinAsm/tasmdoc1.zip

 

MASM6.1

http://int21.narod.ru/develop/masm.zip

Доки к нему:

http://int21.narod.ru/doc/masmdoc.zip

 

AFD, Debug, TD, DG можно скачать разом с http://www.dospage.by.ru/files/debug.zip

 

Отладчик SoftIce2.8 можно скачать с

http://www.dospage.by.ru/files/sidos-28.zip

 

Если Вы решили начать программировать под Win32, то в этом случае потребуется компилятор MASM32(см. замечание по выбору компилятора выше)

http://www.wasm.ru/tools/7/masm32v8.zip

В этот пакет входит практически всё, что может понадобиться для программирования под Win, в том числе туториалы Iczelion’a, различные полезные примеры программ для Win32 и многое другое.

 

Желающим поработать с NASM, FASM и др. добро пожаловать на

http://www.wasm.ru/toollist.php?list=7

 

FASM

http://flatassembler.net/

 

NASM

http://sourceforge.net/projects/nasm

 

==========================================================================

 

Q: Как создать COM-файл по ассемблерному исходнику?

A: Процитируем соответствующую главу из книги О.Калашникова «Ассемблер? Это просто!»:

 

Допустим, вы создали в текстовом редакторе файл с именем PROG.ASM.

 

** Если Вы используете Macro Assembler версии 5.00 – 5.10 (MASM 5.00 – 5.10):

В командной строке необходимо указать следующее:

 

> MASM.EXE PROG.ASM

 

В результате создается файл PROG.OBJ, который нужно слинковать при помощи компоновщика (линковщика) LINK.EXE, который входит в комплект данного пакета:

 

> LINK.EXE PROG.OBJ /t

 

Компоновщик создаст PROG.COM, который и необходимо запускать. Это и будет машинный код ассемблерной программы. Параметр "/t" указывает LINK.EXE, что необходимо создать файл типа COM.

 

** Если Вы используете Macro Assembler версии 6.11 – 6.13 (MASM 6.11 – 6.13):

 

В командной строке необходимо указать следующее:

 

> ML.EXE PROG.ASM /AT

 

В результате создается два файла: PROG.OBJ и PROG.COM. PROG.OBJ, как правило, нам больше не понадобится, и его можно удалить, а PROG.COM запускаете на выполнение. Это и будет машинный код ассемблерной программы. Параметр "/AT" указывает программе-ассемблеру (MASM), что после ассемблирования, в случае, если ошибок не будет обнаружено, следует запустить компоновщик (LINK.EXE) и передать ему параметры для создания файла типа COM.

Обратите внимание, что параметр "/AT" должен быть указан ЗАГЛАВНЫМИ символами!

 

** Если Вы используете Turbo Assembler (TASM):

 

В командной строке необходимо указать следующее:

 

> TASM.EXE PROG.ASM

 

Если prog.asm не содержит ошибок, то в результате создается файл PROG.OBJ, который нужно скомпоновать при помощи компоновщика (линковщика) TLINK.EXE:

 

> TLINK.EXE PROG.OBJ /t

 

TLINK.EXE создаст файл PROG.COM, который и нужно запустить на выполнение. Параметр "/t" указывает TLINK.EXE, что необходимо создать файл типа COM.

 

==========================================================================

 

Q: Какими оболочками пользоваться?

A: Это вопрос вкуса. Многие программисты не используют дополнительные оболочки вообще. Т.е. программа набирается в FAR, Norton Commander, Bred2 или любом другом текстовом редакторе и сохраняется в определенной Вами рабочей папке. Затем запускается пакетный BAT-файл, который помещается в одну папку с компилируемой программой. Например такой батник можно использовать для сборки и запуска программ для Win32:

 

--run.bat----------------------------------------

@echo off

REM Путь к компилятору и линковщику. Подкорректируйте для Вашего случая.

SET PROGPATH = c:\masm32\bin

if exist %1.obj del %1.obj

if exist %1.exe del %1.exe

REM компилируем:

%PROGPATH%\ml /c /coff /nologo %1.asm

REM Линкуем:

%PROGPATH%\Link /SUBSYSTEM:WINDOWS /MERGE:.rdata=.text %1.obj > nul

del %1.obj

REM Запускаем:

%1

-------------------------------------------------

 

Теперь Вам достаточно написать в командной строке:

 

> RUN PROG

 

И Вы получите программу prog.exe, которая тут же и запустится.

 

Если же Вы привыкли к интегрированным оболочкам, типа тех, что поставляются с Turbo Pascal, TD и пр., то воспользуйтесь оболочкой Turbo Shell Сергея Чехуты

http://www.whitetown.com/

 

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

 

==========================================================================

 

Q: Можно ли создавать программы для Win32 ДОС-овскими компиляторами?

A: Нет

 

==========================================================================

 

Q: Пишу программу для ДОС, а вместо русских букв каракули какие-то вылезают...

A:

1. Скорее всего Вы пишете не в DOS-кодировке, а в Win-1251(например в Блокноте). Используйте редакторы Bred2(заменитель Блокнота с возможностями перекодировки) или FAR - там можно изменять кодировку в редакторе нажатием F8.

2. Если это не помогло (например, если у Вас англоязычная ОС), установите руссификатор, например, KeyRus.

 

==========================================================================

 

Q: Моя первая программа для ДОС не работает в Windows XP

A: В самом начале исходника программы поставьте переход в текстовый видеорежим:
mov ax,03h
int 10h
 

==========================================================================

 

 

Q: Как мне выводит на экран числа?

A: Перед выводом на экран число следует разбить на цифры и каждую цифру выводить отдельно, при этом прибавляя к каждой из них 30h. Обратите внимание на таблицу ASCII – числам соответствует ряд, начинающийся с 30h.

Вот пример такой программы(для простоты использован сопроцессор):

 

--writeint.asm-----------------------------------

.387                     ;Используем сопроцессор
.model small
.data
chislo dw 9000           ;Число для вывода
cifra dw ?
delitel dw 10

.code
main:
push @data               ;Инициализация сегмента данных
pop ds

xor cx, cx               ;Обнулим СХ
finit                    ;Инициализация сопроцессора

cycle:
fild delitel             ;Загрузим делитель (т.е. 10)
fild chislo              ;Загрузим число для вывода
fprem                    ;Получим остаток от деления
fistp cifra              ;и выгрузим его в cifra
fild chislo              ;Загрузим число для вывода
fidiv delitel            ;Разделим на 10
fistp chislo             ;Выгрузим частное от деления на место изначального числа
cmp cifra, 5             ;Корректируем результат округления
jb lab
dec chislo
lab:
push cifra               ;Сохраним цифру в стеке
inc cx                   ;И увеличим счетчик разрядов
mov ax, chislo
test ax, ax
jnz cycle                ;Если число еще не ноль, то повторим

sub_loop:                ;Вывод на экран
pop ax
add ax, 30h
int 29h
loop sub_loop

mov ah, 4ch              ;Выход и возвращение
управления ОС
int 21h
end main
-----------
--------------------------------------

 

Работу программы полезно проследить в отладчике, например в TD.

(окно стека сопроцессора у последнего можно вызвать с помощью пункта меню View->NumericProcessor)

 

==========================================================================

 

Q: Как использовать ассемблерный код в ЯВУ

A:

1. Ассемблерными вставками или операторами типа inline(машинный код).

Такой способ подразумевает вставку ассемблерного кода в виде команд ассемблера или машинных кодов прямо в текст программы на ЯВУ. Этот способ удобен, если нужно использовать небольшие фрагменты ассемблерного кода.

 

В Паскале:

Asm

... тут Ваш текст...

End;

 

Например:

 

--primer.pas-------------------------------------

BEGIN

asm

xor ah, ah

int 16h

end;

END.

-------------------------------------------------

 

Ассемблерная процедура оформляется так:

Procedure myproc; assembler;

Asm

...тут Ваш текст...

End;

 

В С/С++:

_asm{ ... тут Ваш текст... }

 

2. Используя внешние ф-ции или процедуры. В этом случае ассемблерный код оформляется в виде текста отдельной программы, котоую можно компилировать и отлаживать независимо от основной программы на ЯВУ.

Передача аргументов происходит через стек. При этом в Паскале аргументы ф-ции или процедуры передаются в стек слева направо (т.е. в вершине стека оказывается крайний справа аргумент), а в С\С++ справа налево.

 

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

Модифицированный пример из Юрова:

 

--pas_asm.pas------------------------------------

uses CRT;

{$D+} {включение полной информации для отладчика}

procedure asmproc(ch: char; x, y, kol:integer); external;

{ch - символ, x, y – координаты, kol - число выводов}

{процедура обявлена как внешняя (external)}

{$L asm_pas.obj}

BEGIN

   clrscr; {очистим экран}

   asmproc('O', 1, 4, 5);

   asmproc('K', 9, 2, 7);

END.

-------------------------------------------------

 

--asm_pas.asm------------------------------------

MASM

.model small

.stack 256

.code

asmproc     proc  near

PUBLIC asmproc           ;объявлена как внешняя

      push  bp           ;пролог

      mov   bp, sp

 

; позиционирование курсора:

      mov   ah, 02h      ;номер ф-ции

      mov   dh,[bp+6]    ;dh = y

      mov   dl,[bp+8]    ;dl = x

      int   10h

 

; вывод символа:

      mov   ah, 09h      ;номер ф-ции

      mov   al,[bp+10]   ;al = ASCII код символа

      mov   bl, 07h      ;bl = цвет символа и заднего фона (атрибут)

      mov   bh, 0        ;bh = номер видеостраницы

      mov   cx,[bp+4]    ;cx = число выводов

      int   10h

 

      pop bp

      ret 8              ;очистка стека (8байт) и возврат из процедуры

asmproc     endp

end

-------------------------------------------------

 

asm_pas.asm следует скомпилировать:

 

> tasm asm_pas.asm

 

Получившийся в результате asm_pas.obj положите в папку с pas_asm.pas и окомпилируйте pas_asm.pas

 

Чтобы стал понятен принцип обмена аргументами, рассмотрим фрагмент стека после выполнения команд пролога:

    ...

+---------+

|   bp    |   <- Вершина стека (ss:sp=ss:bp). Результат команды push bp

+---------+

|   ip    |   <- ss : [bp + 2]   Результат команды call asmproc

+---------+

|   kol   |   <- bp + 4

+---------+

|    y    |   <- bp + 6

+---------+

|    x    |   <- bp + 8

+---------+

|   ch    |   <- bp + 10

+---------+

|Дно стека|   <- ss:ffff

+---------+

    ...

 

При работе с с\с++ мы бы заметили обратный порядок заполнения стека аргументами.

 

Теперь рассмотрим более "культурный" вариант программы на ассемблере с применением директивы ARG (подробнее читайте у Юрова):

 

--asm_pas.asm------------------------------------

MASM

.model small

.stack 256

.code

asmproc     proc  near

arg   kol:WORD, y:WORD, x:WORD, chr:BYTE=a_size

;в a_size лежит число байт, занятых аргументами

PUBLIC asmproc           ;объявлена как внешняя

      push  bp           ;пролог

      mov   bp, sp

 

; позиционирование курсора:

      mov   ah, 02h      ;номер ф-ции

      mov   dh, byte ptr y

      mov   dl, byte ptr x

      int   10h

 

; вывод символа:

      mov   ah, 09h      ;номер ф-ции

      mov   al, chr      ;al = ASCII код символа

      mov   bl, 07h      ;bl = цвет символа и заднего фона (атрибут)

      mov   bh, 0        ;bh = номер видеостраницы

      mov   cx, kol      ;cx = число выводов

      int   10h

 

      pop bp

      ret a_size         ;очистка стека и возврат из процедуры

asmproc     endp

end

-------------------------------------------------

Подробно о связи ассемблера с языками высокого уровня можно прочитать у В.Юрова.

 

==========================================================================

 

Q: Зачем нужен ассемблер в наше время? Каковы его преимущества перед ЯВУ?

A: Эта вечная темя для споров, а посему то, что написано ниже, конечно же, является специфическим мнением автора и подлежит критике. Подробно этот вопрос рассматривался на сайте http://www.assembler.ru , который существует на данный момент лишь в виде архивов, разбросанных в сети.

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

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

      В тоже время нельзя противопоставлять ассемблер языкам высокого уровня, наоборот, следует их использовать в связке – визуальные элементы составлять на ЯВУ, а некоторые специфичные ф-ции писать на ассемеблере.

 

Желающим подробно почитать по теме можно предложить Great Debate by Randell Hyde.

 

Зачем изучать ассемблер?

Ответ на этот вопрос можно найти в ASM FAQ by Bob Johnson:

 

-- http://www.bobjohnson.nm.ru/faqus.html--------

      Знание ассемблера необходимо для понимания принципа работы процессора вообще - т.к. это значительно повышает уровень програмиста в целом, даже если он не пишет ничего на ассемблере, а использует С++. Знание ассемблера позволяет понять, как процессор обрабатывает данные, команды, какие у него есть возможности и как их можно использовать. Это, в свою очередь, позволяет лучше организовать структуру программы даже на другом языке программирования (особенно - С++), потому что изучив ассемблер программист уже представляет себе, как поставленную задачу можно решить на нем, т.е. в каком виде ее должен представить компилятор того же С++ (ведь процессор воспринимает только машинные коды, в которые переводит Вашу программу компилятор, а машинные коды полностью эквиваленты ассемблеру). А это позволяет лучше организовать программу и на языке высокого уровня.

      Кроме того, знание ассемблера необходимо, если Вы собираетесь разобраться в уже готовой чужой программе, т.к. в 99,9% случаев к таким программам нет исходных текстов, а есть только готовый исполняемый файл. А когда Вы "влезете" в этот файл отладчиком, то единственное, что вы увидете - будет ассемблер и байты данных.

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

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

-------------------------------------------------

 

==========================================================================

 

Q: Что можно сделать на ассемблере?  Каковы его возможности?

А: Сделать можно абсолютно любые программы – начиная с Вашего любимого браузера и заканчивая ОС. Более того на ассемблере можно программировать не только компьютеры, но и калькуляторы и любые другие микропроцессорные системы. Единственное, что набор машинных комманд для различных процессоров различен, а следовательно и ассемблерные языки различны, однако сам факт возможности программирования на ассемблере присутствует.

 

==========================================================================

 

Q: Как работать с I/O портами, например, с LPT?

A: Тема подробно разбирается в статье Тиграна Калайджяна: “Программирование I/O устройств для управления внешними схемами"

http://kalaidjian.nm.ru/proekt.rar

Статья написана специально для пользователей RusFAQ.ru. Аналогов в Рунете нет.

 

Также смотрите:

1. О.Калашников, С.Гуляев, Ю.Новиков "Разработка устройств
сопряжения для персонального компьютера типа IBM PC"
Электронную версию см. тут:
http://www.cepera.h1.ru/

2. "Ответы на вопросы о периферии" http://www.svtehs.com/ru/embint.htm

3. Одная из лучших книг по теме:

Пей Ан «Сопряжение ПК с внешними устройствами» (Издательство Newnes-на английском языке или ДМК – на русском языке). Электронной версии пока нет, купите "бумажную" – она того стоит!

 

==========================================================================

 

Q: Как делать точные временные задержки, не зависящие от мощности машины?

A:

1. Под ДОС (не менее 1000мкс):

...

mov ah, 86h
mov cx, число_секунд
mov dx, число_микросекунд
int 15h

...

 

2. Под ДОС (не менее 55мс). Используется счётчик таймера (0000h:046Сh)

...

xor ax, ax
mov es,
ax
mov eax,
es:[Addr]

add eax, Delay
m1:
cmp es:[Addr],eax
jb
m
1

...

;значение задержки в миллисекундах, деленное на 55
Delay equ 100
 

Addr  equ 046Ch ;адрес памяти счетчика тиков таймера
...

 

3. Под ДОС (используем значение счетчика времени суток  BIOS):

;получение значения счетчика и установка задержки

mov   ah,0   ;номер функции для "чтения"

int   1ah    ;получаем значение счетчика

add   dx,91  ;добавляем 5 сек. к младшему слову

mov   bx,dx  ;запоминаем требуемое значение в bx

 

;постоянная проверка значения счетчика времени суток bios

repeat:

int   1ah    ;получаем значение счетчика

cmp   dx,bx  ;сравниваем с искомым

jne   repeat ;если неравен, то повторяем снова

             ;иначе, задержка окончена

 

4. Под Win:

...

push число_миллисекунд
call sleep

...

 

5. Под Win (высокая точность) для FASM:

 

--delay.asm--------------------------------------

format PE GUI

entry start

 

section '.code' code readable executable

 

start:  finit                      ;Инициализация сопроцессора

        emms                       ;Подготовка сопроцессора к операциям с

                                   ;плавающей точкой

                                   ;т.е. освободить регистры ММХ

        rdtsc                      ;EDX:EAX = Текущее число тактов

                                   ;с момента последнего сброса процессора

        push eax                  

        push 1000                  ;Временная задержка на 1сек.

        call [Sleep]

 

        rdtsc                      ;EDX:EAX = Текущее число тактов

                                   ;с момента последнего сброса процессора

     

        pop ebx                    ;EBX = Текущее число тактов

        sub eax, ebx               ;EAX = EAX - EBX (частота процессора)

       

        push eax

 

        fild dword [esp]           ;ST(1) = EAX (т.е. вершина стека)

        fild dword [mil]           ;ST(0) = mul = 1000

        fdivp st1, st0             ;ST(0) = ST(1) / ST(0)

        frndint                    ;Округлить до целого числа ST(0)

        fild dword [req_delay]     ;ST(1) = ST(0), ST(0) = req_delay = 15000

        fmulp st1, st0             ;ST(0) = ST(0) * ST(1)

        push eax

        push eax

        fistp qword [esp]          ;Запихать ST(0) в стек

        pop ebx

        pop ecx

       

        pushad                     ;Запихать в стек все 32-битные регистры

 

        push 1010h

        push szCapt

        push szStart

        push 0

        call [MessageBoxA]         ;Показ диалога

        popad                      ;Вынуть из стека все 32-битные регистры

 

        rdtsc

        push edx

        push eax

 

        fild qword [esp]           ;ST(0) = вершина стека

@@:     rdtsc

        push edx

        push eax

        fild qword [esp]           ;ST(1) = ST(0), ST(0) = вершина стека

        add esp, 8

        fsub st0, st1              ;ST(0) = ST(0) - ST(1)

        push ecx

        push ebx

        fild qword [esp]           ;ST(0) = вершина стека

        pop ebx

        pop ecx

        fcomip st0, st1            ;Сравнить, установить CF и вытолкнуть

        fistp dword [esp]          ;Вытолкнуть в стек

        jnc @B                     ;Прыгаем на @@, если ST(0) >= ST(1)

 

        push 1010h

        push szCapt

        push szEnd

        push 0

        call [MessageBoxA]         ;Показ диалога

 

exit:   push 0

        call [ExitProcess]         ;Выход

 

section '.data' data readable writeable

szCapt          db      "Delay", 0

szStart         db      "Press OK to start...", 0

szEnd           db      "Finished.", 0

mil             dd 1000

req_delay       dd 15000           ;Задержка

 

section '.idata' import data readable writeable

 

      dd RVA kernel_table, 0, 0, RVA kernel_name, RVA kernel_table

      dd RVA user_table, 0, 0, RVA user_name, RVA user_table

      dd 0, 0, 0, 0, 0

 

kernel_table:    

      ExitProcess dd RVA _ExitProcess

      Sleep     dd RVA _sleep

                dd 0

 

user_table:

      MessageBoxA dd RVA _MessageBoxA

                  dd 0

 

_MessageBoxA      dw 0

            db "MessageBoxA",0

 

_sleep:           dw 0

            db "Sleep", 0

 

_ExitProcess      dw 0

            db "ExitProcess", 0

 

kernel_name db 'KERNEL32.DLL',0

user_name   db "USER32.DLL", 0

-------------------------------------------------

 

Эта программа будет работать только на процессорах Pentium, Celeron, AMD K6-2 или выше. Это связано с командой rdtsc, появившейся относительно недавно.

 

==========================================================================

 

Q: Как завесить машину?

A: Предложим несколько вариантов:

1. Win9x (запрет прерываний в бесконечном цикле)

...

cli
jmp $-2

...

 

2. WinNT (консоль)

...

fool dd 0

...

mov eax, 0a0h
mov edx, [Fool]
int 2Eh

...

 

3. WinNT (программа должна быть запущена пользователем с правом Increase Scheduling Priority)

...

m1:

push REALTIME_PRIORITY_CLASS

call SetPriorityClass

jmp m1

...

 

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

DWORD ThreadProc(LPDWORD)
{
while(TRUE);
return 0;
}
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR szLine,int Cmd)
{
DWORD dwResult;
SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);
while(TRUE)
{
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,&dwResult);
}
return 0;
}

 

5. WinNT. Создаем кучу WDM, и забиваем тем самым память. BAT-файл может запускаться программой.

--pushit.bat-------------------------------------

rem "рекурсивный" пакетный файл

start pushit.bat

start pushit.bat
-------------------------------------------------

 

6. WinNT. Откроем максимально возможное количество классов окон. Тогда у наc не получится вызвать Task Manager, т.к. для этого нужно зарагистрировать еще один класс =)

Пример на С (опять же для простоты) см. ниже:

...

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPerv,LPSTR lpszCmd,int Cmd)
{
int i,j;
char szFool[0x40];
WNDCLASS wc;
for(i=0;;i++)
{
srand(i);
for(j=0;j < 0x20;j++) szFool[j]=(rand() >> 7) & 0xFF;
szFool[0x20]=0;
wc.style = NULL;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = szFool;
RegisterClass(&wc);
}

}

...

 

7. OS/2. Запись в своп.

--OS2cool.bat------------------------------------

echo FoolPlainText > swapper.dat

rem swapper.dat - файл подкачки OS/2.

-------------------------------------------------

 

8. UNIX. Запустить в фоне.

--hangunix---------------------------------------

cat hangunix > x
cat x >> hangunix
./hangunix &
./hangunix &
-------------------------------------------------

 

9. UNIX.  Вызывайте ф-ию fork() в бесконечном цикле.

 

10. DOS (Но не DosPromt в Win !):

      a) Переводим микропроцессор в состояние останова.

         ...

         hlt

         ...

      b) Бесконечный цикл.

         ...

         m1:

         jmp m1

         ...

      c) Запрет прерываний

         ...

         cli

         ...

      d) Практически любая некорректная операция =) Можно прыгнуть по

         произвольному адресу памяти и посмотреть, что из этого получится =)

         Например, прыжок в 0000:0000 наглухо вешает машину

 

11. Win16. Поставить бесконечный цикл в процедуре окна. 

 

==========================================================================

 

Q: Как перезагрузить машину?

A: Железный вариант – кнопка RESET =)

Программные варианты:

1. Из-под ДОС (Но не DosPromt в Win !):

      a) Сброс процессора

         mov al,  0feh

         out 64h, al

 

      b) Прыжок по адресу fff0h:0f00h

         db 0eah        ; jmp

         dd 0f000FFF0h

 

      c) Вызов int 18h

      d) Вызов int 19h

 

2. Из-под Win9x(использовался MASM32):

 

--reboot.asm-------------------------------------

.386

.model flat, stdcall

option casemap :none   ; case sensitive

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

 

.code

start:

 

        invoke ExitWindowsEx,1 or EWX_REBOOT,0

        invoke ExitProcess,eax

end start

 

        ; Флаги для ExitWindowEx

 

        ; EWX_LOGOFF    equ 0

        ; EWX_SHUTDOWN  equ 1

        ; EWX_REBOOT    equ 2

        ; EWX_FORCE     equ 4

        ; EWX_POWEROFF  equ 8

-------------------------------------------------

 

 

2. Из-под Win9x(использовался MASM32):

 

-------------------------------------------------

.386
.model flat, stdcall
option casemap :none ; case sensitive

include masm32\include\windows.inc
include masm32\include\user32.inc
include masm32\include\kernel32.inc
include masm32\include\advapi32.inc
includelib masm32\lib\user32.lib
includelib masm32\lib\kernel32.lib
includelib masm32\lib\advapi32.lib

.data
hToken dd 0
tp TOKEN_PRIVILEGES <>
old_tp TOKEN_PRIVILEGES <>
lpName db 'SeShutdownPrivilege',0
old_tp_buff_need dd 0

.code
start:
invoke GetCurrentProcess
invoke OpenProcessToken, eax, TOKEN_ADJUST_PRIVILEGES+TOKEN_QUERY, ADDR hToken
invoke LookupPrivilegeValue, 0, ADDR lpName, ADDR tp.Privileges[0].Luid
mov tp.PrivilegeCount, 1
mov tp.Privileges[0].Attributes, SE_PRIVILEGE_ENABLED
;invoke AdjustTokenPrivileges, hToken, FALSE, ADDR tp, 0, NULL, 0
invoke AdjustTokenPrivileges, hToken, FALSE, ADDR tp, sizeof old_tp,ADDR old_tp, ADDR old_tp_buff_need
mov eax,old_tp_buff_need
invoke ExitWindowsEx, EWX_REBOOT,0
invoke ExitProcess, 0
end start 

-------------------------------------------------

 

==========================================================================

 

Q: Как мне производить запись в BOOT-сектор?

A: Ниже следует программа, которая записывает в BOOT-сектор часть своего тела, как отдельную программу. Только надо учесть, что не всякую программу можно туда положить. Недоступность прерываний(за редким исключением) – только одна из проблем, следует учитывать размер записи (не более 512 байт) и пр. А вообще, если хотите поработать с BOOT-сектором, было бы неплохо учиться этому на основе изучения вирусов.

Итак, программа:

--makeboot.asm-----------------------------------

   ;****************************************************************
;*       Пример программы, пишушей в БУТ-сектор дискеты         *
;*Вставьте дискету, запустите программу и загрузитесь с дискеты *
;****************************************************************

.model small
.stack
.data
; 0 = Дисковод A:
; 1 = Дисковод B:
laufwerk equ 0
;----------------------------------------------------------
; Хранилище под один сектор (размер занимаемой памяти 512b)
;----------------------------------------------------------
puffer db 16h dup (?)
fatsek dw ?                                ;Partition Table
db 2bh-18h dup (?)
laderstart db 200h-2bh dup (?)             ;Загрузчик системы
;----------------------------------------------------------
; Программа записи
;----------------------------------------------------------
.code
start: mov ax,@data                        ;Инициализация сегмента
mov ds,ax                                  ;данных
mov dx,0                                   ;Стартовый сектор (BOOT)
mov cx,1                                   ;Число секторов для чтения: 1
mov bx,offset puffer                       ;Адрес буфера в DS:BX
mov al,laufwerk                            ;Номер дисковода(A:)
int 25h                                    ;Считать в хранилище!

mov cx,3                                   ;Занести 3 байта от
mov si,offset bootsektor                   ;Начала нашего "сектора"
mov di,offset puffer                       ;В буфер
aenderesprungziel:
mov al,cs:[si]                             ;Копирование байта
mov ds:[di],al                             ;CS:[si]->DS:[di]
inc di
inc si
loop aenderesprungziel                     ;Лупим, пока CX > 0

mov cx,laderoutinelaenge                   ;В CX размер данных
mov di,offset laderstart                   ;Адрес буфера кода
mov si,offset startroutine                 ;Смещение загруз. кода
aenderelader:
mov al,cs:[si]                             ;Копирование байта
mov ds:[di],al                             ;CS:[si]->DS:[di]
inc di
inc si
loop aenderelader                          ;Лупим, пока CX > 0

mov dx,0                                   ;Стартовый номер сектора
mov al,laufwerk                            ;Номер дисковода
mov bx,offset puffer                       ;Адрес буфера
mov cx,1                                   ;Число секторов
int 26h                                    ;ЗАПИСАТЬ !

abbruch: mov ah,4ch                        ;Возврат управления
int 21h                                    ;Опер. системе
;----------------------------------------------------------
; Вот то, что мы будем сажать
;----------------------------------------------------------
bootsektor:
jmp short startroutine                     ;Перепрыгнуть
nop                                        ;на загрузчик системы
dummy db 28h dup (?)                       ;Здесь как будто сидит
                                           ;Partition Table, на
                                           ;самом деле нужно только
                                           ;для правильного форми-
                                           ;рования адреса прыжка
startroutine:
cli                                        ;Запрет прерываний
mov bx,cs
mov ss, bx                                 ;SS=DS
mov sp, 7c00h                              ;Программный код
mov ds,bx                                  ;DS=CS
sti                                        ;Разрешение прерываний
mov si,7c00h+textstart                     ;В SI адрес строки
zeichen: lodsb                             ;Пересылка элемента
                                           ;строки в AL
cmp al,'$'                                 ;Конец строки?
je textfertig                              ;Если да,то выход из цикла
mov bx,7                                   ;Если нет, то вывод
mov ah,0Eh                                 ;В AL-символ
int 10h                                    ;Вывести его на дисплей!
jmp short zeichen                          ;Прыгаем вверх
textfertig:                                ;Холстой цикл
jmp short textfertig                       ;Вешаем систему
;----------------------------------------------------------
; Область данных и строка для вывода
;----------------------------------------------------------
textstart equ $-bootsektor+0
db 'Hello from Tigran!$'
;----------------------------------------------------------
; Конец области для записи в BOOT-сектор
;----------------------------------------------------------
laderoutinelaenge equ $-startroutine+0
end start

-------------------------------------------------

==========================================================================

 

Q: Где найти исходники вирусов/троянов?

A: Дело в том, что сайты, содержащие эту информацию долго не живут, но есть некоторые «устойчивые» экземпляры, и всё же будьте готовы, что нижеследующие линки уже будут мертвыми к моменту выхода FAQ

Итак:

http://z0mbie.host.sk

http://www.wasm.ru/publist.php?list=6

http://www.viruslist.com – большой справочник с описанием различных вирусов (без исходников). Постоянно обновляется.

 

Далее Вы можете скачать Файлы с http://kalaidjian.w6.ru :

 

Имя некоторых файлов нужно кое-как подправить (защита от дурака)

 

tutori.zip 80K Изучение Ассемблера на примере написания вирусов. Книга написана живым языком. ВСЕМ СОВЕТУЮ ! Читать под ДОС
cih.rar 16K Полный исходник Чернобыля с комментариями
vir2.rar 63K Игорь Коваль <Как написать компьютерный вирус>
vgw32.rar 311K Руководство по написанию 32-битных вирусов. Очень подробно.
VIRBEZR.RAR 404K Н.Н. Безруков. Компьютерная вирусология
VIRBURG.RAR 208K Ральф Бургер. Большой справочник по компьютерным вирусам
virsim.zip 113K Исходные тексты 34 вирусов: 196, разновидности Anti-Pascal, Highlander, Intrudder, Joshua, Leprosy-B, разновидности Tiny, V2100, Vienna и др.
bootvir.rar 5K Бут-вирус под виндовс98: старые звери в новом лесу (c) Chingachguk/HI-TECH
bw100.rar 38K Генератор вирусов (АСМ)
VBSworm.rar 8K Пишем червь на VBS
virii.rar 7K Пишем макро-вирус
psy.rar 4K Психологические вирусы
klexa.rar 161K Клещ для Windows. Внедряемся в систему.
dvl1.rar 120K “Duke's Virus Labs” Выпуск 1 - журнал для начинающих Вирмейкеров
backDoor.rar 11K Как написать Backdoor
troyan.rar 75K Как написать свой троян
zhello.zip 13K ZHello virus
18.rar 418B Trojan.18 - non-TSR, MBR/BOOT/CMOS-overwriter ;-)
32.rar 536B Z0MBiE.32 - TSR, EXE-overwriter
bitmask.rar 4K О дисассемблировании и битовых масках
enuns.zip 22K ENUNS infection
heur.rar 4K О том, как обмануть эвристик
hllexmpl.zip 8K pascal HLL virus example
hlp.zip 36K Заражение HLP-файлов справки.
hooy.zip 38K win9X.Hooy virus
inf1sec.zip 9K FIRST SECTION FILE INFECTOR
ircworm.rar 2K О некоторых методах распространения вирусов
lde106_x.zip 9K win9X.LDE.Examplo virus
m1.zip 61K M1 virus
rndvir.rar 6K ГСЧ В ВИРУСАХ
selfcorr.rar 3K Помехозащищенные вирусы
tp_com.zip 16K TP_COM virus
undetect.rar 6K Недетектируемые вирусы
vxd.zip 32K Заражаем VxD
w9xshare.rar 1K Win9X: Пишем в закрытые для записи файлы
w9x-tiny.zip 54K win9X.132,133,134,140,142,148,149,150,151, 152,159,161,162,166,170,180,a,182,184,185,187,189, 190,a,197,200,204,b,206,209,218,223,230,242 virii(akaWin95.SillyWR.nnn)
win32vir.rar 16K Вирусы под Win32 FAQ
win32vir.zip 7K win9X.Examplo virus
z0mbie1.zip 114K win95.Zombie
z0mbie2.zip 63K win9X.Z0MBiE-II (Twinny) virus
z0mbie3.zip 5K win9X.Z0MBiE-4 (Zofo)
z0mbie4.zip 8K win9X.Z0MBiE-3 virus
z0mbie4b.zip 37K win9X.KME.Z0MBiE-4.b (ZMorph) virus
z0mbie4c.zip 36K win9X.Z0MBiE-4.c (ZMorph) virus
z0mbie4d.zip 15K win9X.Z0MBiE-4.d (ZoM) virus
z0mbie5.zip 99K Z0MBiE-5 (W95.Bistro) virus
z0mbie6a.zip 41K win9X.RPME.Z0MBiE-6.a (ZPerm) virus (win9x permutatingz0mbie6b.zip 48K+ Z0MBiE-6.b virus (win9x polymorphic(CODEGEN)+permutating(RPME))
z0mbie7.zip 27K win9X.Z0MBiE-7 (ZPerm) permutating virus
z0mbie8.zip 15K win98.Z0MBiE-8 (Damm) virus
007.zip 25K 007JB virus

 

Данные файлы были скачаны с различных сайтов и станций ББС, так что авторы статей могут (при желании) предъявить претензии автору данного FAQ при их несогласии с опубликовыванием здесь ссылок на их статьи без их согласия.

Также хочу напомнить, что автор данного FAQ не несет ответственности за вред, причиненный в результате использования данных статей и программ. Также автор не несет ответственности за содержание статей.

 

==========================================================================

 

Q: Где взять документацию по SoftICE, IDA и другим отладчикам\дизассемблерам? Сами отладчики.

A: Софт смотрите здесь(колонка слева):

http://www.wasm.ru/toollist.php

На том же сайте можно найти примеры работы с этими программами.

 

Стабильный SoftIce для XP:

http://reversing.kulichki.net/files/debug/sinstallnt.exe

патчи тут:

http://reversing.kulichki.net/files/debug/debug.htm

 

Из документации можно порекомендовать:

Крис Касперски «Образ мышления IDA» http://www.bobjohnson.nm.ru/files/IDA.rar

 

Толстое руководство (около 900К) на русском к SoftICE можно скачать:

ftp://shelek.no-ip.com/manuals/softiceru.zip

 

Также посмотрите следующие наиболее частые вопросы по SoftIce, может найдете среди них свой:

 

1. Какую версию использовать?


Лучше   всего  использовать SoftIce из DS 2.7 (ftp://ftp.exetools.com)
или    DS 2.6  Под Win9x/NT также SoftIce 4.05, под 2k/XP стабильно
работает  только  DS 2.7. Установка различных патчей не рекомендуется,
тем более, что DS2.7 весит не очень много - ~40 Мб.

2. Не работает Symbol Loader из DS2.7


Для  исправления этого нужно в файле SoftICE\nmtrans.dll изменить байт
по смещению 0x1CD7A  с 0xB8 на  0x25.

3. Какой видеоадаптер выбирать?


Universal  Video  Driver.  Если  не  нравится,  что  сайс появляется в
слишком маленьком окне, то можно его расширить:
set font 2
lines 60
width 160
или
SET MAXIMIZE ON

При этом может потребоваться увеличить video memory size.

4. Почему не срабатывают breakpaoint'ы на api  в некоторых программах,
например GetWindowTextA?

а)  Возможно  используется  GetWindowTextW  или  GetDlgItemTextA.
б)  Может использоваться WM_GETTEXT (к примеру). В этом случае следует
    попробовать поставить breakpoint на сообщение (bmsg).
в)  Возможно, программа использует свои контролы вместо стандартных.
г)  Может  быть,  проблема в версии SoftIce. Например, SoftIce 4.05 +
   
патч для WinXP иногда игнорирует бряки и вообще работает нестабильно.

5. Как посмотреть стек?

dd ss:esp
Можно создать еще одно окно и привязать ss:esp к нему.
wd.1
dex 1 ss:esp

 

==========================================================================

Q: Как переводить числа из одной системы счисления в другую (D<->H<->B)?

A: Чтобы не запутаться в с.с. будем приписывать справа к числу соответствующую букву:

b (BIN) – двоичная с.с. – основание системы: 2

d (DEC) десятичная с.с. - основание системы: 10

h (HEX) шестнадцатеричная с.с. - основание системы: 16

 

Для перевода DEC->HEX следует последовательно делить число на 16 и записывать остатки в разряды нужного нам шестнадцателичного представления. Вот пример(в скобках мы будем записывать остатки):

 

42623/16 = 2663(15) F (15d=Fh) – младший разряд

2663/16 = 166(7)    7

166/16 = 10(6)      6

10/16 = 0(10)       A (10d = Ah) старший разряд

------------------------------------------

Итого: 42623d = A67Fh

 

Тут нам понадобилась таблица соответствия чисел:

0h -> 0d  -> 0b

1h -> 1d  -> 1b

2h -> 2d  -> 10b

3h -> 3d  -> 11b

4h -> 4d  -> 100b

5h -> 5d  -> 101b

6h -> 6d  -> 110b

7h -> 7d  -> 111b

8h -> 8d  -> 1000b

9h -> 9d  -> 1001b

Ah -> 10d -> 1010b

Bh -> 11d -> 1011b

Ch -> 12d -> 1100b

Dh -> 13d -> 1101b

Eh -> 14d -> 1110b

Fh -> 15d -> 1111b

 

Как видите, тут ничего сложного нет. Перевод DEC->BIN происходит по той же схеме, только число делится не на 16, а на 2 (т.е. на основание данной позиционной с.с. Для восмеричной мы делили бы на 8, для троичной на 3 и т.д.)

 

Что касается перевода HEX->DEC, то это можно сделать следующим образом:

Возьмем 16-ричное число. Сумма=0.

Берем последнюю цифру и умножаем на 16 в степени 0(т.е. на 1). Прибавляем к сумме.

Берем предпоследнюю цифру и умножаем на 16 в степени 1. Прибавляем к сумме.

Берем предпредпоследнюю цифру и умножаем на 16 в степени 2, Прибавляем к сумме.

 .

 .

 .

Берем первую цифру и умножаем на 16 в степени (n-1), где n-число разрядов

16-ричного числа. Прибавляем к сумме.

В сумме будет лежать DEC-число, эквивалентное данному.

 

Пример: F1Ah = 15*[16^2] + 1*[16^1] + 10*[16^0] = 10 + 16 + 3840 = 3866

 

Для перевода BIN->DEC следует работать со степенями двойки, например:

1011b = 1*[2^3] + 0*[2^2] + 1*[2^1] + 1*[2^0] = 1*1 + 1*2 + 0*4 + 1*8 = 8 + 0 + 2 + 1 = 11d

 

Перевод HEX<->BIN производится разбиением двоичного числа на тетрады (т.е. на группы по 4 цифры, т.к. 2^4 = 16) и переводом каждой тетрады в HEX-цифру.

 

Например:

 

011010101010b = 0110 1010 1010 = 6AAh

 

==========================================================================

 

Q: А числа с запятой? Чему равно [1 / 1010]b = xb = yd ?

A: Также, как и целочисленные, т.е. с помощью степеней двойки, только разряды "справа" от запятой будут соответствовать 1/2, 1/4, 1/8, 1/16 и  т.д., т.е. отрицательным степеням двойки.

Например:

0.111b = ([1/2] + [1/4] + [1/8])d = 0.875d

 

Для перевода числа в «обратную сторону» (т.е. из десятичной в двойчную с.с.) можно воспользоваться следующим алгоритмом (прислал BobJohnson на вопрос N 3622):

 

Целая часть переводится, как обычно, а дробная следующим способом:

1. Умножим ее на 2.
2. Если результат больше 1, то пишем 1 и вычитаем 1 из результата (т.е.
еще раз берем дробную часть), иначе - пишем 0.
3. Если исходная дробная часть после шага 2 не равна 0, то идем на шаг 1.
4. Конец алгоритма.


Таким образом
, мы хотим 0.875 в двоичную С.С.:
0
.875 * 2 = 1,75
пишем 1, остается 0,75
0
.75 * 2 = 1,5
пишем 1, остается 0,5
0
.5 * 2 = 1
пишем 1, остается 0
все. число получилось
0.111
b

 

Теперь вторая часть вопроса: [1/1010]b=0.1d

Попробуем применить деление "в столбик":

 

 10000     |1010

- 1010     +----

------     |0.0001100(1100)...

  01100

-  1010

  -----

     10000 (приходим к изначальному делимому => дробь имеет период)

    -  ...

 

Значит [1 /  1010]b = [0.0001100(1100)]b = 0.1d

 

Для дальнейшего разбора вопроса попробуем представить частное в виде суммы ряда степеней двойки, которым соответствует "единица" в частном в двоичном представлении:

 

0.1d = [1/16] + [1/32] + [1/256] + [1/512] ...

 

И действительно:

 

       +<><>

      -------|

      \          3

0.1 =  \       ----------

       /            (2k+1)

      /        8 * 2

      -------|

        k=0

 

Здесь k пробегает все значения от нуля до бесконечности.

Для перевода HEX<->DEC применяются аналогичные методы, только вместо основания 2 применяется основание 16.

 

==========================================================================

 

Q: Как использовать прерывания в защищенном режиме? Как работать с графикой\текстом из-под PM?

A: Стандартными обработчиками прерываний, с которыми можно было работать в реальном режиме, пользоваться нельзя, так что надо писать собственные обработчики. Примеров в Сети очень много, поэтому развивать здесь эту тему не имеет смысла.

Работать с оборудованием можно посредством портов или прямой работой с памятью.

Например, для вывода на экран текста пользоваться пользоваться сегментом видеобуфера (адреса B800h:xxxxh). Вывод графики можно производить одним из двух способов: писать напрямую в видеобуфер (для разных режимов по-разному, начиная с A000h:0000h) или программировать контроллер дисплея 6845 (об обоих способах можно почитать в книге Р.Журдена). Программирование остальных устройств также производится с помощью портов (см. след. вопрос) и перепрограммирования контроллера прерываний (см. Юрова гл. 15 и 17).

Пример программы, работающей с прерываниями в защ. режиме:

http://www.vcl.ru/html/cpu/80486/ch3.htm

 

==========================================================================

 

Q: Как программировать звуковую карту под ДОС? А мышь? НМЖД?...

A:

1. Описание программирования Sound Blaster/Pro/16, Adlib.

   http://www.dospage.by.ru/files/howtosb.zip

 

2. Для работы с мышью под DOS обычно используются ф-ции прерывания int33h. Их

   описание можно найти в списке Ральфа Брауна, в книге С.Зубкова.

   Подборку документов по теме можно скачать:

   http://kalaidjian.pochtamt.ru/mouse.rar

   Также см. Библиотеку Системного Программиста (Том 33)

   http://shmelev.vistcom.ru/doc/bsp/fv33.zip

 

3. Про программирование "жестких дисков":

   http://www.dospage.by.ru/files/hdd_1.zip

   http://kalaidjian.nm.ru/idedisk.rar

   Библиотека Системного Программиста (Том 1, книга 3, том 33)

   http://stratum11.pstu.ac.ru/~leonid/base/fv01b.zip

   http://shmelev.vistcom.ru/doc/bsp/fv33.zip

   Также можно почитать Журдена(гл 5.4)

   Если доступны прерывания, то можно пользоваться int13h, int25h/26h

 

4. Дисководы:

   http://www.dospage.by.ru/files/fddprog.zip

 

5. Клавиатура: используйте порты 60h и 61h. Подробно читайте:

   Библиотека Системного Программиста (Том 2, книги 1-2, Том 33)

   http://stratum11.pstu.ac.ru/~leonid/base/fv02.zip

   http://shmelev.vistcom.ru/doc/bsp/fv33.zip

 

6. Видеоадаптеры:

   Библиотека Системного Программиста (Том 3 и Том 21)

   http://stratum11.pstu.ac.ru/~leonid/base/fv03.zip

   http://shmelev.vistcom.ru/doc/bsp/fv21.zip

 

7. Прочее: Библиотека Системного Программиста (Том 33)
  
http://shmelev.vistcom.ru/doc/bsp/fv33.zip

 

==========================================================================

 

Q: Киньте, плиз, исходники БИОСа.

A: Исходники BIOS'ов - штука дорогая (обычно стоит не один десяток тыс. долларов), поэтому иметь исходники имеет смысл только фирмам, разрабатывающим своё железо. Хотя в Интернете Вы можете найти исходник BIOS для Intel 8088 или NEC "V20" материнских плат:

http://www.dospage.by.ru/files/bios-asm.zip

 

Если же Вам нужно работать с прошивкой, а не с ее исходником версией, то добро пожаловать на http://yusoft.kulichki.com/russian/doc/biosedit.htm

 

==========================================================================

 

Q: Где взять исходники прерываний BIOS\DOS?

A: Исходники прерываний DOS можно найти в исходниках самого DOSа. Например, исходники MS-DOS v3.3 можно скачать:

http://www.dospage.by.ru/files/dos33src.zip

Исходники прерываний BIOS можно найти в в исходниках BIOS (см. соответствующий вопрос).

 

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

 

Предположим Вам надо посмотреть подпрограмму, выполняющуюся при вызове ф-ции 02h прерывания int 10h. Зайдем в Ваш любимый отладчик (здесь описаны действия для работы с Debug.exe).

Посмотрим, что у нас лежит в двойном слове по адресу 0000h:0040h (т.е. по смещению 4*10h, мы ведь смотрим int10h, не так ли? Для каждого адреса(вектора) отводится по 4 байта, потому-то мы и умножаем на 4):

 

-d 0000:0040

0000:0040  07 00 70 CC 4D F8 00 F0-41 F8 00 F0

 

Скорее всего, у Вас будет 070070СС => обработчик сидит по адресу CC70h:0007h.

Теперь смотрим, что "сидит" по этому адресу(дизассемблируем):

 

-U CC70:0007

 

CC70:0007 FB            STI

CC70:0008 84E4          TEST    AH,AH

CC70:000A 7414          JZ      0020

CC70:000C 3D024F        CMP     AX,4F02

CC70:000F 740A          JZ      001B

CC70:0011 80FC4F        CMP     AH,4F

CC70:0014 740A          JZ      0020

CC70:0016 EA0C00860E    JMP     0E86:000C

 

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

Все же, давайте попробуем по-другому. Попробуем протрассировать код:

-r cs

CS 15AA

:cc70

-r ip

IP 0100

:0007

Теперь в паре CS:IP полный адрес нашего обработчика int 10h

 

-r AX

AX 0000

:0201

Подсунем ему (обработчику) вызов ф-ции 02h(как и договаривались)

 

-t

AX=0201  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000  DS=15AA  ES=15AA  SS=15AA  CS=CC70  IP=0008   NV UP EI PL NZ NA PO NC

CC70:0008 84E4          TEST    AH,AH

 

Все! Теперь мы в обработчике! Узнаёте первую строчку? (тут сначала идёт статус регистров, а затем дизассемблированная команда). Далее, выполняя команду t, вы будете гулять по обработчику, в том же порядке выполняя комады, как это бы делалось в результате выполнения следующего кода:

 

mov ah, 02h

mov al, 01h

int 10h

 

Выход из обработчика Вы обнаружите, увидев примерно такую строчку:

 

AX=0201  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000  DS=15AA  ES=15AA  SS=15AA  CS=C000  IP=0226   NV UP EI NG NZ NA PO NC

C000:0226 CF            IRET

 

Команда IRET - возврат из обработчика прерывания.

 

Таким образом можно проследить "путь" в любом обработчике любого прерывания.

 

==========================================================================

 

Q: Я взял код прошивки BIOS и дизассемблировал его. Фигня получается.

A: Информация для размышления - как Ваш дизассемблер отличает код от данных? Т.е. не мог ли он "дизассемблировать" данные?

Представьте также следующий вариант - есть такая вот программа:

====================

.model tiny

.code

org 100h

main:

      a:

      cli

      jmp a

end main

====================

В HEX-редакторе (например QView) она выглядит так:

 

FA EB FD

 

Дизассемблируем её:

 

 00000000: FA                        cli

 00000001: EBFD                  (1) jmp    00000000

 

Пока что всё правильно.

 

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

 

====================

.model tiny

.code

org 100h

main:

      jmp a

OUR_BYTE db 1 ; вот он !

      a:

      cli

      jmp a

end main

====================

 

В HEX-редакторе читаем:

 

EB 02 90 01 FA EB FD

 

Дизассемблер покажет следующее:

 

 00000000: EB02                  (1) jmp    00000004

 00000002: 90                        nop

 00000003: 01FA                      add    dx,di

 00000005: EBFD                  (2) jmp    00000004

 

Ну что, похоже на исходный вариант программы? Нет? А теперь представьте(для примера), что у Вас в результате такого сдвига случайно попалась команда 0E. Дизассемблер показал, что это push cs, а это может быть, например, кусок команды B0 0E (т.е. mov al, 0eh). Такое "разделение" может быть вызвано, упомянутым выше, сдвигом кода из-за данных.

Вывод: дизассемблером НЕЛЬЗЯ получить исходник прошивки, т.к. нельзя отличить код от данных. Если Вы хотите таки получить небольшие участки ассемблерного кода, то используйте отладчики.

 

==========================================================================

 

Q: Что такое сопроцесcор. Как с ним работать?

A: Сопроцессор – это отдельная микросхема, реализующая различные математические функции (в т.ч. и с плавающей запятой) на _аппаратном_ уровне.

Подробно о работе с математическим сопроцессором читайте в книге Зубкова или Юрова(гл. 19).

Далее идет ответ из дружественного FAQ:

Вот коротенький пример.

 

--soproc.asm-------------------------------------

.model tiny

.code

.386                                  ; привычка :)

.387                                  ; использование сопроца

.code

main:

 

               finit                  ; инициализация сопроца

               fild  data1            ; загрузка data1

               fiadd data2            ; складывание с data2

               fist _result           ; сохранение результата в

                                      ; _result

 

               ret

data1   dw 1

data2   dw 200

_result dw ?

 

end main

-------------------------------------------------

 

Теперь немного теории.

Пример команды:

fild

^^^^

|||

|||

||*-- 'ld' - load, загрузка числа в стек сопроцессора

|*--- 'i' - integer, означает, что работаем с ЦЕЛЫМИ данными (

|           еще варианты - '', то есть fld, например - загрузка вещественного

|           числа в сопроцессор, 'b', т.е. fbld - загрузка BCD числа)

*---- 'f' - обозначает, что это команда сопроцессора

 

Примеры команд:

 

fld data1                       ; загрузка вещественного числа из памяти

                                ; по адресу data1 в сопроцессор

 

fist _result                    ; сохранение числа как целого в память по

                                ; адресу _result (при необходимости оно

                                ; округляется - это делает сам сопроц)

 

fistp _result                   ; то же самое, но при сохранении числа оно

                                ; выталкивается из стека сопроца

 

fsqrt                           ; вычисление квадратного корня из st0, то

                                ; есть аргумент берется из стека, туда же и

                                ; помещается значение корня

 

Вообще, для понимания механизма работы возьмите Turbo Debugger:

(мы отлаживаем не ту программу, что написана выше =)

F10/View/Numeric processor:

Здесь видно, что в стеке сопроца находится число 300 :)

 

+=[x]=80486 IPTR=54CE3 OPCODE=706 OPTR=54CEE==2=[][]=+

|Valid ST(0) 300                         | im=1 | ie=0 |

|Empty ST(1)                             | dm=1 | de=0 |

|Empty ST(2)                             | zm=1 | ze=0 |

|Empty ST(3)                             | om=1 | oe=0 |

|Empty ST(4)                             | um=1 | ue=0 |

|Empty ST(5)                             | pm=1 | pe=0 |

|Empty ST(6)                             |iem=0 | ir=0 |

|Empty ST(7)                             | pc=3 | cc=0 |

|                                        | rc=0 | st=7 |

|                                        | ic=0 |      |

+xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+======+=====-+

 

Выполняем:

 

cs:0107 D9FA           fsqrt

 

+=[x]=80486 IPTR=54CE7 OPCODE=1FA OPTR=54BE0==2=[][]=+

|Valid ST(0) 17.320508075688773          | im=1 | ie=0 |

|Empty ST(1)                             | dm=1 | de=0 |

|Empty ST(2)                             | zm=1 | ze=0 |

|Empty ST(3)                             | om=1 | oe=0 |

|Empty ST(4)                             | um=1 | ue=0 |

|Empty ST(5)                             | pm=1 | pe=1 |

|Empty ST(6)                             |iem=0 | ir=0 |

|Empty ST(7)                             | pc=3 | cc=0 |

|                                        | rc=0 | st=7 |

|                                        | ic=0 |      |

+xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+======+=====-+

 

Получили вещественное число в стеке сопроцессора. Сохраним его в памяти

по адресу ds:[110] как целое:

 

cs:0109 DF1E1001       fistp  word ptr[0110]

 

Смотрим содержимое сегмента данных:

 

ds:0110 11 00 FF 16 57 9A A5 1B

        ^^^^^ вон он наш результат :)

 

==========================================================================

 

Q: Как работать с ф-циями Sin/Cos/Tg/Ln/ArcSin и пр. ?

A: самый простой способ – использовать сопроцессор:

 

fcos, fsin,                     ; Вычисление Sin/Cos угла,

                                ; находящегося в стеке сопроцессора.

                                ; Угол должен быть задан в радианах.

                                ; Результат сохраняется в верхине стека

                                ; сопроцессора – регистре st(0)

                                ; команда не имеет операндов.

 

fsincos                         ; одновременно вычисляет и Sin и Cos, в

                                ; st(0) помещается Sin, в st(1) – Cos

 

fratan                          ; вычисление _частичного_ арктангенса угла,

                                ; находящегося в вершине стека сопроцессора

fyl2x                           ; ST(0) = ST(1)*log2(ST(0))

fyl2xp1                         ; ST(0) = ST(1)*log2(ST(0)+1)

 

Таких команд как Arcsin, Arccos, ArcCtg в арсенале сопроцессора нет, однако значения этих ф-ций можно получить самому по формулам:

 

arcsin(a) = arctg(a/sqrt(1-a*a))

arccos(a) = 2 * arctg(sqrt(1-a)/sqrt(1+a))

arcctg(a) = arctg(1/a)

 

Подробно, с примерами и руководством к работе следует почитать у В.Юрова

 

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

 

a) Ряд Маклорена (частный случай ряда Тейлора):

В общем виде ряд Маклорена выглядит следующим образом:

f[x] = f[0] + f'[0]*x/1! + f''[0]*x^2/2! + … + f(n)[0]*x^n/n! + …

Здесь f(n)[x] - производная f[x] n-го порядка,

"^" - знак степени: 2^3 = 2*2*2 = 8.

"!" - знак факториала. Y! = 1*2*3*4*...*Y  (0! = 1)

В частности sin[x], cos[x], arcsin[x], arctg[x] можно разложить в ряд Макларена след. образом:

sin[x] = x  - ([x^3] /3!) + ([x^5] /5!) - ([x^7] /7!) + ([x^9] /9!) - ... +

        + ([(-1)^(n+1)] *[ x^(2n-1)] / [2n - 1]!) + …

cos[x] = 1 - ([x^2] /2!) + ([x^4] /4!) - ([x^6] /6!) + ([x^8] /8!) - ... +

        + ([(-1)^n] *[ x^(2n)] / [2n]!)

 

arcsin[x] = x + ([1 * x^3] / [2*3]) + ([1*3]*[x^5/5]/[2*4]) + ([1*3*5]*[x^7/7]/[2*4*6]) + …

 

arctg[x] = x - [x^3/3] + [x^5/5] - [x^7/7] + …

 

b) Рекуррентная формула: cos(X_n) = 2*cos(X_{n-1}) * Step - X_{n-2}
Соответственно, X_0=1, X_1=Step (т.е. шаг).

 

Пример программы, строящей таблицу косинусов по этой формуле представлен ниже:

 

--zedronts.asm-----------------------------------

.model tiny

.data

 

Num_Cosines equ 720                    ; Число ячеек

Step equ 0FFFDh                        ; cos(360/Num_Cosines)*2^16

; Таблица косинусов в формате 16.16 с фиксированной точкой

Costable dw 0FFFFh, Step, Num_Cosines-2 dup(?)

End_table label

 

.code

.386

org 100h

start:

    mov di,offset Costable[2*2]     ; Начинаем с X_3

    mov ecx,Step

loop_1:

    xor ebx,ebx                     ; EBX = 0

    xor eax,eax                     ; EAX = 0

    mov bx,[di-2*2]                 ; bx=X_{k-2}

    mov ax,[di-2*1]                 ; ax=X_{k-1}

    imul ecx                        ; EDX:EAX=cos(X_{k-1})*Step

    shrd eax,edx,15                 ; EAX=2*cos(X_{k-1})*Step

    sub eax,ebx                     ; EAX=2*cos(X_{k-1})*Step - X_{k-2}

    mov [di],ax                     ; Сохраним полученное значение

    add di,2                        ; k=k+1

    cmp di,offset End_table

    jb loop_1       

    ret                  

end start

-------------------------------------------------

 

Для вычисления Sin воспользуйтесь основным тригонометрическим тождеством, учитывая четверть в которой находится угол.

 

с) Для подсчёта обратных триг. ф-ций можно применять рекурсивный алгоритм с применением метода Ньютона(программа для упрощения написана на Паскале):

 

--arcsin.pas-------------------------------------

function arcsin(x, fi: REAL): REAL; {результат - угол в рад.}

begin

if ABS(Sin(fi)-x)>0.0000001         {задаём точность}

then arcsin:=arcsin(x,fi+(x-Sin(fi))/Cos(fi)) else arcsin:=fi;

end;

 

begin

Writeln((Arcsin(Sqrt(3)/2,0) * 180/pi):9:9);

end.

-------------------------------------------------

 

==========================================================================

 

Q: Как убрать «моргание» изображения при работе с графикой ?

A: Моргание имеет место из-за того, что различные элементы большой картинки заканчивают отрисовку в различные моменты времени. Если картинка постоянно обновляется, то «время жизни» различных компонентов также различно, поэтому появляется впечатление, что картинка «моргает». Чтобы избежать этого эффекта картинку следует выдать полностью в один момент времени, предварительно отрисовав ее в отдельной области памяти (видеостраницы в ДОС) или в виде растровой картинки(в Win32).

Пример работы с видеостраницами под ДОС:

 

--pages.asm--------------------------------------

.model small

.code

main:

mov ax, 12h     ;Устанавливаем граф. режим

int 10h 

 

mov ah, 05h     ;Текущая видеостраница - первая

mov al, 01h

int 10h

 

mov cx, 300     ;Здесь мы рисуем линию в цикле

mainloop:       ;Координаты (X;Y) = (CX;DX)

mov ah, 0Ch

mov bh, 02h     ;Рисуем во вторую видеостраницу...

mov al, 02h     ;...зеленым цветом

mov dx, 200    

int 10h         ;Поставить точку

loop mainloop

 

xor ah, ah      ;Ждем, пока пользователь нажмет на

int 16h         ;какую-нибудь клавишу

 

mov ah, 05h     ;Установим текущей видеостраницей вторую.

mov al, 02h     ;ПОКАЗАТЬ КАРТИНКУ !

int 10h

 

xor ah, ah      ;Ждем, пока пользователь нажмет на

int 16h         ;какую-нибудь клавишу

 

mov ax, 03h     ;Установка текстового режима

int 10h

mov ah, 4ch     ;Выход и возврат управления ОС

int 21h

end main

-------------------------------------------------

 

==========================================================================

 

Q: Как сделать так, чтобы не работали одновременно 2 копии моей программы?

A: Пример для MASM32:

--findwind.asm-----------------------------------

.386

.model flat, stdcall

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

 

.data

ProgName db "My prog",0

 

.code

_start:

; ищем окно нашей программы

invoke FindWindow,0,addr ProgName

 

; если находим, то выходим

test eax, eax

jnz quit

 

; здесь основной код, выполняющийся при запуске первой копии:

invoke MessageBox, 0, offset ProgName, offset ProgName, 0

 

quit: invoke ExitProcess,0

end _start

-------------------------------------------------

 

==========================================================================

 

Q: Как выдвинуть лоток cd-rom'а

A: Если под ДОС, то читайте соответствующий документ по ATAPI-пакетам: http://www.dospage.by.ru/files/atapi-cd.rar

 

Под Win32 по-проще(использовался MASM32):

 

--cdcool.asm-------------------------------------

.386

.model flat, stdcall

option casemap:none

include    \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\winmm.lib

include    \masm32\include\winmm.inc

.const

OPEN DB 'Set CDAudio Door Open Wait',0

CLOSE DB 'Set CDAudio Door Closed Wait',0

.code

_start:

mov EBX, 0            ;0 для ф-ций

push EBX

push EBX

push EBX

push OFFSET OPEN      ;для открытия

;push OFFSET CLOSE    ;для закрытия

call mciSendStringA

push EBX

call ExitProcess      ;Выход

end _start

-------------------------------------------------

 

==========================================================================

 

Q: Как под Win32 работать с портами/памятью?

A: Возможно несколько вариантов:

1. Если порт стандартный (COM, например), то можно с ним работать как с файлом с помощью функций CreateFile, ReadFile, WriteFile (описание см. в MSDN). Если порт нестандартный, то это способ не сработает.

2. Перейти на нулевое кольцо защиты (как это делают вирусы) и работать с портами напрямую, как из-под ДОС. Уровень Ring-0 - уровень Бога.

3. Написать драйвер, который как раз работает на уровне ядра и может работать напрямую с памятью\портами и использовать его функции из своей программы, которая может быть написана не только на ассемблере, но и на ЯВУ(так в основном делается для программирования под WinNT)

   Проект написания wdm-драйвера для LPT c комментариями можно найти на http://progrex.narod.ru

4. Можно воспользоваться уже готовыми библиотеками, например NTPort Library http://www.zealsoftstudio.com/

   В пакете прилагаются примеры на различных языках программирования.

 

Вот еще пара ссылок по теме:

http://www.lvr.com/

http://www.entechtaiwan.com/tools.htm

 

==========================================================================

 

Q: Как написать свой драйвер под Win32?

A: В первую очередь необходимо скачать стандартный набор программ, документации и библиотек для создания драйверов, предоставляемый Microsoft - DDK (Drivers Development Kit) для той платформы, под которую Вы собираетесь написать драйвер.

1. Для Win98:

http://download.microsoft.com/download/win98SE/Install/Gold/W98/EN-US/98DDK.EXE

Или здесь:

ftp://shelek.no-ip.com/ddk/98ddk.exe

 

2. Для WinME

ftp://shelek.no-ip.com/ddk/Wme_DDK.exe

 

3. Для WinNT4 (все сервиспаки)

ftp://shelek.no-ip.com/ddk/nt4ddk.zip

 

4. Образ диска для DDK Для WinXP:

http://windriver.ssarang.net/pds/DDK_XP.ISO

Или здесь:

ftp://shelek.no-ip.com/ddk/Ddk_xp.iso

 

5. Для Win2000

ftp://shelek.no-ip.com/ddk/2kddknly.exe

 

Хотя всё это можно купить на радиорынке...

 

Полезно также вооружиться отладчиком, например SoftIce. Также полезно иметь под рукой MSDN.

 

А далее вперед - компилировать примеры из DDK, смотреть описания в MSDN и пр.

Чтобы написать что-нибудь свое, достаточно перекроить один из примеров к DDK.

 

Следует уточнить, что в Win32 применяются различные варианты драйверов, напрмер VxD (Virtual Device Driver), WDM (win32 driver model) и пр., поэтому при выборе документации следует учитывать неоднозначность понятия "драйвер".

 

 

Итак. Если Вы хотите почитать подробно и доступно о написании драйверов, то можно посоветовать следующие источники:

1. Цикл статей "Как писать драйвера", "Драйвер с нуля" и другие статьи по теме: http://www.shelek.com/club/view.php?id=52&type=0

 

2. Простое руководство от Bob Johnson,  как,  пользуясь MASM написать самому VxD-драйвер под Windows 9x (на примере антивируса):

http://www.bobjohnson.nm.ru/files/driver.zip

 

3. Гречко Ю.Б "Пишем драйвер WDM на Ассемблере"

http://progrex.narod.ru/asmdrv.html

исходники к статье

http://progrex.narod.ru/files/AsmDrv.zip

 

4. Туториалы Iczelion'a "Уроки VxD" (подробно на русском языке):

http://www.wasm.ru/publist.php?list=3

 

Из "бумажных" книг на русском можно упомянуть следующие:

1. Свен Шрайбер «Недокументированные возможности Windows 2000». Издательство «Питер» 2002 год.

2. П. И. Рудаков, К. Г. Финогенов «Язык ассемблера: уроки программирования»

Диалог МИФИ 2001 год

3. Светлана Сорокина, Андрей Тихонов, Андрей Щербаков «Программирование драйверов и систем безопасности». Издательство «БХВ-Петербург» 2002 год

 

Из английского:

1. Программирование WDM (Walter Oney)

http://www.shelek.com/club/download.php?id=9

и приложения к ней

http://www.shelek.com/club/download.php?id=13

2. Windows 2000 device driver book Art Baker Jerry Loza

http://www.shelek.com/club/download.php?id=10

3. Writing Windows VxDs & Device Drivers; Programming Secrets for Virtual Device Drivers, автор Karen Hazzah

 

==========================================================================

 

Q: Что такое «кольца защиты» и зачем они нужны?

A: Кольца защиты, то же что и уровни привелегий.

---------------------------------------------------------------

Ответ на вопрос 3266. Отвечает Knignick:

Уровни привилегий - механизм защиты программ друг от друга в защищенном режиме. В дескрипторе каждого сегмента в защ.режиме указывается какой уровень (ring) ему соотвествует.

Минимальные привелегии соотвествуют прикладным прогам (ring 3).

Ядро ОС функционирует на уровне 0.

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

---------------------------------------------------------------

Про защищенный режим можно прочитать в любой книге по ассмеблеру.

Если же Вы захотите подробно изучить его, то прочитайте цикл статей от

Broken Sword "Процессор INTEL в защищенном режиме"

http://brokensword.narod.ru/

или

http://www.wasm.ru/publist.php?list=24

 

Уровни привелегий, в частности, рассматриваются в 13-ом выпуске:

http://www.wasm.ru/print.php?article=pipm13

 

==========================================================================

 

Q: Как мне корректно подсесть на Ring-0?

A:

  1. непосредственная загрузка VxD-драйвера либо изменение какого-нибудь из существущих загружаемых VxD-файлов (наиболее цивилизованный способ)
  2. модификация дескриптора прерывания в IDT
  3. создание callgate-а в GDT или в LDT, включая сюда поиск LDT в памяти без доступа к GDT
  4. переход посредством вызовов KERNEL-овских функций (всякие там пэйджеры)
  5. переход сплайсингом в одну из VMM-овских процедур (например C0001000) либо изменение каких-либо уазателей в VMM-овских данных
  6. переход модификацией контекста (SetThreadContext, ставим CS=28h, EIP=r0proc)
  7. переход через INT 2E/PsCreateSystemThread, PoCallDriver, RtlCopyMemory и т.п.
  8. используя INT 31, кой можно вызывать через kernel32 (push 002A0029/call ord0)

 

Подробно можно почитать на сайте http://z0mbie.host.sk в разделе Ring-0, на http://www.wasm.ru в разделе "вирусология", а также можно исследовать исходники вируса "Чернобыль"

http://kalaidjian.w6.ru/vir/cih.rar

 

Здесь же приведем программу, работающую под Win9x и переходящую в Ring-0 посредством изменения дескрипторной таблицы прерываний:

 

--ring0.asm--------------------------------------

.386P

.MODEL FLAT, STDCALL                     ;Плоская модель памяти 

option casemap:none

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

 

.DATA

lpOldGate  dd 0                          ;Место для старого шлюза

IDT        db 6 dup (0)                  ;Место для дескрипторной таблицы

 

ExceptionUsed     EQU 5                   ;Номер исключения

 

.CODE

start:

     

      sidt  fword ptr IDT                ;Получить IDT

 

      mov   ebx, dword ptr [IDT+2]       ; ebx -> IDT

      add   ebx, 8*ExceptionUsed         ; ebx -> IDT запись ExceptionUsed

 

      cli                                ;Запретить прерывания

 

      mov   dx, word ptr [ebx+6]         ;Сохраним старый шлюз: старшее слово

      shl   edx, 16d

      mov   dx, word ptr [ebx]           ;Младшее слово

      mov   [lpOldGate], edx

 

      mov   eax, offset Ring0Code        ;"поставить ловушку(хук)"

                                         ; - новый шлюз

      mov   word ptr [ebx], ax           ;Младшее слово

      shr   eax, 16d

      mov   word ptr [ebx+6], ax         ;Старшее слово

 

      int   ExceptionUsed                ;Вызываем исключение

 

      mov   ebx, dword ptr [IDT+2]       ;Восстанавливаем шлюз

      add   ebx, 8*ExceptionUsed

      mov   edx, [lpOldGate]

      mov   word ptr [ebx], dx

      shr   edx, 16d

      mov   word ptr [ebx+6], dx

     

 

      invoke      ExitProcess, -1         ;Выход

 

Ring0Code PROC

      mov   eax, cr0

                        ;Вставьте сюда ваш код, ибо мы под Ring0 =)

      iretd

 

Ring0Code ENDP

end start

-------------------------------------------------

 

==========================================================================

 

Q: Как програмировать под Linux на ассемблере?

A:

  1. Читайте соответствующую главу у С.Зубкова (см. ответ на первый вопрос)
  2. http://www.linuxassembly.org/
  3. Некоторые лабы от Broken Sword http://brokensword.narod.ru
  4. Linux Device Drivers (Объективно лучшая книга про написание драйверов для Linux. Также из нее можно почерпнуть сведения об устройстве ядра) http://www.shelek.com/club/download.php?id=29

 

==========================================================================

 

Q: Как заставить мой комп(или модем) работать быстрее?

A:  Однозначного ответа на этот вопрос дать нельзя, т.к. для разного набора оборудования эти советы различны, однако существует некоторый набор общих советов на эту тему, в том числе и «народные». Их можно найти в списках проектов на http://kalaidjian.nm.ru .

Автор проекта лишь выдает список советов, однако не отвечает за их актуальность и работоспособность.

 

==========================================================================

 

Q: Как «ломать» программы ?

A: Научиться "ломать" программы можно только ломая их. В основном это - кропотливая работа с дизассемблером и отладчиком. Без опыта программирования на ассмеблере - никуда. Желательно также иметь опыт программирования на машинном языке.

Для того, чтобы осмотреться, можно почитать некоторые статьи(всё про Win, т.к. это наиболее просто):

1. "Как ломать программы Windows" (C) ED!SON [UCF], перевод Mr.Boco/TCP

http://kalaidjian.nm.ru/Lomka.rar

2. Распространенный FAQ по взлому для новичков:

http://xaker.online.kg/stat'i/diff/Xak_prog.htm

3. "Учебник по взлому windows-приложений" http://olegk99.chat.ru/hack8.htm

4. Взлом с WinDASM http://www.madalf.ru/cracks/cracks3.shtm

5. 15 подробно разобранных взломов с кратким руководством по SoftICE: http://kalaidjian.nm.ru/crttut.zip

 

Информация по-серьезнее:

1. Группа статей "Исследование программ"

http://www.wasm.ru/publist.php?list=3

2. Крис Касперски. "Дизассемблирование в уме".

http://kalaidjian.nm.ru/head.rar

3. Крис Касперски "Образ мышления IDA" http://www.bobjohnson.nm.ru/files/IDA.rar

 

Если Вы немного поднабрались опыта, то добро пожаловать на

http://www.reverser-course.de/

Тут Вы сможете зарегистрироваться и непрерывно обучаться на взломе различных небольших программ.

 

==========================================================================

 

Q: Что такое RTFM, IMHO, AFAIK и другие слова, столь часто употребляемые экспертами RusFAQ.ru?

A: Это некоторые жаргонные и часто удобные словечки:

IMHO (=ИМХО) - In My Humble Opinion. Одно из наиболее употpебительных слов в Фидо и Usenet. Давно потеpяло пеpвоначальное значение, чаще всего употpебляется пpосто в значении "по-моему" или, в кpайнем случае, "мне кажется". В то же вpемя обязательно употpебление этого слова пpи явно споpных заявлениях. Пpизнаком кpайнего занудства считается выделение IMHO запятыми.

 

RTFM - Read The FUCKING Manual.  Втоpое по употpебительности после IMHO выpажение. Означает: "Пpежде чем спpашивать, пpочитайте pуководство по использованию". Сокpащение почти утpатило пеpвоначальный оттенок гpубости.

 

AFAIK (=АФИК=НЯЗ)As Far As I Know, т.е. «насколько я знаю»

AFAIR (=АФИP=НЯП)As Far As I Remember, т.е. «насколько я помню»

ЯВУ – сокращение от «Языки Высокого Уровня»

 

==========================================================================

 

Q: Что такое “станция BBS"?

A: Станция ББС - это, грубо говоря, склад файлов, к которому можно получить доступ через псевдографический или текстовый интерфейс, позвонив на телефонный номер модемом и скачав то, что нужно... Ничего сложного. Для доступа не нужно иметь специальных программ - HyperTerminal прилагается к стандартному пакету Windows.
      В своё время станции носили более универсальный характер - это и склад
файлов, и почтовый ящик и выход в ФИДО без регистрации и прочее, но сейчас эти дополнительные возможности мало кому нужны из-за существования
Интернет...

      Однако многие файлы, которые лежать на станциях нельзя найти в Интернет + связь не оплачивается в пределах города, поэтому ббски существую и по сей день, хотя и быстро вымирают (за последние несколько лет произошло повальное вымирание, и даже не известно выпускаются ли AMBL или NBL ББС-листы).

      В Москве существуют по крайней мере 2 станции, базирующиеся на документации по ассемблеру. Причём они содержат некоторые программы и документы, которые Вы не найдете в Интернете. Одна из них - TiCOiN BBS. Для получения к ней доступа (в пределах города, т.к. вне города Вам придется оплачивать междугородную связь) достаточно связаться с Системным Оператором(СисОпом) станции (kalaidjian@pochtamt.ru) и договориться о времени подключения. СисОп также расскажет о том, как надо подключаться и выдаст

правила подключения, скачки\закачки и пр.

 

==========================================================================

 

Q: Кто и зачем до сих пор использует DOS. Какой смысл сейчас
писать что-то для него?

A:

1. Под ДОС программировать во многом проще. Структура работы логична и понятна, исходники открыты. Для новичков – это лучший полигон для работы.

2. По привычке. Многие начинали программировать, когда еще не было W98/95 и

прочего.

3. Маленький размер и быстрая работа откомпилированных программ. Маленький

размер исходников.

4. Возможность пощупать код на низком уровне, дабы лучше разобраться в работе программы, а не строить её из «кубиков», как часто это делается в Delphi\Buider, после чего непонятно с чем связана та или иная ошибка

5. Не все машины еще имеют на борту Win\Linux, поэтому не стоит пока

хоронить ДОС ИМХО...

У MTU-INFORM на http://support.mtu.ru был опрос (где-то в 1999г), по теме "ДОС мёртв?". Так вот: около 95% ответили НЕТ.

6. Дополнительное подтверждение того, что ДОС жив, Вы можете найти на http://www.dospage.by.ru , а также на http://int21.narod.ru/links/

Посетителей первого сайта к времени создания данного FAQ было уже больше 9500. Значит это еще нужно людям! А если это нужно людям, то и нужны программы под эту ОС.

 

==========================================================================

 

В создании FAQ принимали участие:

Tigran Kalaidjian       kalaidjian@pochtamt.ru       2:5020/2987.25

Hangatyr                hangatyr@centrum.cz

Zedr0n                  gamesru@narod.ru

Eugene Ivanov           Eugene_Ivanov@mail.nnov.ru

 

Конструктивная критика и замечания:

Bob Johnson             BobJohn@NewMail.ru

Blackman                blackman@ezmail.ru

 

Подборка вопросов составлена на основе архивов RusFAQ.ru

 

При нахождении мертвых ссылок просьба писать на kalaidjian@pochtamt.ru

 

Данный документ может быть выложен на любой сайт участниками проекта RusFAQ.ru