Лидеры рейтинга

ID: 401284

Михаил Александров

Советник

377

Россия, Санкт-Петербург


ID: 259041

Алексеев Владимир Николаевич

Мастер-Эксперт

358

Россия, пос. Теплоозёрск, ЕАО


ID: 401888

puporev

Профессор

215

Россия, Пермский край


ID: 405338

vovaromanov.jr

1-й класс

126


ID: 400669

epimkin

Профессионал

111


ID: 242862

Hunter7007

Мастер-Эксперт

29

Россия, Омск


ID: 137394

Megaloman

Мастер-Эксперт

25

Беларусь, Гомель


8.10.2

13.10.2021

JS: 2.10.2
CSS: 4.6.0
jQuery: 3.6.0
DataForLocalStorage: 2021-10-19 21:16:01-standard


Создание программ на языке Assembler.

Администратор раздела: Зенченко Константин Николаевич (Старший модератор)

Консультация онлайн # 109152

Раздел: Assembler
Автор вопроса: Masada
Дата: 13.11.2007, 03:18 Консультация закрыта
Поступило ответов: 2

Здравствуйте, уважаемые эксперты. Не могу разобрать начало инициализации вируса из главы 13 программы Virus13.
1. Непонятен синтаксис строки mov cx,offset Finish-100h, где Finish equ $. Что значит $? В предыдущих программах $ была в конце строки, выводимой на экран, но в Virus13 таких строк нет. Но если всё же $ здесь и означает конец кода нашего вируса, то зачем к $ приписывать -100h. Всё равно ведь программа будет записана до $, а не до 100h. Отладчик же показывает cx 0084, а не 100h. Наверное, 0084h и есть размер нашего вируса.
2. К строке mov si,100h автор даёт комментарий: «DS:SI откуда перемещать будем нашу программу …» А каким образом в DS:SI попала наша программа, она же находится в DS:DX. Получается, что DX = SI. Всегда ли регистры DS:SI показывают содержание любой текущей программы или это касается только этой?
3. При выполнении команды jmp dword ptr cs:[Off_move], где Off_move dw offset Lab_jmp, изменяется регистр CS. Решив сократить код, т.е. написать не две строки как у автора, а одну, я переделал так: jmp dword ptr cs:[offset Lab_jmp], т.е. сразу указал на метку Lab_jmp, а не через переменную Off_move. Однако при выполнении этой команды регистр CS не изменился. Почему? Ведь в авторской строке и в моей фактически указан один и тот же адрес.
Заранее спасибо.

Приложение:

Здравствуйте, Masada!
Давай по порядку...
0. Сначала давай разберем, как программа грузится в память.
а) ДОС выделяет (если возможно) всю оставшуюся память и строит в ней MCB,
т.е. оформляет ее как блок памяти
б) адрес сегмента этого блока памяти заносится в DS и ES
в) в начале сегмента длиной 100h строит так называемый блок PSP
г) загружает в память, начиная с DS:100h программу
д) для COM делает jmp PSP:100h (такой команды нет, это для понимания)
е) для EXE делается настройка адресов по таблице из заголовка и переход на адрес опять же из заголовка
1. Теперь о $.
Как правильно заметил, символом '$' в 9-й функции отмечается конец строки
Этот символ отрабатывается самой функцией во время выполнения программы
Кроме этого знак '$' используется ассемблером для указания адреса команды, следующей за текущей.
Заметь: во время ассемблирования! В самом коде доллара мы не найдем!
Например: jmp $ фактически ничего не делает (передает управление на следующую команду)
В нашем случае: командой finish equ $ мы запоминаем адрес конца программы как finish ($ стоит в конце программы...)
А mov cx, offset Finish-100h дает нам длину программы (разницу между концом и адресом загрузки!)
2. Командой mov si, 100h мы иницилизируем регистр si началом программы
Программа не попадала в DS:SI - она загружена в DS:100h.
Мы сами настраиваем регистры, как нам надо.
И вообще, откуда взял, что DS:DX - адрес программы? После загрузки программы
все регистры в общем случае неопределены.
3. Команда jmp dword ptr cs:[Off_move] предполагает, что надо сделать длинный переход
по адресу, хранящемуся в длинном слове Off_move.
Что мы и имеем в программе.
Твоя же модификация заставляет интерпретировать как длинный адрес двойное слово по адресу Lab_jmp.
Подумай сам, это одно ли тоже?
Мы же хотим перейти в сегмент 0BF00h, на тоже смещение...
А вообще, молодец, что пытаешься сам разобраться, пусть неправильно, но расуждаешь.
Удачи!

