Справочник от Автор24
Поделись лекцией за скидку на Автор24

Основные инструкции языка ассемблера

  • 👀 242 просмотра
  • 📌 209 загрузок
Выбери формат для чтения
Загружаем конспект в формате docx
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Основные инструкции языка ассемблера» docx
Глава 2. Основные инструкции языка ассемблера Алгоритмы Линейные: все инструкции выполняются друг за другом Нелинейные: есть «точки ветвления» Пересылка данных Передача управления Арифметика (целочисленная) Логика и битовый сдвиг § 2.1. Пересылка данных 1. Простая пересылка данных 2. Работа со стеком 3. Ввод-вывод в порт 4. Работа с адресами 5. Преобразование данных Простая пересылка данных mov операнд_1, операнд_2 Пересылка данных. Содержит два операнда. Операнды должны быть одинаковыми по размерности (байт, слово или двойное слово). Один из операндов должен быть регистром общего назначения. В результате выполнения инструкции операнд_1 принимает значение операнда_2, операнд_2 при этом не меняется (аналог операции «присвоить»). mov eax, ebx ;eax = ebx, ebx не изменится операнд_2: - регистр общего назначения - сегментный регистр - переменная (область памяти) - число (область памяти) операнд_1:  - регистр общего назначения - сегментный регистр (кроме cs) - переменная Нельзя пересылать: - из одной области памяти в другую - из одного сегментного регистра в другой - из области памяти в сегментный регистр - в сегментный регистр cs int a, b = 5; //требуется: a = b _asm{ ;нельзя: mov a, b ;можно: mov eax, b mov a, eax } ;требуется: es = ds ;нельзя: mov es, ds ;можно: mov ax, ds mov es, ax ;а можно и так (см. работу со стеком): push ds ;поместить значение регистра ds в стек pop es ;записать значение из стека в регистр es xchg операнд_1, операнд_2 Обмен данными. Содержит два операнда. Операнды должны быть одинаковыми по размерности. Один из операндов должен быть регистром общего назначения. В результате выполнения инструкции значения операндов меняются местами. xchg eax, ebx ;a = eax, eax = ebx, ebx = a cmovxx операнд_1, операнд_2 Условная пересылка данных. Это целый набор инструкций, которые копируют содержимое операнда_2 в операнд_1, если удовлетворяется то или иное условие в зависимости от постфикса xx. Можно использовать в паре с инструкцией сравнения cmp (xx эквивалентно соответствующему xx в инструкциях условного перехода). операнд_2: - регистр общего назначения или переменная операнд_1: - регистр общего назначения cmp eax, ebx cmovl eax, ebx ;если eax < ebx, то eax = ebx bswap регистр32 Обращает порядок байт в 32-битном регистре: младший байт младшего слова меняется местами со старшим байтом старшего слова, старший байт младшего слова меняется местами с младшим байтом старшего слова. mov eax, 12300000h bswap eax ;eax == 00003012h Чтобы обратить порядок байт в 16-битном регистре, следует использовать команду xchg: xchg ah, al ;обратить порядок байт в ax Работа со стеком push операнд Положить в стек. Инструкция копирует содержимое операнда в память по адресу ss:esp и уменьшает esp на размер операнда в байтах. операнд: - регистр общего назначения - сегментный регистр - переменная - число push esp помещает в стек значение esp до того, как эта же инструкция его уменьшит. pop операнд Извлечь из стека. Берет данные из стека по адресу ss:esp и помещает в операнд. Затем увеличивает esp на размер операнда в байтах. операнд: - регистр общего назначения - сегментный регистр (кроме cs) - переменная ;пример временного хранения push eax ;сохраняет текущее значение eax ;здесь располагаются какие-нибудь инструкции, ;которые используют eax ... pop eax ;восстанавливает старое значение eax pusha / pushad Помещает в стек все 16- / 32-битные регистры общего назначения. popa / popad Считывает из стека все 16- / 32-битные регистры общего назначения. pushf / pushfd Помещает в стек 16- / 32-битный регистр флагов. popf / popfd Считывает из стека 16- / 32-битный регистр флагов. Ввод-вывод в порт in аккумулятор, порт Копирует в аккумулятор данные из порта ввода-вывода, номер которого указан в «порт». порт:  - число не более 255 или dx аккумулятор: - al, ax или eax out порт, аккумулятор Копирует данные из аккумулятора в порт ввода-вывода, номер которого указан в «порт». аккумулятор:  - al, ax или eax порт: - число не более 255 или dx Всего 65536 = 216 (размер регистра dx) адресов ввода-вывода Работа с адресами Способы задания адреса операнда (способы адресации): 1. Регистровая адресация. Операнды могут располагаться в любых регистрах общего назначения и сегментных регистрах. mov eax, ebx ;eax = ebx 2. Непосредственная адресация. Некоторые инструкции (например, все арифметические инструкции, кроме деления) позволяют указывать значение одного из операндов непосредственно в тексте программы. mov eax, 2 ;eax = 2 3. Прямая адресация. Если известен адрес операнда, располагающегося в памяти, можно использовать этот адрес. mov eax, es:0001 ;в es - начало сегмента (база), 0001 – смещение ;eax = значение (4 байта), расположенное ;по адресу es:0001 Далее по умолчанию используется сегментный регистр ds, но если смещение берут из регистров esp или ebp, то в качестве сегментного регистра по умолчанию используется ss. 4. Косвенная адресация. Адрес операнда в памяти можно не указывать непосредственно, а хранить в регистре общего назначения. mov eax, [ebx] ;eax = значение (4 байта), расположенное ;по адресу ds:ebx ;[] – операция РАЗАДРЕСАЦИИ mov eax, dword ptr [ebx] ;то же самое 5. Косвенная адресация со сдвигом. mov eax, [ebx+2] ;или [ebx]+2 или 2[ebx] ;помещает в eax значение (4 байта), ;находящееся в сегменте, указанном в ds, ;со смещением на 2 большим, ;чем число, находящееся в ebx lea операнд_1, операнд_2 Получение адреса. Содержит два операнда. В результате выполнения инструкции в операнд_1 помещается значение адреса (смещения) операнда_2, операнд_2 при этом не меняется. lea ebx, i ;ebx = адрес переменной i, ;значение переменной i не изменится lea eax, [ebx] ;eax = ebx Часто используется для быстрых вычислений. Эта инструкция «меньше», чем соответствующие mov и add, и не изменяет флаговый регистр. lea ebx, [ebx+ebx*4] ;ebx = ebx*5 lds / les / lfs / lss операнд_1, операнд_2 Отличается от lea тем, что в соответствующий названию сегментный регистр помещается база источника. Преобразование данных cdq Convert Double to Quadruple. Превращает двойное слово из eax в учетверенное слово, младшая половина которого остается в eax, а старшая располагается в edx (edx:eax). Биты регистра edx равны значению старшего бита регистра eax (сохраняет знак, то есть копирует значение старшего бита регистра eax во все биты регистра edx). cwd Convert Word to Double. Превращает слово из ax в двойное слово, младшая половина которого остается в ax, а старшая располагается в dx (dx:ax). Биты регистра dx равны значению старшего бита регистра ax (сохраняет знак, то есть копирует значение старшего бита регистра ax во все биты регистра dx). cbw Convert Byte to Word. Расширяет байт, находящийся в регистре al, до слова и помещает в ax. Расширение происходит путем распространения значения старшего бита al на все биты ah (то есть копирует значение старшего бита регистра al во все биты регистра ah). mov al, 0F5h ;al = 0F5h (= 245 = -11) cbw ;теперь ax = 0FFF5h (= 65525 = -11) cwde Расширяет слово, находящееся в регистре ax, до двойного слова и помещает в eax. Расширение происходит аналогично. movsx операнд_1, операнд_2 Пересылка с расширением знака. Копирует содержимое операнда_2 (регистр или переменная размером в байт или слово) в операнд_1 (16- или 32-битный регистр) и расширяет знак. movzx операнд_1, операнд_2 Пересылка с расширением нулями. К опирует содержимое операнда_2 (регистр или переменная размером в байт или слово) в операнд_1 (16- или 32-битный регистр) и расширяет нулями. § 2.2. Арифметика (целочисленная) Все инструкции из этого раздела, кроме деления и умножения, изменяют флаги of, sf, zf, af, pf, cf в соответствии с назначением каждого из этих флагов. Знак числа – интерпретация старшего бита. При этом только две инструкции учитывают старший разряд как знаковый (mul, div) остальные не учитывают. Без знака Со знаком Байт (8 бит) 0…255 -128…+127 Слово (16 бит) 0…65535 -32768…+32767 Двойное слово (32 бита) 0…4294967295 -2147483648…+2147483647 add операнд_1, операнд_2 Целочисленное сложение. Содержит два операнда. Операнды должны быть одинаковыми по размерности. Один из операндов должен быть регистром общего назначения. В результате выполнения инструкции операнд_1 принимает значение суммы операнда_1 и операнда_2, операнд_2 при этом не меняется. add eax, ebx ;eax = eax + ebx, ebx не изменится операнд_2: - регистр - переменная - число операнд_1: - регистр (чаще всего eax) - переменная int i = 10; int j = 20; //i = i + j _asm{ mov eax, i add eax, j mov i, eax ;i = i + j } Инструкция add не различает знак числа. Но использовать можно как для чисел со знаком, так и для беззнаковых. При этом надо анализировать значения флагов: • cf (перенос – при сложении чисел без знака), • of (переполнение – при сложении чисел со знаком). unsigned char i = 255, j = 1; _asm{ mov al, i ;al = 255 = 11111111b = FFh add al, j ; = 256 = 100000000b = 100h == 0 ;of == 0, cf == 1 ;произошел перенос при сложении чисел без знака jnc l1 ;если переноса не было (cf == 0), ;переходим на метку l1, ;иначе обрабатываем ошибку ... l1: mov i, al } printf("%i\n", i); char i = 127, j = 1; _asm{ mov al, i ;al = 127 = 01111111b = 7Fh add al, j ;al = 128 = 10000000b < 0 ;of == 1, cf == 0 ;произошло переполнение при сложении чисел со ;знаком jno l1 ;если переполнения не было (of == 0), ;переходим на метку, ;иначе обрабатываем ошибку ;... l1: mov i, al } printf("%i\n", i); adc операнд_1, операнд_2 Целочисленное сложение с переносом. Эта инструкция во всем аналогична add, кроме того, что она выполняет арифметическое сложение операнда_1, операнда_2 и флага cf. ;сложение двух 64-битных чисел ;edx:eax - первое число, ebx:ecx - второе число add eax, ecx adc edx, ebx ;Если при сложении младших двойных слов произошел ;перенос из старшего разряда (флаг cf = 1), ;то он будет учтен: edx = edx + ebx + cf xadd операнд_1, операнд_2 Обмен значениями и целочисленное сложение. Операнд_2 всегда регистр, операнд_1 – регистр или переменная. xadd eax, ebx ;ebx = eax, eax = eax + ebx sub операнд_1, операнд_2 Целочисленное вычитание. Содержит два операнда. Операнды должны быть одинаковыми по размерности. Один из операндов должен быть регистром общего назначения. В результате выполнения инструкции операнд_1 принимает значение разности операнда_1 и операнда_2, операнд_2 при этом не меняется. sub eax, ebx ;eax = eax - ebx, ebx не изменится операнд_2: - регистр - переменная - число операнд_1: - регистр (чаще всего eax) - переменная Инструкция sub не различает знак числа. Но использовать можно как для чисел со знаком, так и для беззнаковых. При этом надо анализировать значения флагов cf и of. sbb операнд_1, операнд_2 Целочисленное вычитание с займом. Эта инструкция во всем аналогична sub, кроме того, что она вычитает из операнда_1 значение операнда_2 и дополнительно вычитает значение флага cf. ;вычитание двух 64-битных чисел ;edx:eax - первое число, ebx:ecx - второе число sub eax, ecx sbb edx, ebx ;Если при вычитании младших двойных слов произошел ;займ из старшего разряда (флаг cf = 1), ;то он будет учтен: edx = edx - ebx - cf imul сомножитель_1 Целочисленное умножение со знаком. Содержит один операнд: сомножитель_1; cомножитель_2 и результат зависят от размерности сомножителя_1: ax = сомножитель_1  al dx:ax = сомножитель_1  ax edx:eax = сомножитель_1  eax сомножитель_1 (размерность) сомножитель_2 результат байт регистр al ah – старшая часть результата al – младшая часть результата два байта (слово) регистр ax dx – старшая часть результата ax – младшая часть результата четыре байта (двойное слово) регистр eax edx – старшая часть результата eax – младшая часть результата сомножитель_1: - регистр - переменная Результат может занимать в два раза больше места, чем размер сомножителя. Флаги of = 0, cf = 0, если результат умножения поместился целиком в младший регистр «результата». Иначе of = 1, cf = 1. Если результат уместился в младшем регистре, то в старшем – расширение знака (все биты равны знаку). mov ax, -1 ;ax = FFFFh mov bx, 1 ;bx = 0001h imul bx ;dx:ax = bx * ax ;dx:ax == FFFF:FFFFh imul результат, сомножитель_1 результат = сомножитель_1  результат сомножитель_1: - регистр - переменная - число результат: - регистр imul результат, сомножитель_2, сомножитель_1 результат = сомножитель_1  сомножитель_2 сомножитель_1: - число сомножитель_2: - регистр - переменная результат: - регистр int i; _asm{ mov eax, -10 ;eax = -10 (-10 == FFFFFFF6h) imul eax, 10 ;eax = 10 * eax mov i, eax } printf("%i\n", i); //-100 == FFFFFF9Ch Флаги of = 0, cf = 0, если результат умножения поместился целиком в «результат». Иначе произошло переполнение и потеря старших бит результата и of = 1, cf = 1. mul сомножитель_1 Целочисленное умножение без знака. Если результат уместился в младшем регистре, то в старшем – нули. idiv делитель Целочисленное деление со знаком. Содержит один операнд: делитель; делимое и результат зависят от размерности делителя: al = ax / делитель ah = ax % делитель ax = dx:ax / делитель dx = dx:ax % делитель eax = edx:eax / делитель edx = edx:eax % делитель делитель: - регистр - переменная Знак остатка всегда совпадает со знаком делимого. Значения флагов не определены. idiv ebx ;eax = (edx:eax)/ebx делимое делитель (размерность) частное остаток ah – старшая часть делимого al – младшая часть делимого байт al ah dx – старшая часть делимого ax – младшая часть делимого два байта (слово) ax dx edx – старшая часть делимого eax – младшая часть делимого четыре байта (двойное слово) eax edx Если делимое уместилось в младшую часть, то для корректного распознавания знака при делении необходимо использовать инструкцию расширения знакового бита младшей части делимого на все биты старшей части делимого (cbw, cwd, cdq). div делитель Целочисленное деление без знака. inc операнд Инкремент. Содержит один операнд (регистр или переменная). Увеличивает операнд на единицу. inc eax ;eax = eax + 1 Отличие inc ecx от add ecx,1 состоит в том, что флаг cf не затрагивается. dec операнд Декремент. Содержит один операнд (регистр или переменная). Уменьшает операнд на единицу. dec eax ;eax = eax - 1 Отличие dec ecx от sub ecx,1 состоит в том, что флаг cf не затрагивается. neg операнд Изменение знака. Один операнд. Выполняет «дополнение до двух». Эта инструкция эквивалентна обращению знака операнда, если рассматривать его как число со знаком: операнд = 0 – операнд Если операнд равен нулю, то cf = 0, иначе cf = 1. char i = -1; //нахождение модуля числа _asm{ mov al, i ;al == 11111111b == FFh == -1 ll: neg al ;al == 00000001b == 01h == 1 js ll ;если sf == 1 (число отрицательное), ;переход на метку l1 } printf("%i\n", i); cmp операнд_1, операнд_2 Сравнение. Содержит два операнда. Выполняет вычитание операнда_2 (регистр, переменная или число) из операнда_1 (регистр или переменная), но не сохраняет результат, а только изменяет состояние арифметических флагов zf, pf, sf. По состоянию этих флагов возможна реализация условных переходов. Операнды не могут быть переменными одновременно. Обычно инструкцию cmp используют вместе с инструкциями условного перехода (jxx), условной пересылки данных (cmovxx) или условной установки байт (setxx). cmp eax, edx je l1;если eax == edx, то eax – edx == 0 и zf == 1 ;в этом случае переход на какую-то метку l1 § 2.3. Логика и битовый сдвиг Логические инструкции and операнд_1, операнд_2 Побитовое логическое И. Содержит два операнда. Выполняет поразрядную (побитовую) операцию логического умножения над битами операндов. Результат записывается на место операнда_1 (регистр, переменная или число), операнд_2 (регистр или переменная) не меняется. Оба операнда не могут быть переменными одновременно. Часто применяют для выборочного обнуления отдельных бит. and al, 00001111b ;обнуление 4 старших бит ;регистра al or операнд_1, операнд_2 Побитовое логическое ИЛИ. Содержит два операнда. Выполняет поразрядную операцию логического сложения над битами операндов. Результат записывается на место операнда_1 (регистр, переменная или число), операнд_2 (регистр или переменная) не меняется. Оба операнда не могут быть переменными одновременно. Часто применяют для выборочной установки (в единицу) отдельных бит. or al,00001111b ;установка в единицу 4 младших ;бит регистра al xor операнд_1, операнд_2 Побитовое логическое исключающее ИЛИ. Содержит два операнда. Выполняет поразрядную операцию сложения по mod 2 над битами операндов. Результат записывается на место операнда_1 (регистр, переменная или число), операнд_2 (регистр или переменная) не меняется. Оба операнда не могут быть переменными одновременно. ;обнуление регистра ax xor ax, ax ;меняет местами содержимое ax и bx xor ax, bx xor bx, ax xor ax, bx ;быстрее, чем соответствующие очевидные инструкции mov ax, 0 xchg ax, bx not операнд Инверсия. Содержит один операнд. Выполняет поразрядное инвертирование битов операнда. Результат записывается в сам операнд. test операнд_1, операнд_2 Логическое сравнение. Содержит два операнда. Выполняет поразрядную операцию логического умножения над битами операндов. Операнды не меняются, но изменяется состояние флагов zf, sf и pf в соответствии с полученным результатом. Операнды не могут быть переменными одновременно. Обычно инструкцию test используют вместе с инструкциями условного перехода (jxx), условной пересылки данных (cmovxx) или условной установки байт (setxx). Не путать с cmp! После применения инструкции test флаг zf == 0 только в том случае, когда все биты операндов различны. Инструкции битового сдвига Инструкции сдвига имеют одинаковую структуру. Каждая инструкция сдвига принимает: - операнд, в котором выполняется сдвиг, - счетчик сдвигов (счетчик), который показывает, на сколько бит нужно выполнить сдвиг. Счетчик сдвигов варьируется в диапазоне от 0 до 31, поэтому в качестве счетчика использовать можно только регистр-счетчик, размером в 1 байт, т.е. регистр cl (можно в явном виде указать число в качестве счетчика сдвигов). Все инструкции логического и арифметического сдвига очередной выдвигаемый бит заносят в флаг cf. shl операнд, счетчик Логический сдвиг влево. Содержимое операнда сдвигается влево на количество бит, указанных в счетчике. При этом справа в позицию младшего бита на каждом шаге заносятся нули. shr операнд, счетчик Логический сдвиг вправо. Содержимое операнда сдвигается вправо на количество бит, указанных в счетчике. При этом слева в позицию старшего бита на каждом шаге заносятся нули. sal операнд, счетчик Арифметический сдвиг влево. Аналогична инструкции shl, но устанавливает флаг of (of = 1), если очередной выдвигаемый бит меняет знак операнда. sar операнд, счетчик Арифметический сдвиг вправо. Аналогична инструкции shr, но при этом инструкция сохраняет знак операнда, восстанавливая его после каждого очередного бита. Сдвиг на n бит влево – это умножение на 2n 0010b (2)  0100b (4) Сдвига на n бит вправо – это деление на 2n rol операнд, счетчик Циклический сдвиг влево. Содержимое операнда сдвигается влево на количество бит, указанных в счетчике. Выдвигаемые влево биты заносятся в этот же операнд справа. ror операнд, счетчик Циклический сдвиг вправо. Содержимое операнда сдвигается вправо на количество бит, указанных в счетчике. Выдвигаемые вправо биты заносятся в этот же операнд слева. rcl операнд, счетчик Циклический сдвиг влево через перенос. Содержимое операнда сдвигается влево на количество бит, указанных в счетчике. Выдвигаемые влево биты поочередно становятся значениями флага cf. Выдвигаемые из флага cf биты заносятся в операнд справа. rcr операнд, счетчик Циклический сдвиг вправо через перенос. Содержимое операнда сдвигается вправо на количество бит, указанных в счетчике. Выдвигаемые вправо биты поочередно становятся значениями флага cf. Выдвигаемые из флага cf биты заносятся в операнд слева. Другие поразрядные (битовые) инструкции bsf операнд_1, операнд_2 Сканирование битов вперед. Сканирует биты операнда_2 от младшего к старшему в поисках первого бита, установленного в 1. Если такой бит присутствует в операнде_2, то в операнд_1 заносится номер (позиция) этого бита в виде целочисленного значения. Если в операнде_2 все биты равны 0, то операнд_1 не меняется и устанавливается флаг нуля (zf=1). bsr операнд_1, операнд_2 Сканирование битов в обратном порядке. Сканирует биты операнда_2 от старшего к младшему в поисках первого бита, установленного в 1. Если такой бит присутствует в операнде_2, то в операнд_1 заносится номер (позиция) этого бита в виде целочисленного значения. Если в операнде_2 все биты равны 0, то операнд_1 не меняется и устанавливается флаг нуля (zf=1). bt операнд, смещение Проверка бита. Переносит значение бита операнда с номером, равным смещению, в флаг cf. bts операнд, смещение Проверка и установка бита. Работает аналогично bt и устанавливает указанный в операнде бит в 1. btr операнд, смещение Проверка и сброс бита. Работает аналогично bt и сбрасывает указанный в операнде бит в 0. btc операнд, смещение Проверка и инверсия бита. Работает аналогично bt и меняет значение указанного в операнде бита на противоположное. § 2.4. Передача управления jmp операнд Безусловный переход (без возможности возврата). Возможны 4 вида перехода: 1) short (короткий) ­­­- адрес перехода находится в пределах от –127 до +128 байт от инструкции jmp 2) near (ближний) - адрес перехода находится в том же сегменте памяти, что и инструкция jmp 3) far (дальний) - адрес перехода находится в другом сегменте. Задается парой «сегмент:смещение» 4) с переключением задачи  - передача управления другой задаче в многозадачной среде (защищенный режим). При short и near передача управления – это изменение регистра eip. Операнд: - регистр или переменная jmp операнд ≡ mov eip, операнд - число jmp операнд ≡ add eip, операнд - метка на уровне исполнимого кода вычисляется и записывается в eip смещение jxx операнд Условные переходы. Все условные переходы начинаются с j, затем идет код условия. В качестве операнда указывается адрес перехода (обычно – метка). Переход осуществляется, если выполнено соответствующее условие. Условие определяется по состоянию флагов. При вызове после инструкции cmp, условия приобретают формулировки, соответствующие отношениям между операндами cmp. Не поддерживают дальних переходов. (short, near) xx a – above – выше (беззнаковые целые) xx b – before – ниже (беззнаковые целые) xx g – greater – больше (знаковые целые) xx l – less – меньше (знаковые целые) xx n – not xx e – равно xx z – флаг zf = 1 xx o – флаг of = 1 xx c – флаг cf = 1 xx p – флаг pf = 1 xx s – флаг sf = 1 xx n – флаг = 0 jxx Условие перехода Для чисел со знаком: jg/jnle (больше) > jl/jnge (меньше) < jge/jnl (больше или равно) ≥ jle/jng (меньше или равно) ≤ Для чисел без знака: ja/jnbe (выше) > jb/jnae (ниже) < jae/jnb (выше или равно) ≥ jbe/jna (ниже или равно) ≤ Для всех чисел: je (равно) = jne (не равно) ≠ jc (перенос) cf = 1 js (знак) sf = 1 jz (ноль) zf = 1 jp (четное число единичных бит) pf = 1 jo (переполнение) of = 1 jnc (нет переноса) cf = 0 jns (нет знака) sf = 0 jnz (не ноль) zf = 0 jnp (нечетное число единичных бит) pf = 0 jno (нет переполнения) of = 0 Метка – символическое имя, ничего не выполняет, служит для использования в инструкциях перехода. cmp al, 0 ;если не равны, то zf = 0 jnz b1 ;если zf == 0, то переход на метку b1 ;можно jne ;задача: сделать far-переход при условии: ax == 0 cmp ax, 0 jne label_local ;обратное условие jmp label_far ;дальний jmp label_local: jcxz метка (short, near) Переход, если cx == 0 jecxz метка (short, near) Переход, если ecx == 0 loop метка (short) Цикл. Выполняет последовательно операции: 1) уменьшение регистра-счетчика ecx на 1 2) сравнение регистра-счетчика ecx с 0 3) если регистр-счетчик не равен 0, то происходит возврат на метку, иначе переход на следующую строку (выход из цикла). Аналог цикла for(ecx = …; ecx > 0; ecx--). Короче на один байт, чем cmp и jxx, и не изменяет значения флагов. mov ecx, 0Ah l1: loop l1 ;цикл выполнится 10 раз mov ecx, 0Ah l1: dec ecx jnz l1 ;цикл выполнится 10 раз mov eax, 0 ;eax = 0 mov ecx, 3 ;ecx = 3, это счетчик цикла, ;цикл выполнится 3 раза metka: add eax, 4 ;увеличиваем eax на 4 loop metka ;вычитаем 1 из ecx, ;пока ecx не обнулится возврат на metka ;в результате eax == 12 loope метка (пока zf == 1) (short) loopz метка (пока zf == 1) (short) loopne метка (пока zf == 0) (short) loopnz метка (пока zf == 0) (short) Цикл. Выполняет последовательно операции: 1) уменьшение регистра-счетчика ecx на 1 2) сравнение регистра-счетчика ecx с 0 3) если регистр-счетчик не равен 0 и если выполняется условие на флаг zf, то происходит возврат на метку, иначе переход на следующую строку (выход из цикла). Сами команды не изменяют значений флагов. l1: ;тело цикла cmp eax,13 ;если равны, то zf = 1; если не равны, то zf = 0 loopne l1 ;если (ecx != 0)&&(eax != 13), то переход на l1 Примеры int a[3][3] = {1,2,3,4,5,6,7,8,9}; int x = -1, rezult, key = 0; _asm{ mov ecx,9 xor eax,eax lea ebx,a l1: add eax,[ebx] jo l2 add ebx,4 loop l1 imul eax,x ;imul x изм. edx jo l2 mov rezult,eax jmp l3 l2: mov key,1 l3: } _asm{ mov ecx,9 xor eax,eax xor ebx,ebx l1: add eax,a[ebx] jo l2 add ebx,4 loop l1 imul eax,x jo l2 mov rezult,eax jmp l3 l2: mov key,1 l3: } if (!key) printf("%i\n", rezult); else printf("Overflow\n"); char a[3][3] = {1,1,1,1,1,1,1,1,1}; char x = -1,rezult,key = 0; _asm{ mov ecx,9 xor eax,eax xor ebx,ebx l1: add al,a[ebx] jo l2 add ebx,1 loop l1 imul x ;al,x - warning; ax,x – ответ неверный jo l2 mov rezult,al jmp l3 l2: mov key,1 l3: } char a[5][5]={5,1,1,1,1,1,5,1,1,1,1,1,5,1,1,1,1,1,5,1,1,1,1,1,5}; char rezult,key = 0; _asm{ mov ecx,5 xor eax,eax xor esi,esi l1: add al,a[esi] jo l2 add esi,6 loop l1 mov rezult,al jmp l3 l2: mov key,1 l3: } int a[5][5] = 5,1,1,1,1,1,5,1,1,1,1,1,5,1,1,1,1,1,5,1,1,1,1,1,5}; int rezult,key = 0; _asm{ mov ecx,5 xor eax,eax xor esi,esi l1: add eax,a[esi] jo l2 add esi,6*4 loop l1 mov rezult,eax jmp l3 l2: mov key,1 l3: } //=== Запись битов в обратном порядке === unsigned short int x = 3, y; char xx[16]; y = x; for (int i=0; i<16; i++){ xx[i] = y % 2; y = y / 2; } for (int i=15; i>=0; i--){ printf("%i", xx[i]); } printf("\n"); _asm{ mov ax, x mov bx, 0 mov ecx, 16 m1: shl ax, 1 rcr bx, 1 loop m1 mov x, bx } ТЕСТ № 1 § 2.5. Подпрограммы и прерывания call операнд Вызов подпрограммы. Сохраняет текущий адрес в стеке и передает управление по адресу, указанному в операнде (изменяет регистр eip). Используется для вызова подпрограмм. Операндом может быть: - регистр или переменная (абсолютное смещение) - метка (относительное смещение) ret [число] (из стека будет удалено указанное количество байт) retn число (ближний возврат) retf число (дальний возврат) Возврат из подпрограммы. Считывает из стека адрес и загружает его в eip (действия, обратные вызову подпрограммы инструкцией call). int i; char f[] = "%i"; _asm{ ;в ассемблерных вставках в С/С++ в стек надо поместить ;адреса аргументов функции, перечисляя их справа ;налево lea ebx, i ;поместили адрес i в ebx push ebx ;поместили ebx (адрес i) в стек, автоматически ;уменьшился указатель стека esp на 4 байта lea ecx, f ;поместили адрес f в ecx push ecx ;поместили ecx (адрес f) в стек, автоматически ;уменьшился указатель стека esp еще на 4 байта call scanf_s ;вызвали функцию scanf_s ;в ассемблерных вставках в С/С++ может быть надо ;осуществить «дальний вызов»: ;call dword ptr scanf_s ;или в настройках исправить: Runtime Library MTd add esp, 8 ;вернули указатель стека esp в исходное состояние ;(увеличили на 8), так как ;в ассемблерных вставках в С/С++ удаление ;параметров из стека выполняет вызывающая процедура … } //В C/C++ вызвали бы функцию scanf_s("%i",&i) int число Вызов прерывания (с указанным номером прерывания). Помещает в стек содержимое регистров eflags, cs, eip, далее действует аналогично команде call. mov ax,4C00h int 21h ;завершение выполнения программы Прерывание – инициируемый определенным образом процесс, временно переключающий процессор на выполнение другой программы с последующим возобновлением выполнения прерванной программы. В реальном и защищенном режимах обработка прерываний осуществляется принципиально разными методами. В реальном режиме адреса обработчиков прерываний начинаются с адреса 0000h:0000h (по 4 байта на адрес каждого обработчика). В защищенном режиме программа должна обращаться к операционной системе (т.к. адреса прерываний недоступны для прямого чтения). (подробнее о прерываниях см. в методичке № 2) § 2.6. Цепочечные (строковые) инструкции Под строкой символов здесь понимается последовательность байт, а цепочка — это более общее название для случаев, когда элементы последовательности имеют размер больше байта — слово или двойное слово. Таким образом, цепочечные (строковые) инструкции позволяют проводить действия над блоками памяти, представляющими собой последовательности элементов следующего размера: 8 бит — байт; 16 бит — слово; 32 бита — двойное слово. При использовании строковых инструкций считается: 1) строка-источник находится по адресу, записанному в esi 2) строка-приемник находится по адресу, записанному в edi 3) все строковые инструкции работают только с одним элементом строки (байтом, словом или двойным словом) за один раз. 4) для выполнения инструкции над всей строкой, необходим один из префиксов повторения: rep Повторять repe Повторять, пока равно (пока zf == 1) repne Повторять, пока не равно (пока zf == 0) repz Повторять, пока ноль (пока zf == 1) repnz Повторять, пока не ноль (пока zf == 0) Любой из префиксов выполняет следующую за ним инструкцию строковой обработки столько раз, сколько указано в регистре ecx, уменьшая его при каждом выполнении инструкции на 1. В ecx надо положить размер строки. После выполнения инструкции: если df == 0, то esi, edi увеличиваются на 1, 2 или 4 если df == 1, то esi, edi уменьшаются на 1, 2 или 4 movs приемник, источник Копирование строки movsb … строки байт из esi в edi movsw … строки слов movsd … строки двойных слов cmps приемник, источник Сравнение строк cmpsb … строк байт esi и edi cmpsw … строк слов cmpsd … строк двойных слов Устанавливают флаги аналогично команде cmp. scas приемник Сканирование строки scasb … строки байт scasw … строки слов scasd … строки двойных слов Сравнивают содержимое регистра al (ax или eax) с байтом (словом или двойным слово) из памяти по адресу edi. Устанавливают флаги аналогично команде cmp. lods источник Чтение из строки lodsb … из строки байт lodsw … из строки слов lodsd … из строки двойных слов Копируют байт (слово или двойное слово) из памяти по адресу esi в al (ax или eax). stos приемник Запись в строку stosb … в строку байт stosw … в строку слов stosd … в строку двойных слов Копирует регистр al (ax или eax) в память по адресу edi. ins приемник, ds Чтение строки из порта insb … строки байт из порта insw … строки слов из порта insd … строки двойных слов из порта В ds – номер порта ввода-вывода. Считывает байт (слово или двойное слово) из порта в память по адресу edi outs ds, источник Запись строки в порт outsb … строки байт в порт outsw … строки слов в порт outsd … строки двойных слов в порт В ds – номер порта ввода-вывода. Записывает байт (слово или двойное слово) из памяти по адресу esi в порт. //даны две строки s1 и s2 //скопировать содержимое s1 в s2 и вывести s2 на экран #include void main(){ char s1[] = "Hi, people!!!\n"; int i = strlen(s1) + 1; char s2[] = "123456789123456789\n"; _asm{ cld ;флаг направления df = 0 (строки ;обрабатываются в сторону увеличения адресов) mov ecx, i ;ecx = i lea esi, s1 ;поместить адрес строки s1 в esi (в источник) lea edi, s2 ;поместить адрес строки s2 в edi (в приемник) rep movsb ;rep повторяет команду movsb столько раз, ;сколько указано в ecx ;movsb – копирование байта из esi в edi } printf("%s", s2); } #include //вычислить длину строки void main(){ char s[256]; char f[] = "%s"; char fd[] = "%i\n"; ;в ассемблерных вставках в C/C++ не требуется явно ;определять сегменты данных, стека и кода _asm{ ;надо запросить строку для анализа ;в C/C++ мы бы вызвали scanf("%s",s); lea ebx, s push ebx lea ecx, f push ecx call scanf add esp, 8 mov ecx, -1 ;это счетчик символов в строке s dec ebx ;теперь в ebx адрес s[-1] b1: ;метка inc ecx ;увеличили ecx на 1 inc ebx ;увеличили ebx на 1 mov al, [ebx] ;al = s[ecx] cmp al, 0 ;сравнили al с кодом символа '\0' jne b1 ;если не равны ;ecx = "длина строки" } Функция scanf_s для ввода строки имеет 3 параметра: scanf_s("%s",s,256); ;Вычисление длины строки ;с использованием цепочечных операций mov ecx, 0FFFFFFFFh lea edi, s ;в edi адрес строки-приемника mov al, 0 ;в al код символа '\0' cld ;флаг df = 0 repne scasb ;цикл: пока s[i] != '\0' ;теперь ecx = (FFFFFFFF - ("длина строки" + 1)) ;"длина строки" = FFFFFFFF - ecx - 1 = FFFFFFFE - ecx mov ebx, 0FFFFFFFEh sub ebx, ecx ;ebx = "длина строки" Управление флагами stc cf = 1 (установить флаг переноса) clc cf = 0 (сбросить флаг переноса) cme cf = cf XOR 1 (инвертировать флаг переноса) std df = 1 (установить флаг направления) сld df = 0 (сбросить флаг направления) lahf ah = flags sahf flags = ah pushf поместить flags в стек pushfd поместить eflags в стек popf загрузить из стека flags popfd загрузить из стека eflags cli ip = 0 (запретить прерывания) sti ip = 1 (разрешить прерывания) salc если cf == 1, то al = FF; если cf == 0, то al = 0
«Основные инструкции языка ассемблера» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Решение задач от ИИ за 2 минуты
Решить задачу
Помощь с рефератом от нейросети
Написать ИИ

Тебе могут подойти лекции

Смотреть все 588 лекций
Все самое важное и интересное в Telegram

Все сервисы Справочника в твоем телефоне! Просто напиши Боту, что ты ищешь и он быстро найдет нужную статью, лекцию или пособие для тебя!

Перейти в Telegram Bot