I have had my program running on MINGW32 in WinXp. The program is complied by gcc and get the expected result with gdb debug tool. But when directly run it under MINGW32, the WinXp will report errors that:
«0x7c956a6e» instruction have referenced the memory of «0x00000000». This memory cannot be «read».
Then how to locate this instruction? I have checked and it seems caused by a malloc function. The source code is as below:
int find(FILE *fp, char **head) {
char str[100];
char *p, c;
int i = 0, j = 0;
do {
c = fgetc(fp);
if(c == EOF)
return 0;
} while(c == ' ' || c == 'n');
while(c != ' ' && c != 'n') {
str[i++] = c;
c = fgetc(fp);
}
*head = (char *)malloc(sizeof(char) * i);
if(*head == NULL)
printf("nCannot get memory (find)");
else {
p = *head;
for(j = 0; j < i; j++) {
*(p++) = str[j];
}
*p = '';
return 1;
}
return 0;
}
It is appreciated if anyone can help!
10/7 Thanks for the comments. Here is the rest of the code and the data pattern:
int main()
{
FILE *fp;
int lines = 0, i = 0;
TianYa *yp, *linep;
char *head = NULL;
fp = fopen("tysample.txt", "r");
if(fp == NULL)
printf("nCannot open file");
else {
yp = (TianYa *)malloc(TIAN_YA_LINES * sizeof(TianYa));
if(yp == NULL)
printf("nCannot get memory (main)");
else {
linep = yp;
i = 0;
while(find(fp, &head) != 0) {
switch(i++) {
case 0:
linep->name = head;
break;
case 1:
linep->passwd = head;
break;
case 2:
linep->email = head;
i = 0;
linep++;
lines++;
break;
}
}
}
}
linep = yp;
for(i = 0; i < lines; i++) {
printf("nName:%s, Passwd:%s, Email:%s", linep->name, linep->passwd, linep->email);
/* free(linep->name);
free(linep->passwd);
free(linep->email);
*/ linep++;
}
free(yp);
yp = NULL;
linep = NULL;
if(fclose(fp))
printf("nFailed to close file");
return 0;
}
momre 123456 baitianyang@live.cn
白天也懂 123456 baitianyedong@tianya.cn
baitiansosuo weirenminfuwu baitianyouxiang@sohu.com
heng__chang 87732351 baitianyu.06@163.com
风正 5581100 baitianyu@126.com
sparkbai 20001228 baitianyu@tianya.cn
背粪篓进银行 19851019 baitianyu123@163.com
白天月 11200929 baitianyue@126.com
Всем привет! Сегодня будет небольшая заметка по ошибке которая выскакивает при запуске приложения, которое вы только что скачали с интернета и поставили, но при запуске его вы видите ошибку которая звучит так:
или если дословно, то:
Инструкция по адресу 0x0 *** обратилась к памяти по адресу 0x0 ***. Память не может быть read (write)»
В моем случае это была игра battlefield 3 которую скачали с торрента и пытались запустить на windows 7, но при каждом запуске пользователь не рубился с врагами на поле боя, а шерстил интернет в поисках проблемы!
Уже с windows 7 была добавлена новая защита под названием Data Execution Prevention или сокращённо DEP.
DEP – это технология которая имеет набор инструкций которые предотвращают запуск “плохого” программного кода для исполнения.
И если у вас вылетела ошибка с текстом – “Инструкция по адресу обратилась к памяти по адресу” это на 99% может означать, что вы запускаете опасное приложение! НО бывают и такие ситуации когда в результате конфликта системных библиотек или приложений у вас приложение которое работало перестало запускать, тогда для решения этих проблем воспользуйтесь одной из инструкций ниже.
Все варианты я буду описывать так, что надо начинать с первого варианта.
1 Вариант
Отключите все антивирусы и запустите приложение заново
2 Вариант
Если это приложение или игра, то у нее наверняка есть сайт, где можно скачать обновленную версию, даже если вы скачали с торрента.
3 Вариант
Обновите до последней версии ваш Windows (если у вас пиратская windows, то скачайте архив автономных обновлений) В большинстве случаев это помогает!
4 Вариант
Если после отключения всех защит и обновления программ и windows ошибка до сих пор вылетает, тогда необходимо воспользоваться стандартной утилитой которая починит и восстановит системные файлы вашей windows
5 Вариант
Мы подошли к варианту когда уже было сделано все возможное и для того что бы убедиться, что запуск программы блокируется не на уровне защиты windows мы отключим DEP
Отключаем DEP через командную строку
Сразу говорю, что последствия могут быть необратимыми!!
- Запускаем консоль cmd от имени Администратора
- вводим команду
bcdedit.exe /set {current} nx AlwaysOff - На мониторе должно быть написано – Операция успешно завершена
Отключаем DEP вручную
Кто не доверяет консолям, то вот вариант как это сделать вручную.
- Заходим в систему
- Выбираем Дополнительные параметры системы
- В открывшемся окне в блоке Быстродействие нажимаем на кнопку Параметры
- Далее переходим на вкладку Предотвращение выполнения данных
- Переключаете переключатель на – Отключить DEP для всех программ и служб, кроме выбранных ниже.
рис.3 – Включить DEP для всех программ и служб, кроме выбранных ниже - Перезагружаем компьютер
Если Вам не помог не один из способов, пишите в комментарии или мне на почту, будем разбираться.
PS
А в моем случае ошибка которая вылетала при запуске игры была устранена обновлением в лаунчера игры (это второй способ по соей инструкции)
возникшая проблема привела к прекращению работы программы. windows закроет эту программу, а если есть известный спосбо устранения проблемы, уведомит вас об этом.
Вопрос от пользователя
Здравствуйте.
При попытке запустить игру PUBG — вылетает ошибка, что «память не может быть прочитана».
Подскажите, что можно с ней сделать? (переустановка игры и системы — не помогла…)
Здравствуйте.
Не буду оригинальным, но, если подобная ошибка вылетает при запуске игры (загруженной с интернета из неизвестного источника) — есть высокая вероятность, что вы пытаетесь запустить опасное приложение, а система предотвращает сие действие.
Ниже в статье рассмотрю общую последовательность действий для устранения подобной проблемы.
Память не может быть «Read» / «Written» — внешний вид ошибки при запуске игры
*
И так, как исправить ошибку…
👉 ШАГ 1
Загружаем какой-нибудь «одноразовый» антивирус (например, Dr.Web CureIt!) и проверяем папку с игрой (приложением, которое вылетает) и системный диск с Windows.
Примечание: рекомендую это сделать даже в том случае, если у вас установлен какой-нибудь антивирус.
Dr.Web CureIt! — найдена угроза!
Если будут найдены вредоносное ПО — удалите копию игры (приложения) и перезагрузите ее 👉 с офиц. магазинов. Установите и перепроверьте — как правило, после этого всё начинает работать в штатном режиме…
*
👉 ШАГ 2
Если вирусы не были найдены и с файлами игры (приложения) все в порядке — отключите временно антивирус (защитник Windows) и попробуйте еще раз запустить игру.
Примечание: в некоторых случаях антивирус может блокировать норм. работу игр. Если окажется, что «виновником» является именно защитное ПО — добавьте нужную игру в белый список антивируса…
Отключение антивируса Avast на 1 час
Безопасность Windows — параметры ОС
*
👉 ШАГ 3
Помимо штатного защитника в современных версиях Windows есть еще одна защита — DEP (это набор технологий, который предотвращает запуск прогр. кода из некоторых областей памяти). Разумеется, во многих случаях эта защита работает «криво»…
В качестве диагностики (на время) стоит ее попробовать отключить.
*
Вариант 1: запускаем 👉 командную строку от имени администратора и используем команду: bcdedit.exe /set {current} nx AlwaysOff
(для включения: bcdedit.exe /set {current} nx AlwaysOn)
*
Вариант 2:
необходимо открыть вкладку «Панель управленияСистема и безопасностьСистема» и перейти в раздел с доп. параметрами.
Доп. параметры системы
После открыть параметры быстродействия и перейти во вкладку «Предотвращение выполнения данных» и добавить то приложение, для которого нужно отключить DEP (например, проблемную игру).
DEP — настройка
*
👉 ШАГ 4
После, посоветовал бы проверить целостность системных файлов (сделать это можно в командной строке, запущенной от имени администратора).
Команда для проверки: sfc /scannow
В идеале, по завершению проверки, вы должны увидеть сообщение о том, что нарушение целостности файлов не обнаружены (см. скриншот ниже 👇).
Не обнаружено нарушений целостности — проверка системных файлов
*
👉 ШАГ 5
Проверьте, не вышли ли для ОС обновления и заплатки. Благо, что Windows 10 позволяет это сделать в авто-режиме: достаточно открыть параметры (Win+i) и перейти во вкладку «Обновление и безопасность». См. скриншот ниже. 👇
Обновление ОС Windows 10
Кроме этого, рекомендовал бы вам просканировать свою систему с помощью 👉 Driver Booster. Эта утилита не только покажет, какие драйвера нуждаются в обновлении, но и проверит все необходимые библиотеки для корректной работы игр (разумеется, прямо из окна Driver Booster их можно будет установить).
Обновить всё — игровые компоненты, звуковые и игровые устройства и пр. / Driver Booster
*
👉 ШАГ 6: еще «пару» советов
Проверьте путь установки игры
Самое главное, чтобы в нем не было русских символов (в редких случаях определенные игры могут вылетать из-за этого — т.к. неправильно читают кириллицу). Обратите внимание на пример ниже:
- корректный: C:gamesMX vs ATV All Out
- не желательный: D:игрыгонкиgamesMX vs ATV All Out
Кстати, это же относится и к папке «Мои документы». Ее расположение можно узнать, если открыть ее свойства (например, в «Моем компьютере» 👇)
Расположение документов
*
Проверьте плашки ОЗУ
Проверьте плашки ОЗУ на ошибки и сбои. О том, как сделать такой тест — 👉 у меня на блоге была отдельная заметка.
Также попробуйте отключить часть из них, оставив всего одну плашку (это для тех, у кого их 2 и более). Кстати, не лишним будет протереть контакты RAM резинкой и кисточкой…
Чистка контактов памяти резинкой и кисточкой
*
Проверьте BIOS: не разогнаны ли плашки
В BIOS/UEFI можно изменять частоту работы плашек ОЗУ (на ноутбуках, обычно, данной опции нет). И если частота выставлена не оптимальная — ПК может вести себя не стабильно: внезапно перезагружаться, «показывать» синие экраны (иногда сыпать ошибки чтения памяти).
👉 В помощь!
Как войти в BIOS (UEFI) на компьютере или ноутбуке [инструкция]
Чаще всего частота памяти помечается как DRAM Frequency (рекомендуется снизить текущую частоту на 5-10%).
Если вы слабо в этом разбираетесь — то просто перейдите в раздел «Exit» и установите 👉 безопасные настройки (Load Optimized Defaults, Load Fail-Safe Defaults). Таким образом частота будет автоматически сброшена в наиболее оптимальную для вашей системы.
Настройки ОЗУ и встроенной графики / UEFI
*
Если вы исправили ошибку как-то иначе — сообщите в комментариях (заранее благодарю!).
Всего доброго!
👣


