Возможны "хитрые" ошибки.

Предыдущая тема Следующая тема Перейти вниз

Возможны "хитрые" ошибки.

Сообщение  Vadim Weinberg в Пт Ноя 05, 2010 6:50 am

Код:

Dim UShort_Max As UShort=65535 'БОЛЬШЕ НЕ БЫВАЕТ.

? "Цикл № - " & Str(UShort_Max-1)
For i As UShort=0 To UShort_Max-1
   ' I ПУСТОЙ ЦИКЛ.   
Next
? "выполнено..."
?
? "Цикл № - " & Str(UShort_Max)
For i As UShort=0 To UShort_Max
   ' II ПУСТОЙ ЦИКЛ.   
Next
? "НЕ ДОЖДЁТЕСЬ :("
Вроде как, во втором цикле прибавляет к 65535 1 и зависает.
А на самом деле вот как:
Код:

Dim UShort_Max As UShort=65535 'БОЛЬШЕ НЕ БЫВАЕТ.
UShort_Max+=1      'ДУМАЕТЕ ОШИБКА...
? UShort_Max       'НЕТ - 0.

UShort_Max=65535+2 'ОПЯТЬ НЕТ ОШИБКИ.
? UShort_Max       'БУДЕТ - 1.

UShort_Max=65535   'БОЛЬШЕ НЕ БЫВАЕТ.
? UShort_Max+2    'ОРИГИНАЛЬНО, НО БУДЕТ  - 65537. :)
'ПОНЯТНО, ЧТО ЗДЕСЬ ПРЕОБРАЗОВАНИЕ В Integer, ОПЕРАТОР Print ПОСТАРАЛСЯ.
Sleep
Теперь понятно поведение во II цикле.
- особенность реакции на переполнение (переход на 0)
- особенность проверки цикла (делает шаг +1, затем сравнивает с количеством интераций)

Vadim Weinberg

Сообщения : 18
Дата регистрации : 2010-07-08
Возраст : 52
Откуда : СПб

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  VerhoLom в Чт Ноя 11, 2010 6:35 pm

А как выглядит ассемблерный вывод (опция -r)? Cool Suspect Выложите... Question (вариант с "вечным" циклом)

Извиняюсь, я пока без компа... Sad
avatar
VerhoLom

Сообщения : 67
Дата регистрации : 2010-07-06
Возраст : 35

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  Vadim Weinberg в Пт Ноя 12, 2010 10:51 am

Сокращаю

Код:

For i As UShort=0 To 65535
'ПУСТОЙ ЦИКЛ.
Next

Запускаю

fbc -r -s console

Получаю


.intel_syntax noprefix

#Perpetuum Mobile.bas' compilation started at 10:23:40 (FreeBASIC v0.21.0b)

.section .text
.balign 16
_fb_ctor__PerpetuumzMobile:
push ebp
mov ebp, esp
sub esp, 4
.Lt_0002:
mov word ptr [ebp-4], 0
.Lt_0007:
.Lt_0005:
inc word ptr [ebp-4]
.Lt_0004:
cmp word ptr [ebp-4], 65535
jbe .Lt_0007
.Lt_0006:
.Lt_0003:
mov esp, ebp
pop ebp
ret
#Perpetuum Mobile.bas' compilation took 0.0001773968498142153 secs

.section .ctors
.int _fb_ctor__PerpetuumzMobile

В этом я слабо разбираюсь.

Цикл крутится между .Lt_0007: и jbe .Lt_0007.

mov word ptr [ebp-4], 0 это "i As UShort=0"

Единицу прибавляет inc word ptr [ebp-4].

cmp word ptr [ebp-4], 65535 - савнивает,
а jbe .Lt_0007 переход...

Но слабо ориентируюсь. Вообще - меток многовато, на 6 меток 1 ссылка.


Последний раз редактировалось: Vadim Weinberg (Пт Ноя 12, 2010 1:44 pm), всего редактировалось 2 раз(а)

Vadim Weinberg

Сообщения : 18
Дата регистрации : 2010-07-08
Возраст : 52
Откуда : СПб

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  trew в Пт Ноя 12, 2010 1:34 pm

Неужели такой ассемблерный листинг выдал компилятор? Shocked Меток действительно многовато, в данном примере надо то всего одну .Lt_0007 !
Код:
#Perpetuum Mobile.bas' compilation started at 10:23:40 (FreeBASIC v0.21.0b)

.section .text
.balign 16
_fb_ctor__PerpetuumzMobile:

push ebp
mov ebp, esp  ' стандартный пролог

sub esp, 4  ' уменьшаем адрес стека для работы с  переменными
mov word ptr [ebp-4], 0  ' записываем по адресу ebp-4 (i As UShort)  значение 0
.Lt_0007:
inc word ptr [ebp-4]  Прибавляем значение на единицу по адресу ebp-4
cmp word ptr [ebp-4], 65535  '  Если значение по адресу ebp-4 меньше или равно 65535
jbe .Lt_0007                '    поползли на метку .Lt_0007

