Сообщение было отмечено theone как решение
Решение
theone
| Assembler | ||
|
При изменении делителя на 2 подключается знаковое деление(idiv).
При использовании longint подключается процедура:
| Assembler | ||
|
Ваше прерывание выглядит так:
| Assembler | ||
|
Но оно вызывает функцию @$brdiv$q7Longintt1, где используются 32-х битные регистры, ладно младшие 16-ть бит востанавливаются(куча push и pop вначале и в конце), но старшая часть регистра перезаписывается 18,2 раза в секунду(в прерывании), плюс ещё программа вносит свои изменения в цикле.
До тех пор, пока Вы не раскажите о хитрых ходах: a mod 1 = 0 и newtick div 1 смысла разговаривать нет.
Добавлено через 15 минут
Ваша программа выполненяет newtick div 1 в цикле и прерывается прерыванием и выполняя a mod 1 = 0 заходит в общую функцию, при этом портит сами регистры(старшую часть) именно это приводит к ошибке.
Я бы посоветовал использовать критические секции, но в этом паскале/ассемблере, кроме как запрета прерываний ничего нет.
2
Неописанная переменная
begin S := 1; // Неизвестное имя S end.
Все используемые переменные должны быть предварительно описаны с помощью ключевого слова var (внутри блока begin/end или, что обычно хуже, в разделе описаний вначале программы).
Отсутствующая ;
begin var S: integer S := 1; // Компилятор здесь скажет: Ожидалась ; — имеется ввиду предыдущая строка! end.
begin var S := 1 S := S + 1 // Аналогично: проблема на предыдущей строке, а на текущей нет, потому что после неё идёт end. end.
Очень частая ошибка у начинающих. Курсор, как правило, позиционируется в начале следующей строки.
Несовместимость типов при присваивании
begin var S: integer := 1.3; // Нельзя преобразовать тип real к integer end.
Безболезненно можно присваивать только данные одного типа. Если данные — разных типов, то в редких случаях можно преобразовать данные одного типа в данные другого. Например, целое можно преобразовать в вещественное, а символ — в строку. Обратные преобразования не допускаются.
Чтобы не ошибаться в подобных простых случаях в Паскале есть следующая краткая форма объявления и инициализации переменной:
begin var S := 1.3; // Тип real будет выведен компилятором автоматически end.
Отсутствие закрывающего апострофа литеральной строки
begin var x := 2; // x получает тип integer var y := 3; // y получает тип integer writeln('Результат сложения равен =, x + y); // Не хватает закрывающего апострофа end.
Закрыть апостроф надо на той же строке, где расположен открывающий апостроф
Ошибки расстановки запятых и апострофов при выводе строк и выражений
begin var x := 2; // x получает тип integer var y := 3; // y получает тип integer writeln(x, '+,' y, '=', x+y); // Неверная расстановка запятых и апострофов end.
Слишком много запятых и апострофов рядом, потому начинающие часто путаются 🙂
Надо уяснить правила:
- запятые разделяют разные элементы вывода
- все, что находится в апострофах, будет выведено на экран без изменений
Ошибка ввода
begin var x: integer; read(x); // введите блаблабла и посмотрите, что получится end.
Это — ошибка во время выполнения. Программа пытается преобразовать введенную строку в число, не может это сделать и завершается с ошибкой.
Аналогичный фрагмент в более современном и предпочтительном синтаксисе:
begin var x := ReadInteger; end.
Ошибка неинициализированной переменной
begin var x: integer; // Забыли инициализировать или ввести x var r := x * x; // r получает тип integer writeln('Квадрат числа ', x, ' = ', r); end.
Перед использованием любую переменную надо ввести или присвоить ей начальное значение. Это действие называется инициализацией переменной.
Деление на 0
begin var x := 0; var c := 666 div x; // Здесь происходит деление на 0 end.
Если во время выполнения программа выполнит деление на 0, то она завершится с ошибкой.
Корень из отрицательного числа
begin writeln(sqrt(-1)); // Корень из отрицательного числа end.
В обычном Паскале возникает ошибка времени выполнения.
В PascalABC.NET выводится NaN — Not a Number
Ссылки
- Программы для начинающих
- Сайт PascalABC.NET: Программы и алгоритмы для начинающих
uses crt;
var i,k:word;
BEGIN
clrscr;asm
mov cx, i { ; это будет i}
mov si, k {; это будет k}
mov bx, 11 {; число для вычисления модуля}@l0:
cmp cx, 199 {; если i больше или равно 199 выходим из цикла}
jge @ext1mov ax, si
shr ax, 1 {; деление k на 2}
add ax, cx {; добавляем i}
xor dx, dx {; очищаем dx для деления}
div bx {; делим на 11}cmp dx, 5{ ; сравниваем остаток}
jnz @label2{ ; если не равен 5 - то на label2}sub cx, si{ ; иначе i = i - k}
jmp @l0 ; {в начало цикла}@label2:
mov ax, si {; подготавливаем деление}
xor dx, dx
mul ax {; умножаем на себя (k*k)}
mov dx, cx
shr dx, 1 {; делим i на 2 }
add ax, dx {; добавляем к резульату k*k}
mov si, ax {; заносим результат в k }
jmp @l0 {; в начало цикла}@ext1:
{... ; обработка результата}
end;
writeln('REZULTAT-ASSAMBLER');
writeln('k=',k,' i=',i);
readkey;
end.
сам цикл таков
i:=57; k:=19;
while i<199 do
if ((i + k div 2) mod 11) = 5 then i:=i-k else k:=k*k+(i div 2)
Сообщение отредактировано: volvo — 18.01.2007 15:18
← →
Genious
(2002-02-16 17:47)
[0]
Народ кто-нибудь знает как сделать простой обработчик ошибок на Pascal»е. Смысл в том, что если происходит недопустимая арифметическая операция(например: деление на ноль или логарифм из отрицательного числа) мне надо ее обработать.
![]()
![]()
← →
Desdechado
(2002-02-16 18:17)
[1]
![]()
![]()
← →
panov (M)
(2002-02-16 18:43)
[2]
обрабатывай в блоке try..except…end
![]()
![]()
← →
APL
(2002-02-17 12:25)
[3]
а можно и так
function Mydiv(x,y:real):real;
begin
if y=0 then
result:=0
else
result:= x/y;
end;
![]()
![]()
← →
AlexKniga
(2002-02-17 15:20)
[4]
Как я понял, нужно сделать обработчик исключений на Turbo Pascal»е.
Program RTE;
Procedure Main;
Var Value: Double;
Begin
Repeat
WriteLn;
ReadLn (Value);
WriteLn (1/Value); //при вводе нуля получим RTE 200
Until Value=9999;
End;
Var ExitStandart: Pointer;
Procedure MyExit; far; // мой обработчик исключений
Begin
ExitProc:=ExitStandart;
If
ErrorAddr<>nil Then
Case
ExitCode of
200:
Begin
ErrorAddr:=nil;
WriteLn ("Division by zero!");
ExitProc:=@MyExit;
Main
End
Else
End;
ReadLn;
End;
Begin
ExitStandart:=
ExitProc;
ExitProc:=@MyExit;
Main
End.
Почитай хелп по выделенному.
Аналогично обрабатываются все run time error»ы.
Можно реализовать
самому все возмозности try..except…end.
Т.е. каскадную обработку исключений, возбуждение собственных и пр.
![]()
![]()
Добрый день!
Недавно начал учиться программированию, ещё более недавно — Паскалю в Лазарусе.
Делаю незамысловатую игру, пока что без сторонних библиотек, средствами ИДЕ. ОС — Линукс Xubutnu.
Возникает периодически ошибка такого плана:
Проект вызвал класс исключения ‘External: Unknown exception code 8’.
В файле ‘laztracer.pas’ на строке 50
LazTracer, в свою очередь, указывает на такую строку:
procedure RaiseGDBException(const Msg: string);
begin
DebugLn(lrsERRORInCode, Msg);
// creates an exception, that gdb catches:
DebugLn(lrsCreatingGdbCatchableError);
DumpStack;
{$ifndef HASAMIGA} // On Amiga Division by 0 is not catchable, just crash
if (length(Msg) div (length(Msg) div 10000))=0 then ;
{$endif}
end;
Происходит это временами, всё чаще. Последний раз после того, как в модуле попытался присвоить переменной случайное значение:
function filler(var name: string): Oblast;
var
Obl: Oblast;
RandBG: integer;
begin
Randomize;
RandBG:= Random(3);
После этого я изменил код, удалив всё, что написал с момента, когда программа работала исправно:
function filler(var name: string): Oblast;
var
Obl: Oblast;
begin
Не помогло. Тогда запустил программу без ИДЕ. Она тоже сообщила о делении на ноль, но, после того, как я проигнорировал это сообщение, запустилась. И через ИДЕ после этого снова всё собралось… А потом (ничего не менял, просто попробовал ещё раз запустить в ИДЕ) — опять не работало…
Короче, я не вижу связи между этим сообщением и своими действиями. То работает, то нет.
Иногда появляется сообщение и после каких-то других действий. Откатываюсь назад, пишу снова вроде то же самое — работает.
Короче, работать невозможно. Подскажите, в чём может быть беда. Или хотя бы направление, в котором надо копать.
Спасибо.