Полезный софт:
-
- Видео-Монтаж
Отличное ПО для создания своих первых видеороликов (все действия идут по шагам!).
Видео сделает даже новичок!
-
- Ускоритель компьютера
Программа для очистки Windows от «мусора» (удаляет временные файлы, ускоряет систему, оптимизирует реестр).
Помимо встроенного антивируса Defender, Windows 8.1 имеет и другие механизмы защиты от угроз. Один из них называется Data Execution Prevention или сокращённо DEP. Представляет он собой набор технологий, предотвращающих запуск программного кода из тех областей оперативной памяти, которые не являются в Windows исполняемыми.
Однако в некоторых случаях DEP может стать причиной ошибок при запуске ряда приложений и игр.
DEP отслеживает изменения в оперативной памяти и если обнаруживает, что некая программа использует её неправильно, тут же блокирует эту программу, а пользователь получает сообщение «Предотвращение выполнения данных» или «Инструкция по адресу обратилась к памяти по адресу ***. Память не может быть read (write)». Способов решения этой проблемы существует несколько.
Если ошибка появилась «беспричинно», то есть вы до этого не устанавливали никаких программ, не изменяли параметров системы и прочее, есть смысл проверить компьютер на наличие вирусов как минимум одним сторонним антивирусным сканером. Сам DEP не препятствует проникновению на компьютер вредоносного ПО, а лишь регистрирует подозрительные изменения в памяти.
Ошибка предотвращения выполнения данных также может возникнуть вследствие повреждения системных файлов. Просканируйте систему командой sfc /scannow и убедитесь, что целостность файлов Windows не нарушена.
Если ошибка появилась после установки нового приложения либо же возникает при запуске конкретной программы, скорее всего причина кроется в неправильной работе последней. Решением может стать удаление, переустановка или переход на другую версию приложения, а также отключение DEP для всей системы или конкретных программ.
Полное отключение DEP
Чтобы деактивировать DEP, откройте командную строку от имени администратора и выполните следующую команду:
bcdedit.exe /set {current} nx AlwaysOff
Чтобы изменения вступили в силу, перезагрузите компьютер. После этого ошибка «…Память не может быть read» должна исчезнуть. Для включения DEP применяется та же команда, но с параметром AlwaysOn.
Отключение DEP для конкретных программ
К полному отключению предотвращения выполнения данных стоит прибегать лишь в крайних случаях, более разумным решением является отключение DEP для конкретных конфликтных программ. Для этого в Панели управления выбираем Система -> Дополнительные параметры системы -> Дополнительно -> Параметры (Быстродействие).
В открывшемся окошке переключаемся на вкладку «Предотвращение выполнения данных», активируем радиокнопку «Включить DEP для всех программ и служб, кроме выбранных ниже», а затем указываем путь к исполняемому файлу программы, вызывающей ошибку DEP.
Сохраняем результат и перезагружаемся.
Загрузка…
Бонд. Джеймс Бонд.
Рейтинг (т): 49
Использование стандартного отладчика debug.exe
Сегодня мы рассмотрим стандартный отладчик debug.exe, входящий в любую версию DOS/Windows. Должен заметить, что этот отладчик не такой мощный, как гиганты SoftICE или Turbo Debugger. Однако, в то же время debug.exe очень прост и доступен, и поэтому идеально подходит для начинающих программистов на языке Ассемблер.
Итак, запускаем debug.exe (для этого заходим в Пуск->Выполнить и выполняем команду debug) и начинаем изучать этот замечательный отладчик
Команды debug.exe
Для начала разберемся с правилами набора команд debug.exe:
- В debug.exe не различается регистр букв.
- Пробелы в командах используется только для разделения параметров.
- Вводимые числа должны быть в шестнадцатеричной системе счисления, причем без завершающей буквы h.
- Сегмент и смещение записываются с использованием двоеточия, в формате сегмент:смещение, например, CS:3C1 (смещение 3C1h в сегменте кода) или 40:17 (смещение 17h в сегменте, адрес начала которого — 40[0]h).
Разобравшись с правилами, давайте перейдем к изучению команд debug.exe. Замечу, что работа с командами debug.exe в чем-то похожа на работу с командной строкой DOS. Поcле загрузки отладчика на экране появится приглашение, выглядещее в виде дефиса:
-_
Регистры CS, DS, ES, SS в этот момент инициализированы адресом 256-байтного префикса сегмента програмы, а рабочая области в памяти будет начинаться с адреса этого префикса + 100h.
Команды debug.exe вводятся сразу после приглашения на месте, которое отмечено курсором. Каждая команда состоит из идентификатора и параметров, идентификатор состоит из одной буквы.
Краткая таблица всех команд debug.exe
| Команда | Описание | Формат |
|---|---|---|
| A (Assemble) | Транслирование команд ассемблера в машинный код; адрес по умолчанию — CS:0100h. |
A [<адрес_начала_кода>] |
| C (Compare) | Сравнение содержимого двух областей памяти; по умолчанию используется DS. В команде указывается либо длина участков, либо диапазон адресов. |
C <начальный_адрес_1> L<длина> <начальный_адрес_2> C <начальный_адрес_1> <конечный_адрес_1> <начальный_адрес_2> |
| D (Display/Dump) | Вывод содержимого области памяти в шестнадцатеричном и ASCII-форматах. По умолчанию используется DS; можно указывать длину или диапазон. |
D [<начальный_адрес> [L<длина>]] D [начальный_адрес конечный_адрес] |
| E (Enter) | Ввод в память данные или инструкции машинного кода; по умолчанию используется DS. |
E [<адрес> [<инструкции/данные>]] |
| F (Fill) | Заполнение области памяти данными из списка; по умолчанию используется DS. Использовать можно как длину, так и диапазон. |
F <начальный_адрес_1> L<длина> ‘<данные>’ F <начальный_адрес> <конечный_адрес> ‘<данные>’ |
| G (Go) | Выполнение отлаженной программы на машинном языке до указанной точки останова; по умолчанию используется CS. При этом убедитесь, что IP содержит корректный адрес. |
G [=<начальный_адрес>] <адрес_останова> [<адрес_останова> …] |
| H (Hexadecimal) | Вычисление суммы и разности двух шестнадцатеричных величин. | H <величина_1> <величина_2> |
| I (Input) | Считывание и вывод одного байта из порта. | I <адрес_порта> |
| L (Load) | Загрузка файла или данных из секторов диска в память; по умолчанию — CS:100h. Файл можно указать с помощью команды N или аргумента при запуске debug.exe. |
L [<адрес_в_памяти_для_загрузки>] L [<адрес_в_памяти_для_загрузки> [<номер_диска> <начальный_сектор> <количество_секторов>]] |
| M (Move) | Копирование содержимого ячеек памяти; по умолчанию используется DS. Можно указывать как длину, так и диапазон. |
M <начальный_адрес> L<длина> <адрес_назначения> M <начальный_адрес> <конечный_адрес> <адрес_назначения> |
| N (Name) | Указание имени файла для команд L и W. | N <имя_файла> |
| O (Output) | Отсылка байта в порт. | O <адрес_порта> <байт> |
| P (Proceed) | Выполнение инструкций CALL, LOOP, INT или повторяемой строковой инструкции с префиксами REPnn, переходя к следующей инструкции. |
P [=<адрес_начала>] [<количество_инструкций>] |
| Q (Quit) | Завершение работы debug.exe. | Q |
| R (Register) | Вывод содержимого регистров и следующей инструкции. | R <имя_регистра> |
| S (Search) | Поиск в памяти символов из списка; по умолчанию используется DS. Можно указывать как длину, так и диапазон. |
S <начальный_адрес> L<длина> ‘<данные>’ S <начальный_адрес> <конечный_адрес> ‘<данные>’ |
| T (Trace) | Пошаговое выполнение программы. Как и в команде P, по умолчанию используется пара CS:IP. Замечу, что для выполнения прерываний лучше пользоваться командой P. |
T [=<адрес_начала>] [<количество_выполняемых_команд>] |
| U (Unassemble) | Дизассемблирование машинного кода; по умолчанию используется пара CS:IP. К сожалению, debug.exe некорректно дизассемблирует специфические команды процессоров 80286+, хотя они все равно выполняются корректно. |
U [<начальный_адрес>] U [<начальный_адрес конечный_адрес>] |
| W (Write) | Запись файла из debug.exe; необходимо обязательно задать имя файла командой N, если он не был загружен. А программы записываются только в виде файлов .COM! |
W [<адрес> [<номер_диска> <начальный_сектор> <количество_секторов>]] |
Примечание. Символами [] отмечены необязательные параметры.
Просмотр областей памяти
В этой части нашей статьи мы рассмотрим подробно работу команды D, позволяющей просматривать содержимое отдельных областей памяти.
Этот пример использует команду D для просмотра области памяти, начиная с 0159:0240:
-d 0159:0240
0159:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ……….l…..
0159:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
0159:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
0159:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 …………….
0159:0280 00 00 00 00 00 00 00 00-00 FF FF FF FF 00 00 00 …………….
0159:0290 FF 00 00 00 00 00 00 00-00 00 4E 4F 20 4E 41 4D ……….NO NAM
0159:02A0 45 20 20 20 20 00 26 81-4F 03 00 01 CB 00 00 00 E .&.O…….
0159:02B0 00 00 00 00 00 00 00 00-00 00 00 01 07 04 FF 02 …………….
-_
Здесь на запрос просмотра участка памяти мы получили восемь строк, в которых указано содержимое выбранной области памяти. Каждая строка состоит из трех частей:
- Адрес первого слева показанного байта в формате сегмент:смещение.
- Шестнадцатеричное представление параграфа (16 байт), начинающегося с указанного в начале строки байта.
- Символы этого же параграфа в ASCII-формате.
Адрес, указанный в строке, относится исключительно к первому байту в параграфе, а адреса последующих байтов следует вычислять самостоятельно. Шестнадцатеричное представление содержит по два знака в каждом байте, а сами байты разделены пробелами для облегчения чтения. Кроме того, следует отметить, что восьмой и девятый байты разделены дефисом, разделяя тем самым параграф на две части и облегяая вычисление адресов байтов в параграфе.
Полезные приемы с командой D
Проверка параллельных и последовательных портов
Первые 16 байт области данных BIOS содержат адреса параллельных и последовательных портов. Поэтому с помощью следующей команды можно проверить эти порты:
-D 40:00_
Первые выведенные восемь байтов указывают на адреса последовательных портов COM1-COM4. Следующие 8 байтов указывают на адреса параллельных портов LPT1-LPT4.
Например, если на вашем компьютере есть один параллельный порт, то первые два байта будут, скорее всего, такими: 7803. Адрес порта записывается в обращенной последовательности, т.е. 0378.
Проверка оборудования
Первые два байта, располагающиеся в BIOS по адресу 410h, содержат информацию об установленном в системе оборудовании. Находим эти байты командой:
-D 40:10_
Предположим, что первые два байта окажутся 23 44. Расшифруем эти байты для получения информации об установленных устройствах. Для этого обратим эти байты (44 23), затем переведем их в двоичную систему счисления. Получаем:
| Значение бита |
0 |
1 |
0 |
0 |
0 |
1 |
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
| Позиция бита | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Что означают эти биты? Продолжаем расшифровывать:
| Биты | Устройство |
|---|---|
| 15, 14 | Число параллельных портов (01 = 1 порт, …) |
| 11, 10, 9 | Число последовательных портов (…, 010 = 2 порта, …) |
| 7, 6 | Число дисководов (00 = 1 дисковод, 01 = 2, 10 = 3, 11 = 4) |
| 5, 4 | Начальный видеорежим (01 = 40х25 цветной, 10 = 80х25 цветной, 11 = 80х25 монохромный) |
| 1 | Присутствие математического сопроцессора (0 = нет, 1 = есть) |
| 0 | Наличие привода для дискет (0 = нет, 1 = есть) |
Проверка состояния регистра клавиатуры
В области данных BIOS по адресу 417h находится первый байт, который хранит состояние регистра клавиатуры. Выключаем Num Lock и Caps Lock, затем набираем команду:
-d 40:17_
Первый байт будет равен 00. Включив Num Lock и Caps Lock, снова выполняем команду. Теперь первый байт должен равняться 60. Опытным путем установлено, что при включенном Num Lock первый байт равен 20, а при Caps Lock — 40.
Проверка состояния видеосистемы
По адресу 449h в BIOS находится первая область видеоданных. Для проверки набираем:
-d 40:49_
Первый байт показывает текущий видеорежим (к примеру, 03 — цветной), а второй — число столбцов (например, 50 — режим с 80 столбцами). Число строк можно найти по адресв 484h (40:84).
Проверка копирайта BIOS и серийного номера
Сведения об авторских правах на BIOS встроены в ROM BIOS по адресу FE00:0. Строку с копирайтом можно легко найти в ASCII-последовательности, а серийный номер — в виде шестнадцатеричного числа. Хотя, строка с указанием авторских прав может быть длинной и не умещаться в выведенную область памяти. В таком случае следует просто ввести еще раз D.
Проверка даты произвоства BIOS
Эта дата также записана в ROM BIOS начиная с адреса FFFF:5. После выполнения соответствующей команды в ASCII-последовательности будет находиться эта дата, записанная в формате мм/дд/гг.
Пример:
-d FFFF:5
FFFF:0000 31 31 2F-32 38 2F 30 35 00 FC 00 11/28/05…
FFFF:0010 34 12 00 00 00 00 00 00-00 00 00 00 00 00 00 00 4……………
…
-_
Непосредственный ввод программы в память с помощью debug.exe
debug.exe позволяет вводить программу непосредственно в память машины, а затем следить и управлять ее выполнением. Мы будем вводить программу в машинных кодах, используя команду E. При этом будьте бдительны — ввод ошибочных данных по ошибочному адресу чреват непредсказумыми последствиями! Хотя к серьезным проблемам в системе это вряд ли приведет, но потерять все данные, введенные в debug.exe, можно потерять запросто.
Программа, которую мы сейчас будем вводить, использует данные, заложенные непосредственно в теле инструкций. Далее показан листинг программы на Ассемблере, в комментариях указаны аналоги команд языка в машинных кодах, а также объяснение каждй команды. Замечу, что в числах нет символа h, поскольку, как было сказано выше, debug.exe понимает только числа в шестнадцатеричной системе.
MOV AX, 0123 ; код B82301: заносим значение 0123h в AX
ADD AX, 0025 ; код 052500: прибавляем 0225h к значению AX
MOV BX, AX ; код 8BD8: заносим значение AX в BX
ADD BX, AX ; код 03D8: прибавляем значение AX к BX
MOV CX, BX ; код 8BCB: заносим значение BX в CX
SUB CX, AX ; код 2BC8: отнимаем значение AX из CX
SUB AX, AX ; код 2BC0: очищаем AX
JMP 100 ; код EBEE: переходим к началу программы
Как можно заметить, каждая машинная инструкция имеет длину от 1 до 3 байтов. Первый байт указывает операцию, последующие — ее операнды. Исполнение программы начинается соответственно с первой инструкции и последовательно проходит через все инструкции одну за другой.
Теперь можно ввести программу в память. Разделим машинный код на три части по шесть байт и введем каждую, используя команду E и начиная с адреса CS:100.
-E CS:100 B8 23 01 05 25 00
-E CS:106 8B D8 03 D8 8B CB
-E CS:10C 2B C8 2B C0 EB EE
-_
Теперь, когда программа введена в память, попробуем управлять ее выполнением. Для начала проверим текущее состояние регистров и флагов, для этого вводим команду R. Отладчик выведет содержимое регистров в шестнадцатеричной форме; на разных машинах содержимое регистров может различаться.
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15D7 ES=15D7 SS=15D7 CS=15D7 IP=0100 NV UP EI PL NZ NA PO NC
15D7:0100 B82301 MOV AX,0123
-_
Итак, как можно видеть, debug.exe инициализировал сегменты DS, ES, SS, CS одним и тем же адресом. Регистр IP содержит 0100, указывая на то, что инструкции выполняются со смещения 100h относительно CS (а мы, вводя инструкции в память, как раз указали этот адрес).
Здесь же указаны и значения флагов переполнения, направления, прерывания, знака, нуля, дополнительного переноса, четности и переноса:
| Значение | Описание |
|---|---|
| NV | Отсутствие переполнения |
| UP | Направление вверх или вправо |
| EI | Разрешение прерываний |
| PL | Положительный знак |
| NZ | Ненулевое значение |
| NA | Отсутствие дополнительного переноса |
| PO | Нечетное слово |
| NC | Отсутствие переноса |
После регистров и состояния флагов debug.exe выводит информацию о первой инструкции, которая будет выполняться:
- Адрес инструкции, в нашем случае это 15D7:0100, где 15D7 — адрес сегмента кода.
- Машинный код, соответствующей этой инструкции (B82301).
- Собственно инструкция, записанная на ассемблере (MOV AX,0123).
Теперь, после анализа содержимого регистров и флагов, давайте перейдем к выполнению программу. Выполнять программу мы будем пошагово, используя команду T. Использовав в первый раз команду T, мы выполняем инструкцию MOV. Здесь машинный код операнда инструкции — 2301. Операция помещает 23 в AL (младшая половина AX), а 01 — в AH (старшая).
После этого debug.exe снова выводит информацию о регистрах:
-t
AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15D7 ES=15D7 SS=15D7 CS=15D7 IP=0103 NV UP EI PL NZ NA PO NC
15D7:0100 B82301 ADD AX,0025
-_
Теперь AX содержит 0123h, IP — 0103h (следовательно, длина выполненной инструкции: 0103h — 0100h = 3 байта), а в качестве следующей инструкции указана операция ADD.
Так, раз за разом выполняя команду T, мы дойдем до последней инструкции JMP 100. Она установит регистр IP в 100h, и debug.exe вернется к началу программы. Возвращаясь к началу программы, следует заметить, что в DS, ES, SS и CS содержится один и тот же адрес. Дело в том, что debug.exe рассматривает введенные программы исключительно как программы .COM. А в программах .COM, в отличие от .EXE, стек, код и данные хранятся в одном сегменте.
Ассемблирование и дизассемблирование
В прошлом примере мы вводили программу в машинных кодах, однако, debug.exe вполне способен понимать инструкции, записанные на ассемблере. Для работы с такими программами в debug.exe используются команды A и U.
Команда A запрашивает инструкции на ассемблере и преобразовывает их в машинный код. Для начала инициализируем начальный адрес для ввода инструкций (100h):
-a 100_
Отладчик выведет адрес сегмента кода и смещения (например, 13F2:0100). Теперь мы должны ввести следующие инструкции на ассемблере в память, после каждой строки нажимая Enter:
MOV CL, 42
MOV DL, 2A
ADD CL, DL
JMP 100
После ввода последней инструкции нажимаем Enter дважды, чтобы указать отладчику, что мы закончили вводить текст программы. Теперь программу можно запускать, используя команды R для просмотра регистров и T для трассировки. Замечу, что в своих программах при наличии инструкций INT их следует обрабатывать не командой T, а командой P, которая обрабатывает все прерывание сразу.
Перейдем к процедуре дизассемблирования, а в качестве примера возьмем только что введенную программу. Используем адреса первой и последней инструкций для указания диапазона, который мы собираемся дизассемблировать, т.е. 100h и 107h.
-u 100, 107_
После выполнения этой команды debug.exe выведет инструкции, находящиеся в указанном диапазоне, на ассемблере, в машинных кодах, а также адрес каждой инструкции:
13F2:0100 B142 MOV CL, 42
13F2:0102 B22A MOV DL, 2A
13F2:0104 00D1 ADD CL, DL
13F2:0106 EBF8 JMP 0100
Итог
А теперь, после небольшого обзора возможностей стандартного отладчика debug.exe давайте подведем итоги. Итак:
- debug.exe можно применять для наблюдений и отладки программ на ассемблере и машинных кодах.
- debug.exe позволяет трассировать программу, устанавливать точки останова, просматривать области памяти, вводить программы непосредственно в память компьютера.
- debug.exe представляет загружаемые программы как программы .COM.
- debug.exe воспринимает только числа в шестнадцатеричной системе.
- debug.exe не различает регистр букв.
Дополнительные материалы:
Абель П. АССЕМБЛЕР: Язык и программирование для IBM PC. — К.: Век+, 2003.
http://www.allasm.ru/low_prog_01.php — низкоуровневое программирование для дZенствующих — DZebug: руководство юZверя
http://thestarman.pcministry.com/asm/debug/debug.htm — A Guide to DEBUG, by Daniel B. Sedory



























