На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Все статьи должны быть оформлены согласно Правил оформления статей.
2. Любые обсуждения должны происходить в специальной теме, обсуждение в любых других темах раздела запрещены.
3. Запрещается писать статьи о создании и распространении вирусов, троянов и других вредоносных программ!
4. За грамотно написанные и правильно оформленные статьи авторы награждаются DigiMoney.

Дополнительные ссылки:
Желаю творческих успехов! ;)
Модераторы: Jin X
  
    > Изучаем ассемблер. Часть 1 , Windows, Общие вопросы (журнал Sources.Ru)
       
      Изучаем ассемблер. Часть 1

      Предисловие

      С этой статьи я начинаю цикл статей «Изучаем Ассемблер». Основная идея состоит в том, что я знаю ассемблер не лучше вас и я как бы изучаю ассемблер вместе с вами. Предполагается, что вы уже хотя бы немного знакомы с любым языком программирования. Итак, начнем!

      Основы

      Какой компилятор выбрать? Компиляторов ассемблера существует очень много. Самые популярные из них: MASM, TASM, FASM, NASM. Большинство примеров будет на MASM’е, но большинство компиляторов мало чем отличаются по синтаксису. Скачать MASM можно на http://www.masm32.cjb.net/. Вместе с MASM поставляется редактор для него. Перед тем, как компилировать программу нужно ее сохранить(File->Save). Теперь можно откомпилировать(Project->Build All). Чтобы запустить вашу программу нажмите Project->Run Program.
      Теперь о структуре программы. Вот «скелет» стандартной программы:
      ExpandedWrap disabled
        .386
         
        .model flat, stdcall
        option casemap :none
         
        ;подключение библиотек,необходимых нам
        include \MASM32\INCLUDE\windows.inc
        include \MASM32\INCLUDE\masm32.inc
        include \MASM32\INCLUDE\gdi32.inc
        include \MASM32\INCLUDE\user32.inc
        include \MASM32\INCLUDE\kernel32.inc
        includelib \MASM32\LIB\masm32.lib
        includelib \MASM32\LIB\gdi32.lib
        includelib \MASM32\LIB\user32.lib
        includelib \MASM32\LIB\kernel32.lib
         
        ;раздел, где объявляются все константы
        .const
         
        ;раздел, где объявляются переменные, уже имеющие какое-то значение
        .data
         
        ;раздел, где объявляются переменные, еще не имеющие значения
        .data?
         
        .code
        start: ;с этого слова начинается код программы
        invoke ExitProcess,0
        end start ;с этого слова заканчивается код программы
         
        Советую сохранить этот «скелет» в отдельном файле для удобства. В большинстве наших программ мы будем использовать функции WinAPI. Давайте напишем программу, которая будет выводить всплывающее окно с каким-либо сообщением. Для вывода этого окна мы будем пользоваться функцией MessageBox:
         
        .386
         
        .model flat, stdcall
        option casemap :none
         
        include \MASM32\INCLUDE\windows.inc
        include \MASM32\INCLUDE\masm32.inc
        include \MASM32\INCLUDE\gdi32.inc
        include \MASM32\INCLUDE\user32.inc
        include \MASM32\INCLUDE\kernel32.inc
        includelib \MASM32\LIB\masm32.lib
        includelib \MASM32\LIB\gdi32.lib
        includelib \MASM32\LIB\user32.lib
        includelib \MASM32\LIB\kernel32.lib
         
        .data
        message db "Sources.RU Magazine",0 ;переменная с сообщением
        mestitle db " Sources.RU Magazine ",0 ;переменная с заголовком
         
        .code
        start:
        invoke MessageBox,0,ADDR message,ADDR mestitle,MB_OK ;выводим сообщение
        invoke ExitProcess,0 ;завершаем программу
        end start


      Как можно увидеть в примере, все API-функции вызываются с помощью команды invoke. Сначала нужно написать имя функции, а потом все ее параметры, то есть:
      ExpandedWrap disabled
        invoke имя_функции, [параметр1, параметр2, параметр3, … …]


      У многих сразу возникнет вопрос: где взять справочник по API? Я отвечу: а искать не пробовали? Но если все-таки не нашли, то я пользуюсь API-Guide(http://www.allapi.net/). Это справочник по API для VB, но он подходит и для ассемблера. А вообще сети их полно, просто нужно хорошо поискать.

      Математика

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

      переменная=число1 + число2

      В ассемблере все по-другому. Чтобы сложить, вычесть, умножить или разделить два числа он использует не переменные, а регистры процессора. Регистр процессора – это как бы переменные, которые находятся в процессоре. Вот таблица с основными регистрами:
      EAX используется для сохранения числа и для счета
      ECX используется для счета
      EDX сохраняет остаток от деления
      EBX может быть использован для всего
      ESI используется для управления строками
      EDI также используется для управления строками
      И таблица с основными операторами, которые используются для счета:
      MOV EAX,число1 копирует число1 в регистр EAX
      ADD EAX,число1 прибавляет к содержимому EAX число1
      SUB EAX,число1 отнимает от содержимого EAX число1
      MUL регистр1 используется для умножения, умножает содержимое регистр1 на число, которое всегда хранится в EAX и сохраняет результат в EAX
      DIV регистр1 Делит содержимое EAX на содержимое регистр1 и сохраняет результат в EAX

      Вообще все арифметические операции в ассемблере производятся между регистром и аккумулятором, то есть регистром EAX. В операторах MUL и DIV только один параметр, потому что ассемблер сразу знает, что второе число хранится в EAX. Но почему же в операторах SUB и ADD два параметра, а не один? Об этом мы поговорим позже после того, как рассмотрим пример в конце статьи.
      Теперь немного подробнее об арифметике. В регистре EDX всегда хранится остаток от деления и вы должны запомнить, что перед делением нужно обязательно очистить этот регистр. Это можно сделать так:
      ExpandedWrap disabled
        MOV EDX,0

      или так:
      ExpandedWrap disabled
        XOR EDX,EDX

      Между этими двумя способами нет никакой разницы, но второй способ быстрее. Привожу пример программы, вычисляющей число 7*30-40*2:
      ExpandedWrap disabled
        ; в программе есть то, о чего я еще не объяснял, но я объясню вам это позже
        .386
         
        .model flat, stdcall
        option casemap :none
         
        include \MASM32\INCLUDE\windows.inc
        include \MASM32\INCLUDE\masm32.inc
        include \MASM32\INCLUDE\gdi32.inc
        include \MASM32\INCLUDE\user32.inc
        include \MASM32\INCLUDE\kernel32.inc
        includelib \MASM32\LIB\masm32.lib
        includelib \MASM32\LIB\gdi32.lib
        includelib \MASM32\LIB\user32.lib
        includelib \MASM32\LIB\kernel32.lib
        wsprintfA PROTO C :DWORD,:VARARG
        wsprintf equ <wsprintfA>
         
        .data
        bufferforstring db 10 dup(0)
        titlestring db "Результат",0
        szformat db "%u",0
         
        .code
         
        start:
        mov eax,7 ;заносим в EAX 5
        mov ecx,30 ;заносим в ECX 25
        mul ecx ;умножаем EAX на ECX
        mov ebx,eax ;заносим содержимое EAX в EBX
        mov eax,40 ;заносим в EAX 40
        mov ecx, 2 ;заносим в ECX 2
        mul ecx ;заносим в ECX 2
        sub ebx,eax ;отнимаем от EBX EAX
        invoke wsprintf,addr bufferforstring,addr szformat,eax
        invoke MessageBox,0,ADDR bufferforstring,ADDR titlestring,MB_OK ;выводим резульат
        invoke ExitProcess,0
        end start

      Помните, как я обещал объяснить, почему в mul и div один параметр, а в sub и add их два? На самом деле ответ прост. Вспомните правила арифметики. Ведь умножение и деление должно производится раньше, чем сложение и вычитание! То есть, чтобы решить наше выражение(7*30-40*2), нужно где-то хранить результат 7*30 и 40*2, EAX мы использовать не можем, так как он используется в арифметических операциях. Поэтому приходится хранить результат 7*30 в EBX. Конечно, в нашем случае в операторе sub все равно используется EAX. Но подумайте, что было бы, если бы у нас было в выражении не одна операция вычитания или сложения, а несколько?
      Вот и конец статьи! Надеюсь, что вы все поняли, если нет, то пишите письма miksayer@mail.ru. Удачи!
      С уважением, Miksayer!
      Сообщение отредактировано: 7in X -
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0287 ]   [ 15 queries used ]   [ Generated: 24.04.24, 08:32 GMT ]