Лысков Игорь Витальевич

Мастер-Эксперт
13.11.2007, 10:52
Ответ # 194207 от an42
Здравствуйте, Masada!
Ответ на вопрос 1. $ - счетчик текущего адреса, показывает смещение от начала сегмента до самого знака $. Пример:
data segment
metka1=$ ; metka1=0, так как от начала сегмента до $ (metka1) ноль байт
mes1 db ‘abcd’
metka2=$ ; metka2=4, так как от начала сегмента до $ (metka2) четыре байта
mes2 db ‘12345’
metka3=$-mes2 ; metka3=9-4=5, так как от начала сегмента до $ (metka3) девять байт (4 байта это mes2 и 5 байтов это mes3) смещение mes3 в сегменте data составляет 4, поэтому metka3 имеет значение 5 (сам знак $ в сегменте имеет нулевую длину, только не путать с ‘$’ – это 1 байт).
Аналогично $ работает и в сегменте команд (определяет длину программы от начало сегмента команд до знака $).
Строка mov cx,offset Finish-100h, эту строку можно было записать так mov cx, Finish-100h, где Finish equ $.
В этих двух случаях в cx заносится длина кода (в байтах) программы до Finish.

Ответ на вопрос 2. Строка mov si,100h определяет начало программного кода в сегменте CS, но так как вирус пишется в COM исполнении, то все сегменты cs, ds, ss, es имеют один и тот же адрес (директива assume), а то что код начинается с адреса 100h это требование COM – формата.
Адрес DS:DX – нужен для реализации например функции 09h прерывания 21h.
Далее в программе есть строка
mov es, Seg_move ;где Seg_move dw 0bf00h
mov di, 100h
эти строки необходимы для адреса приемника ES:DI
строка
rep movsb
это строковая операция которая копирует бай находящейся по адресу DS:SI (это код программы) в область памяти расположенной по адресу ES:DI, rep число повторений (число раз копирований) определяет регистр cx.

Ответ на вопрос 3. При выполнении команды jmp dword ptr cs:[Off_move], будет сформирован адрес состоящий из двух слов. Первое слово (младшее) будет считано по адресу cs:[Off_move], второе (старшее) слово будет считано по адресу cs:[Seg_move], и будет совершен межсегментный переход.
При выполнение команды jmp dword ptr cs:[offset Lab_jmp] будет сформирован адрес перехода на метку Lab_jmp, так как явно указываем текущей сегмент и адрес метки в этом сегменте. Компоновщик компонуя программу вычислит длину адреса, а она окажется меньше 64K поэтому он заменит код перехода на короткий или внутрисегментный. Поэтому команда jmp dword ptr cs:[offset Lab_jmp] равносильно команде jmp Lab_jmp.

Удачи

an42

Посетитель
16.11.2007, 09:53
Мини-форум консультации # 109152
Нет сообщений в мини-форуме
Возможность оставлять сообщения в мини-форумах консультаций доступна только после входа в систему.
Воспользуйтесь кнопкой входа вверху страницы, если Вы зарегистрированы или пройдите простую процедуру регистрации на Портале.

Лучшие эксперты раздела

Зенченко Константин Николаевич

Старший модератор

Рейтинг: 164

Коцюрбенко Алексей Владимирович

Старший модератор

Рейтинг: 47

Лысков Игорь Витальевич

Мастер-Эксперт

Рейтинг: 0

Evgen aka Chuma

6-й класс

Рейтинг: 0

cain52

3-й класс

Рейтинг: 0

Kdsfofwe21

2-й класс

Рейтинг: 0