Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Ассемблер? Это просто! Учимся программировать Запус программ


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

Ассемблер? Это просто! Учимся программировать
______________________________________

Выпуск N 029 (Запуск программ)

Приветствую вас, уважаемые подписчики!

Сегодня в номере:

  • Информация для новых подписчиков

  • Новости

  • Ваши письма

  • Запуск программ

  • Наши партнеры


  • Благодарю Вас, что подписались на рассылку "Ассемблер? Это просто! Учимся программировать". Надеюсь, что Вы не останетесь равнодушны к ней и почерпнете море полезной информации, а также повысите свой уровень в "общении" с IBM-совместимыми компьютерами.

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

    Все, что нужно для изучения Ассемблера (предыдущие выпуски, необходимые программы, документацию, форму для подачи вопроса экспертам, а также многое другое), можно найти на сайте http://www.Kalashnikoff.ru. Рекомендую Вам сперва ознакомиться с разделом "Для новых подписчиков".

    Если у Вас нет выхода в Сеть, то предыдущие выпуски рассылки, файлы-приложения и информацию для новеньких можно получить по почте, направив пустое письмо по адресу AssmIssues@Kalashnikoff.ru. Архив (420 Кб) будет выслан Вам автоматически в течение двух рабочих дней с момента получения Вашего письма. Однако, пожалуйста, не злоупотребляйте этим, т. к. высылка писем подобного объема несет существенную нагрузку на почтовые сервера. Обращаю также Ваше внимание на тот факт, что бесплатные сервера (mail.ru, beep.ru, newmail. ru и т.п.) не всегда работают корректно. Если письмо к Вам не придет в указанный выше период, то попробуйте отправить запрос еще раз.


    Новости

    1. Начала работать рассылка "Ассемблер? Это просто! Учимся программировать (FAQ)". Честно говоря, даже не думал, что вопросов будет так много, да и вовсе не ожидал, что эксперты будут так оперативно давать ответы. Очередной раз выражаю благодарность ВСЕМ экспертам, а также подписчикам, задающим вопросы.

    ____________

    2. Сайт перехал на новую хостинговую платформу Majordomo.ru, в связи с чем были небольшие перебои в работе сайта, за что приношу свои извенения (об этом я старался заранее сообщать на головной странице сайта).

    Для чего нужно было переходить к новому хостеру?

    Плюсы очевидны:

    1. Теперь я могу обрабатывать почту Перлом, что позволит экспертам и подписчикам, задающим вопросы, отправлять их (вопросы / ответы) по почте, не заходя на сайт. Осталось дело за "малым": написать программу обработки вопросов.

    2. Существенно увеличен размер почтового ящика (до 75 Мб).

    3. Возможность использования crontab (если правильно пишу). Это такая штука, которая позволяет запускать какую-нибудь программу на Перле в определенное время. Очень удобно, например, для обновления базы данных; высылки предыдущих выпусков (скажем, каждые 30 минут проверять ящик и высылать письма. Для этого мне необязательно сидеть в Сети и пользоваться The Bat!) и пр.

    4. Возможность создания поддоменов (доменов третьего уровня). Кстати, новый адрес форума теперь такой: http://forum.kalashnikoff.ru. Вскоре планирую полностью разделить программирование и законодательство.

    5. Использование MySQL. Правда, пока толком не разобрался что это вообще такое, но, думаю, со временем научусь всему (говорят, что MySQL - это программа для создания баз данных. Если так, то экспертные группы будут работать гораздо быстрее. Нужно только время...).

    В общем, еще дополнительно много чего нового.

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

    ____________

    2. Открыты еще две рассылки:

    1. "От Советского Информбюро" (state.politics.discussion):
    В рассылке рассматриваются различные точки зрения по поводу развала СССР, объединения СНГ, политики НАТО, действий президентов различных стран, способы возрождения России и стран СНГ, Союзный Договор между Россией и Беларусью и пр. Кроме этого, обсуждения и вспоминания прежних советских времен, плюсы и минусы, ностальгия по прошлому (или наоборот), проблемы современной молодежи и многое другое...

    2. "Было время... Был я ламмер..." (rest.joke.lammer):
    Реальные юморные истории, анекдоты, рассказы, шутки и многое другое от настоящих Ассемблерщиков!

    Подписаться можно в приведенной ниже форме:

    Рассылки Subscribe.Ru
    От Cоветского Информбюро
    Было время... Был я ламмер...

    Ассемблер? Это просто! Учимся программировать (FAQ)

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

    Надеюсь, что рассылки будут интересны вам!


    Олег, у меня к тебе есть небольшое предложение.

    Давай как-нибудь займемся написанием собственной операционной системы, а? Писать под "окна" конечно интересно, но в них столько "БАГОВ"... Давай что-нибудь СВОЕ сделаем, нас ведь много... Что-нибудь типа Линукса (в смысле свободного кода)... Интересно ведь...

    Давай просто еще раз проведем голосование... А?

    __________

    С удовольствием! Если это заинтересует соответствющее количество подписчиков, то будем делать рассылку. Жду письма от заинтересованных лиц: OS@Kalashnikoff.ru.


     

    4BH(1).asm
    4BH(2).asm

    Test.asm


    Сегодня целый выпуск посвящен функции 4Bh прерывания 21h (загрузка и запуск программ). Почему так? Дело в том, что запустить программу на Ассемблере - задача нетривиальная, как может показаться с первого взгляда, тем более, что поступает много вопросов по этой теме.

    Итак-с, начнем...

    Обратите внимание, что в приложении находятся три небольших файла: 4BH(1).ASM, 4BH(2).ASM и Test.asm. Не спешите их ассемблировать! Прочтите сперва выпуск до конца!

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

    1. Выделить память для загружаемой программы;

    2. Ужать стек, если это com-файл;

    3. Сохранить необходимые регистры;

    4. Подготовить EPB;

    5. Подготовить строку с именем файла, который будем запускать;

    6. Подготовить командную строку;

    7. Сохранить сегментные регистры (если необходимо);

    8. Сохранить стековые регистры (SS и SP);

    9. Запустить программу (вызвать int 21h).

    С этого момента (с момента вызова 21h-ого прерывания) наша программа (родительская) находится в памяти до тех пор, пока запущенная программа не отработает.

    Как только она отработала, управление получает наша (родительская) программа. Что делаем дальше:

    1. Восстановим стековые регистры (SS и SP);

    2. Восстановим сохраненные в стеке регистры (сегментные и пр., если их сохраняли);

    3. Произвести другие необходимые действия.

    Вот, собственно, и все.

    ___________________

    Теперь рассмотрим, как это все происходит на практике.

    Шаг 1: Отводим (урезаем) память.

    (1) mov bx,offset Finish
    (2) shr bx,4
    (3) inc bx
    (4) mov ah,4Ah
    (5) int 21h

    Надеюсь, что вы помните о том, что метка Finish у нас последняя.

    Зачем нужно урезать память перед загрузкой?

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

    В первой строке загружаем в регистр BX адрес (смещение) последнего байта нашей программы. Это понятно.

    Зачем же во второй строке мы сдвигаем на 4 бита вправо это смещение? Дело в том, что функция 4Ah (изменение размера отведенной памяти) требует указания в регистре BX блока памяти размером 16 байт. Т.е., загрузив в BX единицу, мы отведем не один байт, а сразу шестнадцать (т.е. один параграф).

    Загружая в BX адрес последнего байта нашей программы, мы получаем не количество параграфов, а количество байт. Т.о., не разделив BX на 16, мы отведем памяти в 16 раз больше. Делим же мы так: просто сдвинем число в BX на 4 вправо, что эквивалентно делению BX на 16. Мы это уже проходили...

    А для чего увеличиваем BX на единицу (3)? Для уверенности. Лучше отведем на 16 байт больше, чем на один меньше...

    Теперь у нас BX содержит количество параграфов (блоков памяти по 16 байт), которые заняла наша программа в памяти.

    ___________

    Шаг 2: Переносим стек в область PSP (0FFh).

    (1) mov sp,0FFh

    Зачем? Вспомните, что при загрузке com-программы в память, смещение стека находится в самом низу сегмента, в который загрузилась программа (т.е. 0FFFEh). Но мы ведь ужимаем память до метки Finish! Получается, что программа будет загружаться в первый байт после этой метки. Т.о. мы затираем стек.

    Чтобы этого не произошло, перенесем стек в область PSP (все равно она не используется в нашем примере, а это лишние 256 байт, куда можно переместить указатель стека).

    ___________

    Шаг 3: Готовим EPB.

    (1) mov bx,offset EPB
    (2) mov C_F,cs

    Что такое EPB?

    EPB - EXEC Parameter Block - блок параметров функции загрузки файла. В этом блоке должна содержаться следующая информация:

    Смещение Длина Содержимое
    00h 2 Сегмент окружения DOS для порождаемого процесса
    02h 4 Смещение и сегмент адреса командной строки
    06h 4 Первый адрес блока FCB
    0Ah 4 Второй адрес блока FCB
    0Eh 2 Длина EPB

    А вот, как мы обозначаем его в Ассемблере:

    ; === Exec Parameter Block (EPB) для функции 4Bh ===
    EPB:
    Env dw 0
    ;Сегмент среды (окружения DOS) для загружаемой программы
    C_O dw offset Comm_line
    ;Смещение командной строки +
    C_F dw 0
    ;+ сегмент командной строки
    dd 0
    ;FCB 1
    dd 0
    ;FCB 2
    Len dw $-EPB
    ;Длина EPB

    Сегмент окружения DOS.

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

    Окружение DOS хранит в себе настройки (текущие параметры), которые передаются, в частности, при загрузке ОС в файле autoexec.bat. Например:

    TEMP=C:\WINDOWS\TEMP
    PROMPT=$p$g
    COMSPEC=C:\WINDOWS\COMMAND.COM
    PATH=D:\PERL\BIN;C:\WINDOWS
    windir=C:\WINDOWS
    BLASTER=A220 I5 D1 H5 P330 T6 E620

    Посмотреть текущие параметры можно выполнив внутреннюю команду set в приглашении DOS.

    Итак, если в поле "Сегмент окружения DOS..." находится 0, то программа получит те параметры, которые получила наша программа (т.е. значения передаются по умолчанию).

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

    Но, как правило, в это поле практически все программы заносят нуль.

    Для чего нужно тогда создавать свое окружение DOS? Ну, в разных случаях... Например, некоторая антивирусная программа, запуская чужую, может не передать текущее окружение, принимая во внимание тот факт, что некоторые вирусы размножаются по пути (PATH), который они сами находят в памяти (вспомним из прошлых выпусков, что найти сегмент окружения DOS можно по смещению 2Ch сегмента, в который загрузилась программа. Смещение всегда будет равно нулю).

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

    Обратите также внимание, что нам нужно заносить только один байт (смещение), а не два (сегмент + смещение). Как уже отмечалось выше, смещение всегда будет равно нулю.

    Смещение и сегмент командной строки.

    Здесь все просто. Создаем некий массив и заносим в это поле ВНАЧАЛЕ смещение, а ЗАТЕМ сегмент этого массива.

    Например, так:

    Comm_line db 5,' abcd',0Dh

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

    C_O dw offset Comm_line ;Смещение командной строки
    mov C_F,cs ;Сегмент командной строки

    Уверен, что вы уже знаете, как устроена командная строка, т.к. мы неоднократно ее уже разбирали. Тем не менее, опишу вкратце (по приведенному выше примеру (Comm_line):

    Первый байт - длина строки (включая символ 0Dh);
    Остальные байта - сама строка;
    Последний байт - 0Dh (обязательно!).

    Первый и второй адрес блоков FCB.

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

    ________________

    Шаг 4: Сохраняем регистры

    (1) pusha
    (2) push ds
    (3) push es
    (4) mov SS_Seg,ss
    (5) mov SP_Seg,sp

    Сохранять такие регистры, как AX, BX, CX, DX, SI, DI и т.п. не обязательно, если вы, конечно, не сохраняете в них информацию, которая понадобится после завершения порожденного процесса. Однако, в нашем примере мы это делаем. Для наглядности и полноты (строка (1)).

    Сегментные регистры (DS и ES) также сохранять не обязательно, если они все перед запуском новой программы были равны CS. Просто в таком случае (если они равны CS), то мы можем после завершения порожденного процесса сделать так:

    push cs
    push cs
    pop ds
    pop es

    Но мы их все-таки также сохраним (строки (2) - (3)).

    Затем идут регистры указателя стека (SS:SP). Сохранить в стеке мы их не можем. Думаю, что это понятно и так. Для такой цели выделяем две переменные, в которые мы их и занесем.

    Шаг 5: Запуск программы

    (1) mov ah,4Bh
    (2) mov dx,offset File
    (3) mov al,0
    (4) int 21h

    Итак, функция 4Bh (1). В DX заносим смещение строки с файлом (2). Это все просто.

    Далее. Подфункция 0 функции 4Bh прерывания 21h - загрузка и запуск программы (3).

    Это значит, что программа будет загружена в память и запущена.

    Существуют также подфункция 1, которая только загружает программу, но не передает ей управление.

    И подфункция 3 - загрузка оверлея.

    Подфункции 1 и 3 используются редко и мы их пока рассматривать не будем. Наша цель - заставить программу загрузиться и выполниться.

    Все! После выполнения строки (4) пойдет загрузка. Следующая за ней строка получит управление только тогда, когда завершит работу загруженная программа.

    _________________

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

    Шаг 1: Восстановление регистров стека

    mov ss,cs:SS_Seg
    mov sp,cs:SP_Seg

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

    Обратите внимание, что т.к. мы не уверены, что отработанная программа не поменяла регистры DS, то обращаемся мы к переменным SS_Seg и SP_Seg, используя регистры CS, который, как мы уже знаем, всегда равен тому сегменту, в котором выполняется текущая команда.

    Шаг 2: Восстановление иных сохраненных регистров

    pop es
    pop ds
    popa

    В нашем примере мы сохраняли эти регистры (см. выше).

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


    Ну что, уважаемые читатели, сложно? Нисколько! Почему же тогда поступало столько вопросов на эту тему?

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


    1. Рассылка "Уроки для начинающих программистов".

    Одна из лучших рассылок по программированию для начинающих. Проект Эдуарда Дмитриева.

    ___________

    2. Рассылка Сергея Никифорова "Программирование на Visual Basic и ASP" на Subscribe.ru (код рассылки: comp.soft.prog.vbs).

    Название и сайт автора: Visual Basic Streets, http://www.vbstreets.ru.

    ___________

    3. Рассылка "Мир программирования на Visual BASIC и HTML" (http://soobcha-vb.narod.ru/alex):

    Подписаться на рассылку Кувалина Алексея
    Мир программирования на Visual BASIC и HTML

    С уважением,

    Калашников Олег: Assembler@Kalashnikoff.ru
    Мой ICQ No.:
    68951340
    URL сайта подписчиков:
    http://www.Kalashnikoff.ru
    Форма для подачи вопроса:
    http://www.Kalashnikoff.ru/Experts/Question.html

    ______________

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

    1. Публичное размещение материала из рассылки: Cooperation@Kalashnikoff.ru
    2. Реклама на сайте, в книге и рассылках: http://www.Kalashnikoff.ru/Reklama.html, Reklama@Kalashnikoff.ru
    3. Издание книги по материалам рассылки (спонсорство): Sponsor@Kalashnikoff.ru

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


    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Отписаться Рейтингуется SpyLog

    В избранное