PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » PureBasic для Windows » Что за ошибка?


Что за ошибка?

Сообщений 1 страница 24 из 24

1

Без процедуры работает а в ней косяк?

Код:
Procedure x()
Protected r=0
cikl:
If r<21
Select r
  Case 0 To 20
    r+1
    Debug r
    Goto cikl
EndSelect  
EndIf
EndProcedure
x()
Код:
Procedure x()
Protected r=0
cikl:
Select r
  Case 0 To 33 
   Select r
   Case 0 To 20 
    r+1
    Debug r
    Goto cikl
   EndSelect
EndSelect
EndProcedure
x()

Отредактировано Sergeihik (26.08.2021 00:37:56)

0

2

почитай про protected. индусский код налицо

Код:
Procedure x(r)
  ;r=0;Protected r=0
  cikl:
  Select r
    Case 0 To 33 
      Select r
        Case 0 To 20 
          Debug r
          x(r+1)
          ;Goto cikl
      EndSelect
  EndSelect
EndProcedure
x(0)

0

3

egons написал(а):

почитай про protected. индусский код налицо

Причём тут protected,
Есле парсер,или транслятор компилятора не правильно где то работают?
Да и мне допустим не нужен ваш лесяпед с рекурсией в реальной процедуре.а нужен вложенный цикл.

0

4

Sergeihik написал(а):

Без процедуры работает а в ней косяк?

Ошибка в коде, но в процедуре она более очевидна. Не нужно выходить через Goto из Select. Из-за этого из стека не извлекается значение. Если не хочешь переписывать код  можно вручную извлечь данные из стека, но это не самое лучшее решение хоть и рабочее.

Код:
Procedure x()
  Protected r=0
  cikl:
  If r<21
    Select r
      Case 0 To 20
        r+1
        Debug r
        FakeReturn
        Goto cikl
    EndSelect  
  EndIf
EndProcedure
x()

0

5

Получается select извлекает в стек значение и так как нет endselect то стек не очищается,так?

0

6

Sergeihik, открой окно ассемблерной отладки, перейди на вкладку стека и пройтись пошагово по коду. Будет видно как данные загружаются в стек и выгружаются из него.

0

7

Не помню я как это сделать но дизасмом сейчас посмотрел и ахнул

Код:
.code:00402000 sub_402000      proc near               ; CODE XREF: start+3Fp
.code:00402000
.code:00402000 var_8           = dword ptr -8
.code:00402000 var_4           = dword ptr -4
.code:00402000
.code:00402000                 push    ebx
.code:00402001                 xor     eax, eax
.code:00402003                 push    eax
.code:00402004                 mov     [esp+4+var_4], 0
.code:0040200B
.code:0040200B loc_40200B:                             ; CODE XREF: sub_402000+30j
.code:0040200B                 mov     ebx, [esp+4+var_4]
.code:0040200E                 cmp     ebx, 15h
.code:00402011                 jge     short loc_402033
.code:00402013                 push    [esp+4+var_4]
.code:00402016                 xor     ebx, ebx
.code:00402018                 cmp     ebx, [esp+8+var_8]
.code:0040201B                 jg      short loc_402032
.code:0040201D                 mov     ebx, 14h
.code:00402022                 cmp     ebx, [esp+8+var_8]
.code:00402025                 jl      short loc_402032
.code:00402027                 mov     ebx, [esp+8+var_4]
.code:0040202B                 inc     ebx
.code:0040202C                 mov     [esp+8+var_4], ebx
.code:00402030                 jmp     short loc_40200B
.code:00402032 ; ---------------------------------------------------------------------------
.code:00402032
.code:00402032 loc_402032:                             ; CODE XREF: sub_402000+1Bj
.code:00402032                                         ; sub_402000+25j
.code:00402032                 pop     eax
.code:00402033
.code:00402033 loc_402033:                             ; CODE XREF: sub_402000+11j
.code:00402033                 xor     eax, eax
.code:00402035                 add     esp, 4
.code:00402038                 pop     ebx
.code:00402039                 retn
.code:00402039 sub_402000      endp

Это пипец
сейчас через время будет проганю через свою прогу(гдето ручками,надо дорабатывать прогу но время желает лучшего)для более понятного и немного по комментирую тогда.
Ps:Пётр пока хочется спросить ведь break и continue нормально выход делают,поэтому и для goto допустим нельзя ли стек или чего там также сделать и обозвать допустим gotoselect(прыжок из обработчика значений селекта)?
pps:целыый вечер перед тем как задать вопрос не мог понять что у меня то память вылетает то ещё дебуг показывает на goto,ну и пришол в итоге к этим проверкам где понял не работоспособность.а таких конструкций ранее не припомню что бы делал?и это(FakeReturn,может это в новых версиях?) первый раз услышал а так думаю логически вроде бы должно работать а не тут то было.

Отредактировано Sergeihik (26.08.2021 19:38:57)

0

8

и получаем это

Код:
Procedure x()

                !push    ebx
                !xor     eax,eax
                !push    eax
                !mov     [esp],0
!loc_40200B:                            
                !mov     ebx,[esp]
                !cmp     ebx,15h
                !jge     short loc_402033
                !push    [esp]
                !xor     ebx,ebx
                !cmp     ebx,[esp]
                !jg      short loc_402032
                !mov     ebx,14h
                !cmp     ebx,[esp]
                !jl      short loc_402032
                !mov     ebx,[esp+8+-4]
                !inc     ebx
                !mov     [esp+8+-4],ebx
                !jmp     short loc_40200B
; ---------------------------------------------------------------------------
!loc_402032:                            
                                      
                !pop     eax
!loc_402033:                            
                !xor     eax,eax
                !add     esp,4
                !pop     ebx
                !retn
EndProcedure

0

9

Код:
Procedure x()

                !push    ebx
                !xor     eax,eax
                !push    eax
                !mov    dword [esp],0
!loc_40200B:                            
                !mov     ebx,[esp]
                !cmp     ebx,15h
                !jge     short loc_402033
                !push   dword [esp]
                !xor     ebx,ebx
                !cmp     ebx,[esp]
                !jg      short loc_402032
                !mov     ebx,14h
                !cmp     ebx,[esp]
                !jl      short loc_402032
                !mov     ebx,[esp+8+-4]
                !inc     ebx
                ;===========
                !mov dword[v_r],ebx
                 Debug r
                ;=============
                !mov     [esp+8+-4],ebx
                ;=======
                !pop eax;собственно да стек не очищает и нет этой команды
                ;=======
                !jmp     short loc_40200B
; ---------------------------------------------------------------------------
!loc_402032:                            
                                      
                !pop     eax
!loc_402033:                            
                !xor     eax,eax
                !add     esp,4
                !pop     ebx
                !retn
EndProcedure
              x()

Вот уж действительно компиляция индусская,мучать так стек перекидывая в цикле через него переменную.................
PS:Когда понял переделал на if-ах

Отредактировано Sergeihik (27.08.2021 06:47:44)

0

10

А что ты ждал то? TinyC тоже выдает полный ахтунг.

0

11

Sergeihik написал(а):

Вот уж действительно компиляция индусская

Компиляция в PB 6.0.

Код:
loc_140001060
add     rbx, 1
cmp     rbx, 15h
jnz     short loc_140001060

Так лучше?

0

12

Пётр написал(а):

Компиляция в PB 6.0.

Так лучше?

Странный вопрос с кодом в три строчки,есле так компилит то не отражает полную суть проверок(нет же вложенной проверки)
если это намёк на то что теперь стек возможно не участвует в коде pb 6.0 x64 то может и лучше?
Ps: мой пример самый первый конечно тоже не идеален если его рассматривать как есть но он просто для сути вложенности а так там проверка другая на данные в памяти
и данные ячеек другие ,а то скажите ещё что так проще.:)

Код:
Procedure x()
Protected r=0
cikl:
If r<21
Select r
  Case 0 To 20
    r+1
    Debug r
    Goto cikl
EndSelect  
EndIf
EndProcedure
x()

Procedure x2()
Protected r=0
cikl:
If r<21 and r>-1
    r+1
    Debug r
    Goto cikl
EndIf
EndProcedure
x2()

Отредактировано Sergeihik (27.08.2021 18:31:52)

0

13

Этот код бесполезный и компилятор его выкидывает. Заменил Debug на Delay чтобы компилятор увидел в коде хоть какой-то смысл.

Код:
Procedure x()
Protected r=0
cikl:
If r<21
Select r
  Case 0 To 20
    r+1
    Delay(2)
    Goto cikl
EndSelect  
EndIf
EndProcedure
x()

Procedure x2()
Protected r=0
cikl:
If r<21 And r>-1
    r+1
    Delay(2)
    Goto cikl
EndIf
EndProcedure
x2()

Вот что получилось.

Код:
 ; int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
.text:0000000140001030 WinMain         proc near               ; CODE XREF: start+20Cp
.text:0000000140001030                                         ; DATA XREF: .pdata:000000014000300Co ...
.text:0000000140001030                 push    rbx
.text:0000000140001031                 sub     rsp, 20h
.text:0000000140001035                 xor     ecx, ecx        ; lpModuleName
.text:0000000140001037                 mov     ebx, 15h
.text:000000014000103C                 call    GetModuleHandleW
.text:0000000140001041                 xor     r8d, r8d        ; dwMaximumSize
.text:0000000140001044                 mov     edx, 1000h      ; dwInitialSize
.text:0000000140001049                 xor     ecx, ecx        ; flOptions
.text:000000014000104B                 mov     cs:qword_140004368, rax
.text:0000000140001052                 call    HeapCreate
.text:0000000140001057                 mov     cs:hHeap, rax
.text:000000014000105E                 xchg    ax, ax
.text:0000000140001060
.text:0000000140001060 loc_140001060:                          ; CODE XREF: WinMain+3Ej
.text:0000000140001060                 mov     ecx, 2
.text:0000000140001065                 call    sub_140001474
.text:000000014000106A                 sub     rbx, 1
.text:000000014000106E                 jnz     short loc_140001060
.text:0000000140001070                 mov     ebx, 15h
.text:0000000140001075
.text:0000000140001075 loc_140001075:                          ; CODE XREF: WinMain+53j
.text:0000000140001075                 mov     ecx, 2
.text:000000014000107A                 call    sub_140001474
.text:000000014000107F                 sub     rbx, 1
.text:0000000140001083                 jnz     short loc_140001075
.text:0000000140001085                 call    sub_140001010
.text:0000000140001085 WinMain         endp

То что до loc_140001060 это начальная инициализация.
call    sub_140001010 в конце кода это деинициализация.
call    sub_140001474 это вызов Delay.

0

14

И эти люди рассуждают о качестве кода:

Код:
Case 0 To 20
Код:
if r>=0 and r <=20

0

15

Ерунду Пётр не пишите ,посмотрите на свой пост выше и как же у вас так выходит 2 разных кода?

Код:
loc_140001060
add     rbx, 1
cmp     rbx, 15h
jnz     short loc_140001060

0

16

egons написал(а):

И эти люди рассуждают о качестве кода:

Да уж,а нечего что цикл идёт на?
cikl:
If r<21
а  r может до цикла к примеру быть с отрицательным числом....

Отредактировано Sergeihik (28.08.2021 07:45:12)

0

17

ты зря сам заморачиваешься и другим мозг пудришь. поучись с другого языка что ли - в моде Питон и Го.

0

18

egons написал(а):

ты зря сам заморачиваешься и другим мозг пудришь. поучись с другого языка что ли - в моде Питон и Го.

Вопрос был про очевидную ошибку которую делает компилятор а не как упростить код есле что.
Вопрос решён и смысла писать дальше не вижу.

0

19

Sergeihik написал(а):

Ерунду Пётр не пишите

Я выложил дизассемблированный асм код вашего кода. Я же написал что код с точки зрения компилятора не выполняет никаких полезных действий, не зря же Delay добавил, а значит неиспользуемый код выбрасывается. Это называется "оптимизация".
Скомпилируйте код в PB 6 с C backend и включенной оптимизацией и посмотрите на результат.

Sergeihik написал(а):

а  r может до цикла к примеру быть с отрицательным числом

В коде переменной r присваивается 0, а значит компилятор знает что переменная равна нулю.

0

20

А вот это у кого что выдаёт,это у меня только -1?

Код:
time.w=-8191
Debug time
time>>15
Debug time

хотел проверку бита сделать If (time>>15)=1
а тут на тебе задвигает при сдвиге единицы

-1

21

Sergeihik написал(а):

А вот это у кого что выдаёт,это у меня только -1?

В справке же ясно написано что сдвиг арифметический. То есть с учетом того что число имеет знак.
Используйте беззнаковые переменные.

Sergeihik написал(а):

хотел проверку бита сделать If (time>>15)=1

Код:
time.w=-8191
If time & 1<<15
  Debug 1
Else
  Debug 0
EndIf

0

22

Sergeihik написал(а):

Вопрос был про очевидную ошибку которую делает компилятор а не как упростить код есле что.
Вопрос решён и смысла писать дальше не вижу.

ошибка в ДНК похоже. А ничего, что переменная объявлена protected?

0

23

Sergeihik написал(а):

А вот это у кого что выдаёт,это у меня только -1?

хотел проверку бита сделать If (time>>15)=1
а тут на тебе задвигает при сдвиге единицы

если ты разделишь -4 на 2, то выйдет -2.

0

24

Syntax

Goto <label>

Description

This command is used to transfer the program directly to the labels position. Be cautious when using this function, as incorrect use could cause a program to crash...

Note:
To exit a loop safely, you always must use Break instead of Goto, and never use it inside a Select/EndSelect block (Unless you have the ability to manage the stack yourself, correctly.)
Примечание:
Чтобы безопасно выйти из цикла, вы всегда должны использовать Break вместо Goto и никогда не использовать его внутри блока Select / EndSelect (если у вас нет возможности правильно управлять стеком).

https://www.purebasic.com/documentation … thers.html

p.s. так что ошибка традиционная и называется она "Не читал, но осуждаю"

Отредактировано useful (28.08.2021 23:30:55)

0


Вы здесь » PureBasic - форум » PureBasic для Windows » Что за ошибка?