[Ajuda] Gotos Globais
#1

Nгo й um lanзamento, nem um pedido de ajuda. Apenas criei este tуpico para discutir, e mostrar uma coisa que estou tentando fazer hб algum tempo. Nгo funcionou durante muitas tentativas, apуs algum tempo consegui fixar a arrumar meio por completo.

Basicamente, consegui mudar o modo de execucaзгo de Pawn, simulando um GOTO — consegui interromper um cуdigo e pular para outra бrea de memуria, totalmente distinta, sem qualquer vinculo com as callbacks.

Veja o exemplo abaixo:

pawn Код:
#include <a_samp>


#pragma dynamic 65335

// definiзхes para uso

#define goto<%0> \
                global_step(#%0)

#define glabel<%0> \
                globalLabel(#%0)


forward bruno2(brusno, bruno);
public bruno2(brusno, bruno) {

        new b;
        new string[] = "teste";
       
        goto<l>;
       
        #pragma unused b
        #pragma unused string

        return 1;

}

forward bruno1();

public bruno1() {
   
    new b;
    new string[] = "teste";
    print("1");
    print("2");
    print("3");
    glabel<l>;
    print("4");

    #pragma unused b

    #pragma unused string

    print("5");


}


main() {

    SetTimerEx("bruno1", 1000, false, "i", 0); // chamar a public 1 e imprimir 1,2,3,4,5
    SetTimerEx("bruno2", 2000, false, "ii", 0,0); // chamar public 2 para dar goto na public 1
}


stock globalLabel (name []) {

    static beh;

    // carregar valor da variбvel puxada na callback anterior
    #emit load.s.pri    4

    // salvar o endereзo dela em beh
    #emit stor.pri      beh

    // salvar goto em propriedade, para poder puxar pelo nome strng
    setproperty(.id = 0, .name = name, .value = beh);
    setproperty(.id = 1, .name = name, .value = _: true);
   
    return true;
}

stock global_step(label[])
{
    // puxar o endereзo de execuзгo do meu goto por strng
    static beh;

    if(  !getproperty(1,label) ) return printf("ERROR ON LABEL: %s (not executed)", label);
   
    beh = getproperty(0,label);

    // carregar endereзo de execuзгo antigo
    #emit load.pri  beh

    // adicionar 28 sobreo  valor atual de pri, para que pule o cуdigo GOTO
    //#emit add.c 28

    // fechar registro, e passar PRI para o CIP.
    #emit sctrl      6

    return 0xffffffff;

}

No exemplo abaixo, eu executo a callback bruno1 imprimindo 1,2,3,4,5. Tudo bem, entгo em outro temporizador, executo bruno2, mas aн que estб o detalhe. No bruno2 tem uma interrupзгo de memуria, que envia diretamente para callback bruno1.

Atй aн tudo bem, certo? Nгo.

Ao invйs de ele fazer uma chamada comum, como CallRemoteFunction, CallLocalFunction ou atй mesmo bruno1(); por si prуprio, ele faz algo diferente. Ele chama a funзгo, mas comeзa a executar ela pela metade imprimindo 4,5 (e nгo 1,2,3). Executando um GOTO, sу que intercalando callbacks.

Dissertem!
Reply
#2

isso e porque as funcoes 4,5 sao mais rapidas e sao chamadas primeiro que as outras? ou e erro de codigo?
Reply
#3

Й uma coisa meio avanзada, й similar o mйtodo como o y_inline de ****** trabalha. Sу que aн, ele interrompe o cуdigo e manda para o label definida atravйs de goto<>. Й como se chamasse a callback pela metade.


Tipo:

pawn Код:
main() {

   label:



   print("bruno");



   goto label;
}

Assim, vocк faz um loop. Usando o cуdigo que eu tenho, vocк pode dar goto para outras callbacks. O que nгo era possнvel sem #emit.


pawn Код:
main() {

   glabel<conexao>;

   print("callback1");

   func();

}

func () {
   print ("callback2");
   goto<conexao>;
}
Код:
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
[09:20:22] callback2
[09:20:22] callback1
Se fazer com GOTO:

pawn Код:
main() {

   conexao:

   print("callback1");

   func();

}

func () {
   print ("callback2");
   goto conexao;
}
darб erros, veja:

Quote:

grandlarc.pwn(31) : error 019: not a label: "conexao"

Reply
#4

e se fizer como fez la em cima


pawn Код:
func ()
{
    conexao:
    print ("callback2");
    goto conexao;
}
?
Reply
#5

Quote:
Originally Posted by ipsBruno
Посмотреть сообщение
O que nгo era possнvel sem #emit.
O intuito desse tуpico й provar que #emit й ъtil ? Se for, isso jб foi provado nos seus tutorias
Reply
#6

O cуdigo ficou interessante, porque vocк estб criando pontos de continuaзгo em callbacks diferentes. Mas eu nгo vejo muito progresso nisso... O goto em si jб й uma coisa feia, assim como break, vocк estб quebrando uma linha de raciocнnio, que poderia ter sido feita com lуgica simples.

Vocк me deu algumas ideias em relaзгo a esses posts sobre #emit...
Reply
#7

Quote:
Originally Posted by Willian_Luigi
Посмотреть сообщение
O cуdigo ficou interessante, porque vocк estб criando pontos de continuaзгo em callbacks diferentes. Mas eu nгo vejo muito progresso nisso... O goto em si jб й uma coisa feia, assim como break, vocк estб quebrando uma linha de raciocнnio, que poderia ter sido feita com lуgica simples.
Eu estava tentando pensar em uma maneira de expressar isso, mas nгo consegui. Sу excluo a parte do break, pois break nгo quebra o raciocнnio, ele apenas encerra um loop :3
pawn Код:
new array[50],i;
array[30] = true;
for(i=0; i<50;i++) if(array[i]) break;
print("O valor onde i й verdadeiro й %d", i);
Considero que o break й como um return que sу encerra o loop.
Reply
#8

Quote:
Originally Posted by Magnus'
Посмотреть сообщение
Eu estava tentando pensar em uma maneira de expressar isso, mas nгo consegui. Sу excluo a parte do break, pois break nгo quebra o raciocнnio, ele apenas encerra um loop :3
pawn Код:
new array[50],i;
array[30] = true;
for(i=0; i<50;i++) if(array[i]) break;
print("O valor onde i й verdadeiro й %d", i);
Considero que o break й como um return que sу encerra o loop.
uso o break em 1 comando quando usa loop e quero que o playerid id seja por exemplo o unico a ser kickado... isso encerra o loop e nao deixa os outros ser kickados...
Reply
#9

Quote:
Originally Posted by Magnus'
Посмотреть сообщение
Eu estava tentando pensar em uma maneira de expressar isso, mas nгo consegui. Sу excluo a parte do break pois break nгo quebra o raciocнnio, ele apenas encerra um loop :3
pawn Код:
new array[50],i;
array[30] = true;
for(i=0; i<50;i++) if(array[i]) break;
print("O valor onde i й verdadeiro й %d", i);
break й como um return que sу encerra o loop.
O break muitas vezes й uma utilidade para pessoas que nгo encontraram a condiзгo certa para utilizar no seu loop.
Й por isso que eu prefiro dizer que ele quebra a linha de raciocнnio.

Se vocк tem certeza que um dos valores inseridos tem de ser verdadeiro, por que vocк vai mandar rodar x vezes e ficar verificando, se pode fazer isso logo na condiзгo de parada do loop ?

pawn Код:
new i, array[] = {0,0,0,0,3,0};
for (i = 0; !array[i]; ++i) {}

printf("%d й verdadeiro", i);
Reply
#10

Quote:
Originally Posted by Willian_Luigi
Посмотреть сообщение
O break muitas vezes й uma utilidade para pessoas que nгo encontraram a condiзгo certa para utilizar no seu loop.
Й por isso que eu prefiro dizer que ele quebra a linha de raciocнnio.

pawn Код:
new i, array[] = {0,0,0,0,3,0};
for (i = 0; !array[i]; ++i) {}

printf("%d й verdadeiro", i);
Concordo com vocк que nesse caso o break poderia ser poupado, mas nгo й sempre que nos deparamos com uma condiзгo tгo simples, por isso ainda prefiro usar o break. Essa lуgica usada tambйm daria facilmente um stack overflow e encerraria o bloco inteiro.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)