@samsungovetch

Assembler — Входит ли число в интервал?

Здравствуйте
Делаем в университете ассемблеровские вставки кода в Паскаль (Делфи).
Проблема в данной задаче - найти, входит ли число в интервал чисел.

label less;
label greater;
label ennnd;

var k: real;
    n: byte;
    result: byte;
    min: byte;
    max: byte;
    i: Byte;
    digit: byte;

Function Interval(digit, min, max: byte):byte;
  label ennnd;
  label greater;
  label less;
  var res: byte;
  begin
    res:=0;
    asm
        mov al,digit;  //приравниваю al=digit
        cmp al,min;    //сравниваю с минимальной границей
        ja greater;    //если больше, то переходим
        jna ennnd;     //если нет, то на выход


      greater:
        cmp al,max;    //сравниваю с максимальной границей
        jb less;       //если меньше, то переходим
        jnb ennnd;     //если нет, то на выход

      less:
        mov res,1;     //если меньше, то попадает в интервал, то рес = 1

      ennnd:


    end;
  end;

begin
  writeln('Number of digit?: ');
  readln(n);

  writeln('Min digit?: ');
  readln(min);
  writeln('Max digit: ');
  readln(max);

  for i:= 0 to n-1 do
  begin
    writeln('Digit? ');
    readln(digit);
    if (Interval(digit,min,max) > 0) then
      writeln('In Interval')
    else
      writeln('Not In Interval');
  end;

  readln(k);

end.


Сделал так, но при проверке любое число оказывается в интервале, вместо перехода на метку ennnd, всё равно выполняется метка greater и less соответственно. В чём я ошибся?
  • Вопрос задан
  • 493 просмотра
Решения вопроса 1
@zedxxx
В Delphi (для Win32) по умолчанию используется соглашение вызовов register: до 3-х параметров передаётся через регистры EAX, ECX, EDX, результат передаётся через EAX (подробнее, смотри тут: Using Assembler in Delphi).

Соответственно, получаем вот такой код:
function IntervalAsm(const AValue, AMin, AMax: Byte): Boolean; register;
asm
  // Входные параметры уже лежат в регистрах:
  // al = AValue
  // dl = AMin
  // cl = AMax

  cmp dl, al     // сравнение с AMin
  ja @@RetFalse  // если al < dl, то выход с False
  cmp cl, al     // сравнение с AMax
  jae @@RetTrue  // если al <= cl, то выход с True

@@RetFalse:
  xor eax, eax   // eax = 0 -> Result = False
  ret

@@RetTrue:
  mov al, 1      // eax = 1 -> Result = True
  ret
end;

Если возникают трудности с написанием кода на ассемблере, то лучше всего написать код на Delphi (или даже на самом простом Си), скомпилировать его, а затем декомпилировать и посмотреть, а какой же код генерирует сама Delphi. Для учебных проектов на Delphi прекрасно подойдёт Interactive Delphi Reconstructor (IDR).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@samsungovetch Автор вопроса
Разобрался. Вот получивший код:
uses
  SysUtils;

label less;
label greater;
label ennnd;

var k: real;
    n: byte;
    min: byte;
    max: byte;
    i: byte;
    digit: byte;

Function Interval(digit, min, max: byte):byte;
  label ennnd;
  label greater;
  label less;
  var res: byte;
  begin
    asm
        mov res,0;
        mov al,digit;  //приравниваю al=digit
        cmp al,min;    //сравниваю с минимальной границей
        ja greater;    //если больше, то переходим
        jna ennnd;     //если нет, то на выход


      greater:
        cmp al,max;    //сравниваю с максимальной границей
        ja ennnd;     //если нет, то на выход
        mov res,1;     //если меньше, то попадает в интервал, то рес = 1


      ennnd:


    end;
    Interval:=res;
  end;

begin
  writeln('Number of digit?: ');
  readln(n);

  writeln('Min digit?: ');
  readln(min);
  writeln('Max digit: ');
  readln(max);

  for i:= 0 to n-1 do
  begin
    writeln('Digit? ');
    readln(digit);
    writeln(Interval(digit,min,max));
    if (Interval(digit,min,max) > 0) then
      writeln('In Interval')
    else
      writeln('Not In Interval');
  end;

  readln(k);

end.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы