На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила ЧаВо (FAQ) разделов Паскаля
В этом разделе разрешено создавать только темы, в которых описано РЕШЕНИЕ какой-либо общей проблемы, или описание какого-либо аспекта языка Паскаль.
Обсуждение уже созданных тем разрешено, но только конструктивное, например указание на ошибку или уточнение имеющегося текста.

Также читать Требования к оформлению статей
Модераторы: volvo877, Romtek
  
> Встроенный ассемблер , основы работы с этой штуковиной
    Встроенный ассемблер


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

    Ассемблерные инструкции пишутся примерно так:
    ExpandedWrap disabled
      program program_name;
      begin
        ...
        asm
          ...  {Здесь располагаются ассемблерные инструкции}
        end;
        ...
      end.


    Операторы asm...end работают, как операндные скобки begin...end. т.е. можно делать так:
    ExpandedWrap disabled
      for i := 1 to 100 do
        asm
          ...
        end;

    и так:
    ExpandedWrap disabled
      if ((i=0) and (k<>6)) or (t div 5 - 7 = 99)) xor (r=0) then
        asm
          ...
        end;



    Регистры

    В Турбо Паскале (вернее в МП 8086/8088) имеется 14 регистров. Их можно поделить на 5 групп:
    • регистры общего назначения (АХ, ВХ, СХ, DX); предназначены для хранения операндов и выполнения основных команд; любой из них может использоваться как совокупность двух независящих друг от друга 8-разрядных регистров: старшего байта регистра (АН, ВН, СН, DH) и младшего байта (AL, BL, CL, DL); например, АХ состоит из АН и AL;
    • сегментные регистры (CS, DS, SS, ES); используются для указания сегмента при адресации памяти;
    • регистры-указатели (SP, BP, IP); используются для указания смещения при адресации памяти;
    • индексные регистры (SI, DI); применяются для индексной адресации;
    • регистр флагов. используется для хранения признаков состояния процессора.

    Теперь подробнее:

    AX,BX,CX,DX можно использовать как переменные.
    CS, DS, SS, ES используются для указания сегмента. В частности
    CS - Содержит номер сегмента памяти (сегмента кода), в котором располагается текущая машинная инструкция
    DS - Содержит номер сегмента памяти (сегмента данных), в котором располагаются данные (константы и переменные)
    SS - Это сегмент Стека, а ES это... это дополнительный сегментный регистр, который используется для межсегментного обмена данными и в некоторых строковых операциях
    SP - Указывает на вершину стека. Совместно с регистром SS он адресует ячейку, куда будет помещаться/извлекаться операнд. BP - т.н. указатель базы. Облегчает создание и использование локального стека. IP - Определяет смещение относительно начала сегмента кода CS очередной исполняемой машинной инструкции. Содержимое IP автоматически изменяется в ходе исполнения инструкции, обеспечивая правильный порядок выборки команд из памяти.
    SI - Определяет адрес источника информации при индексной адресации данных. По умолчанию используется в паре с DS. DI - определяет приемник информации при межсегментном обмене данными. По умолчанию - в паре с ES.


    Команды.

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

    Команды пересылки данных

    MOV - Переслать значение.
    push - "Загнать" в стек
    pop - Извлечь из стека
    xchg - Обменять значения

    mov, xchg нельзя использовать для пересылки из памяти в память:
    ExpandedWrap disabled
      var
        a,b:integer;
      begin
        ...
        asm
          mov a,b {Ошибка!!!}
         { Надо так:}
          mov ax,b
          mov a,ax
        end;
        ...
      end;


    Вот пример. (В комментариях - код на Паскале, чтобы было легче разобраться)

    ExpandedWrap disabled
      asm
        mov ax,60 {ax := 60}
        push ax
        mov bx,88 {bx := 88}
        mov ax,bx {ax := bx}
        pop ax    {!!!ax := 60!!!}
        xchg ax,bx {ax = 60, bx = 88 -> ax = 88, bx = 60}
      end;


    Арифметические команды.

    ADD Сложить
    ADC Сложить, добавить перенос
    INC Увеличить на единицу

    SUB Вычесть
    SBB Вычесть с заёмом
    DEC Уменьшить на единицу

    MUL Умножить
    iMUL Умножить со знаком

    DIV Поделить
    iDIV Поделить со знаком

    Вот пример - программа выполняющая над двумя числами 4 арифметические операции
    ExpandedWrap disabled
      program asm_test_arifnetika;
      var
        a,b,c:integer;
      begin
        ReadLn(a,b);
        asm
          mov ax,a {ax := a}
          adc ax,b {ax := ax+b}
          mov c,ax {c := ax}
        end;
        WriteLn('Сумма a и b = ',c);
        asm
          mov ax,a {ax := a}
          sbb ax,b {ax := ax - b}
          mov c,ax {c := ax}
        end;
        WriteLn('Разность a и b = ',c);
        asm
          mov ax,a {ax := a}
         imul ax,b {ax := ax*b}
          mov c,ax {c := ax}
        end;
        WriteLn('Произведение a и b = ',c);
        asm
          mov ax,a {ax := a}
         idiv ax,b {ax := ax div b}
          mov c,ax {c := ax}
        end;
        WriteLn('Частное a и b = ',c)
      end;


    Вот. Теперь...
    Битовые команды:
    and
    or
    xor
    not
    shl
    shr

    ExpandedWrap disabled
      {and, и все остальные бинарные команды в ассемблере работают не совсем так, как в Паскале, а именно:}
      asm
        and ax,bx {будет означать ax := ax and bx}
      end;



    Условия.

    Синтаксис написания условий в ассемблере значительно отличается от Паскаля. Попробую объяснить что и как. Думаю, что легче всего на примере. Программа (вернее её фрагмент) гениален. Она выполняет
    ExpandedWrap disabled
        if a=0 then b := 7;

    Примерно так это бужет выглядеть на асме
    ExpandedWrap disabled
      asm
        cmp a,0  {?a=0?}
        jne @    {нет - перейти к концу}
        mov b,7  {b := 7}
      @:
      end;


    Вот. Сначала идет оператор cmp и два сравниваемых параметра через запятую. На следующей строчке идет параметр сравнения. В данном случае он расшифровывается как перейти, если не равны.
    Вот все параметры условий:

    Операция больше:
    JA - для беззнаковых чисел
    JG - для чисел со знаком

    Числа равны - JE

    Операция меньше:
    JB - для беззнаковых чисел
    JL - для чисел со знаком

    Операция больше или равно:
    JAE - для беззнаковых чисел
    JGE - для чисел со знаком

    Операция меньше или равно:
    JBE - для беззнаковых чисел
    JLE - для чисел со знаком

    Не равно - JNE

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

    Прерывания.

    Здесь уж совсем все просто. Ниже приводится пример выводящий курсор мыши на экран.
    ExpandedWrap disabled
      asm
        mov ax,01h {ax := 1}
        int 33h    {33h - прерывание мышки}
      end;
    Сообщение отредактировано: volvo877 -
      Цитата Азат @ 13.12.04, 15:35
      Здесь уж совсем все просто. Ниже приводится пример выводящий курсор мыши на экран.
      asm
      mov ax,01h {ax := 1}
      int 33h {33h - прерывание мышки}
      end;

      Я бы сделал вот так:
      ExpandedWrap disabled
        BEGIN
          Asm
            MOV   AX,11h {ставим графику}
            INT   10h
            MOV   AX,00h {инициализируем мышку}
            INT   33h
            MOV   AX,01h {показываем мышку}
            INT   33h
           @LOOP:        {балуемся - бесконечный цикл}
            JMP  @LOOP
          End
        END.
        Ассемблерные процедуры.

        Синтаксис.

        ExpandedWrap disabled
          procedure названиепроцедуры(параметры); assembler;
            asm
              ...
            end;

        например:
        ExpandedWrap disabled
          procedure ShowMouse; assembler;
            asm
              mov ax,01h
              int 33h
            end;


        Ассемблерные функции.

        Синтаксис:
        ExpandedWrap disabled
          function названиефункции(параметры):значение; assembler;
            asm
              ...
            end;


        Результат функции записывается в регистры. А именно:
        • длиной 1 байт (Byte, Char и т.п.) - в регистре AL;
        • длиной 2 байта (Integer, Word) - в регистре АХ;
        • длиной 4 байта (Pointer, LongInt) - в регистрах DX (старшее слово) и АХ (младшее слово);
        • типа Real - в регистрах DX, BX, АХ (старшее слово - в DX, младшее в АХ);
        • вещественных типов Single, Double, Extended, Comp - в регистре ST (0) сопроцессора;
        • строкового типа - во временной области памяти, на которую ссылается @Result.

        Пример:
        ExpandedWrap disabled
          function Shogen(a,b:integer):integer; assembler;
            asm
              mov ax,a
              adс ax,b
            end;


        Литература
        Фаронов В. В. Турбо паскаль: начальный курс
        Форум на исходниках
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0455 ]   [ 16 queries used ]   [ Generated: 26.04.24, 18:00 GMT ]