[b]mov esp, ebp 'стандартный эпилог
pop ebp[/b]

ret
#Perpetuum Mobile.bas' compilation took 0.0001773968498142153 secs

.section .ctors
.int _fb_ctor__PerpetuumzMobile

trew

Сообщения : 331
Дата регистрации : 2010-10-14

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  VerhoLom в Чт Ноя 18, 2010 1:38 pm

trew пишет:Неужели такой ассемблерный листинг выдал компилятор? Shocked Меток действительно многовато, в данном примере надо то всего одну

Какая разница, сколько меток? они все-равно живут на этапе компиляции.
avatar
VerhoLom

Сообщения : 67
Дата регистрации : 2010-07-06
Возраст : 35

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  VerhoLom в Чт Ноя 18, 2010 2:12 pm

А теперь смотрите цикл:

mov word ptr [ebp-4], 0 'Тут 0 для начала
.Lt_0007:
.Lt_0005:
inc word ptr [ebp-4] 'Увеличиваем на 1
.Lt_0004:
cmp word ptr [ebp-4], 65535 'Смотрим, а вдруг дошли до 65535 Rolling Eyes
jbe .Lt_0007 'Теперь внимание: если число меньше Twisted Evil или равно Twisted Evil 65535, то крутим цикл дальше pig

Тут выходит, что если мы дошли до 65535, то условие (меньшеили равно) все равно поведет нас на очередной виток, так как число РАВНО 65535, а в программе явно задано условие, что даже при этом значении все равно крутить цикл. Надо было вместо jbe ставить jb (тогда это было бы условие меньше) и число сравнения увеличить на 1. Это уже глюк! Тут и имеем вечный цикл: остальные разряды числа пошли в старшие 2 байта, а младшие вплоть до 4Гб и более будут равны 65535 (&hFFFF).

Я бы написал где-то так:

mov word ptr [ebp-4], 0 'Тут 0 для начала
.Lt_0007:
.Lt_0005:
inc word ptr [ebp-4] 'Увеличиваем на 1
.Lt_0004:
'Или так: jnc .Lt_0007, т .е. если не было переноса в старшие разряды
cmp word ptr [ebp-4], 65536 'Смотрим, а вдруг дошли до 65536
jb .Lt_0007 'если число меньше 65536, то крутим цикл дальше

Тогда бы был полный проход (65536 раз: от 0 до 65535)...

Надо бы авторам компилятора эту тему почитать.
avatar
VerhoLom

Сообщения : 67
Дата регистрации : 2010-07-06
Возраст : 35

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  Саня в Чт Ноя 18, 2010 2:56 pm

если быть ваапще точным, то тоже будет вечный цикл
во-первых по ассемблеру видно что сравниваются, числа типа word а это 16 бит и максимум какое значение может принимать это 65535, что в двоичной системе - 1111111111111111 , так шо когда происходит инкремент, то получается 0( единичка уходит в старший разряд ), и в дальнейшем сравнении это даст новую итерацию, хотя это те и так понятно... в общем, word надо заменить на dword ushort на uinteger или подобное:

Код:

mov dword ptr [ebp-4], 0 'Тут 0 для начала
.Lt_0007:
.Lt_0005:
inc dword ptr [ebp-4] 'Увеличиваем на 1
.Lt_0004:
'Или так: jnc .Lt_0007, т .е. если не было переноса в старшие разряды
cmp dword ptr [ebp-4], 65536 'Смотрим, а вдруг дошли до 65536
jb .Lt_0007 'если число меньше 65536, то крутим цикл дальше
в примере явно указан тип ushort, компилятор в данном случае правильно сделал, я почти уверен, что примерно такая же прога на си будет давать пообной результат ..

метки, в принципе, пофиг сколько их, но чрезмерное их количество затрудняет чтение, хоть для маленьких прог можно и так, но для больших ставим ключ -gen gcc и получаем на листинг на си..
avatar
Саня

Сообщения : 65
Дата регистрации : 2010-04-28
Возраст : 23
Откуда : Екатеринбург

Посмотреть профиль http://vkontakte.ru/id30561430#/id57547166

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  VerhoLom в Чт Ноя 18, 2010 4:15 pm

Кстати, вместо jbe (jb) можно и jne поставить: все равно когда-то дойдем до момента, когда word ptr [ebp-4] будет равно 65535. afro cat Suspect

Да, а 4байтовые переменные лучше использовать - все-равно стек будет выровнен на 4 байта... pig Жизть такая, 32 разрядная...
avatar
VerhoLom

Сообщения : 67
Дата регистрации : 2010-07-06
Возраст : 35

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: Возможны "хитрые" ошибки.

Сообщение  Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Предыдущая тема Следующая тема Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения