Введение в Ассемблер. Команды передачи управления. Условный и безусловный переход. Организация циклов

Команды передачи управления

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

  • команда вызова процедуры (CALL);
  • команда возврата из процедуры (RET);
  • команда вызова прерывания (INT);
  • команда возврата из прерывания (IRET).

Мы будем ориентироваться в написании программ на Windows. Каждая задача в операционной системе Windows работает в своем виртуальном адресном пространстве, представляющем по сути один большой сегмент, размер которого определяется 32-битным числом (для 32-битной Windows). Поэтому все переходы в программах для Windows осуществляются в рамках этого сегмента и предполагают простое изменение содержимого регистра EIP (указателя команд). Отметим, что в некоторых случаях (в других ОС) приходится осуществлять межсегментную передачу управления.

Заголовок

// иллюстрация использования меток Си и ассемблера одновременно
#include <windows.h>
#include <stdio.h>
#include <conio.h>
DWORD a,b,c;
 
void main()
{
    a = 400;
    b = 600;
    c = 700;
 
    __asm{
	MOV EAX, a;
	MOV EBX, b;
	JMP L2;     
L1:
	MOV EDX, EAX;
L2:
	ADD EBX, EAX;
	MOV c, EBX;
	JMP L3;
	MOV c, EAX;
};
L3:
	printf("%d\n", c);
	c+=100;
L4: if(c>2000)
	    _getch();
	else goto L3;
// обращаться из Си к ассемблерным меткам нельзя. Следующий код не работает:
//	goto L1;
};

Пример. Нахождение максимального из трех чисел

// нахождение максимального из 3 целых чисел
#include <windows.h>
#include <stdio.h>
#include <conio.h>
DWORD a,b,c,d;
 
void main()
{
    a = 400;
    b = 600;
    c = 700;
 
    __asm{
	MOV EAX, a;
	CMP EAX, b; // сравниваем содержимое регистра EAX и переменную b
	JA L1;      // ***если a>b, то максимальное из чисел a и b - это a, оно хранится в буфере EAX
		    // если EAX>b то переходим по метке L1 (JA - для беззнаковых целых,
		    // JG - для чисел со знаком. Можно использовать JZ - (если нуль) или
		    // JE (если равно). При помощи этих команд результат выполнения последней арифметической 
		    // команды сравнивается с нулем)
	MOV EAX, b; // *** иначе максимальное из чисел a и b - это b, помещаем его в буфер EAX
L1:      
        CMP EAX, c; // сравниваем содержимое регистра EAX (максимальное из чисел a и b) и переменную c
        JNA L2; // если EAX меньше с, то перейти по метке L2
	JMP L3; // безусловный переход по метке L3, если больше или равно
		// JMP l1 - переход по адресу, который содержится в переменной l1
		// JMP EAX - переход по адресу, который содержится в регистре EAX
		// JMP [EAX] - переход по адресу, который находится в переменной,
		// адрес которой находится в регистре EAX
L2:
	MOV EAX, c; // максимальное из 3 чисел - с
L3:
        MOV d, EAX; // выводим максимальное из 3 чисел
	};
	printf("%d", d);
	_getch();
};

 

Назад: Введение в Ассемблер. Команды передачи управления. Условный и безусловный переход. Организация циклов