unc4nny Posted April 8, 2020 at 04:32 AM Share Posted April 8, 2020 at 04:32 AM Oi. Me pediram pra formular minha duvida melhor no video que o Fernando fez de CRC. Bixo, eu achava que entendia de C, mas o jeito que esse CRC funciona me bugou um pouquinho. Depois de pensar um pouco eu ate consigo ver oq esta acontecendo, mas eu nao sei se eh isso que esta acontecendo bool checa(char *nome, int serial) { int serial_correto = 0; while (*nome) serial_correto += *nome++; return (serial == serial_correto); } int main(void) { char nome[50]; int serial; uint32_t crc = crc32((unsigned char *)checa, 63); O unico jeito que eu vejo de isso funcionar do jeito que parece que esta funcionando eh se ele pegar todos os bytes que representam essa funcao: 000000000000129b <checa>: 129b: 55 push rbp 129c: 48 89 e5 mov rbp,rsp 129f: 48 89 7d e8 mov QWORD PTR [rbp-0x18],rdi 12a3: 89 75 e4 mov DWORD PTR [rbp-0x1c],esi 12a6: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0 12ad: eb 15 jmp 12c4 <checa+0x29> 12af: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18] 12b3: 48 8d 50 01 lea rdx,[rax+0x1] 12b7: 48 89 55 e8 mov QWORD PTR [rbp-0x18],rdx 12bb: 0f b6 00 movzx eax,BYTE PTR [rax] 12be: 0f be c0 movsx eax,al 12c1: 01 45 fc add DWORD PTR [rbp-0x4],eax 12c4: 48 8b 45 e8 mov rax,QWORD PTR [rbp-0x18] 12c8: 0f b6 00 movzx eax,BYTE PTR [rax] 12cb: 84 c0 test al,al 12cd: 75 e0 jne 12af <checa+0x14> 12cf: 8b 45 e4 mov eax,DWORD PTR [rbp-0x1c] 12d2: 3b 45 fc cmp eax,DWORD PTR [rbp-0x4] 12d5: 0f 94 c0 sete al 12d8: 5d pop rbp 12d9: c3 ret 0x55, 0x48, 0x89, 0xe5... etc, castar para char*, e fazer o calculo. Eh assim que funciona mesmo? Se eu estiver errado (O que eh bem provavel kkk) alguem me ajuda ai! Obg desde ja! Link to comment Share on other sites More sharing options...
Marioh Posted April 8, 2020 at 11:45 AM Share Posted April 8, 2020 at 11:45 AM Man eu acho que é exatamente assim, até mesmo se tu olhar o codigo de "crc32.c"... u_int32_t chksum_crc32 (unsigned char *block, unsigned int length){ register unsigned long crc; unsigned long i; crc = 0xFFFFFFFF; for (i = 0; i < length; i++) { // incremento // vvvvvv crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF]; } return (crc ^ 0xFFFFFFFF); } u_int32_t crc32(unsigned char *block, unsigned int length){ if(!initialized){ chksum_crc32gentab(); initialized = 1; } return chksum_crc32(block, length); } Já da pra perceber que o nome da variavel na "crc32" é "length"(suspeito...), além disso o "for" na "chksum_crc32" realmente "passa" length vezes, incrementando "block"(o address da funcao) cada vez que "passa". Mas assim, não sou especialista. Link to comment Share on other sites More sharing options...
fredericopissarra Posted April 8, 2020 at 12:37 PM Share Posted April 8, 2020 at 12:37 PM Prefira sempre compilar seus códigos com a opção -O2 (pelo menos). Isso criará código mais "enxuto". A função checa(), por exemplo, ficará assim: ; Entrada: RDI = nome, ESI = serial ; Saída AL (0 = false, 1 = true). checa: movsx eax, BYTE PTR [rdi] ; Lê o primeiro byte. xor edx, edx ; edx = serialcorreto = 0 test al, al ; fim de string? je .endOfString ; sim, salta para a comparação. .loop: add rdi, 1 ; aponta para o próximo byte add edx, eax ; acumula o checksum. movsx eax, BYTE PTR [rdi] ; lê o próximo byte. test al, al ; fim de string? jne .loop ; não, volta ao loop. .endOfString: cmp esi, edx ; serial == serialcorreto? sete al ; ajusta AL. ret No entanto, não entendi qual é a dúvida, especificamente... Link to comment Share on other sites More sharing options...
unc4nny Posted April 8, 2020 at 02:15 PM Author Share Posted April 8, 2020 at 02:15 PM 1 hour ago, fredericopissarra said: No entanto, não entendi qual é a dúvida, especificamente... Opa, foi mal.Minha duvida eh, como que funciona o casting da funcao para uma string? Isso parece meio esoterico, pelo menos na minha cabeca ashduiahsduih Link to comment Share on other sites More sharing options...
Marioh Posted April 8, 2020 at 04:28 PM Share Posted April 8, 2020 at 04:28 PM Bom, o jeito que eu entendo os casts é simplesmente um modo de interpretar os bytes dentro daquele endereço. No código la o cara usa um char justamente pra poder acessar byte por byte, lembrando que na aritimética de ponteiro quando uma soma é feita, na verdade estamos somando n+(sizeof(elemento)). Acho que o @fredericopissarra deve saber explicar melhor. Fiz um programinha aqui: #include<stdio.h> #include<stdlib.h> int main(void){ FILE *fd = fopen("number","r"); unsigned long int li; fread(&li, sizeof(li), 1, fd); // os tamanhos so pra ajudar //printf("char: %zu\n", sizeof(char)); //printf("short: %zu\n", sizeof(short)); //printf("int: %zu\n", sizeof(int)); //printf("%zu\n", sizeof(long int)); // aqui vem os casts printf("%hhu\n",(unsigned char) li ); printf("%hu\n",(unsigned short) li ); printf("%u\n",(unsigned int) li ); printf("long value: %ld\n",li ); return 0; } number: [mario@zrmt forum]$ hd number 00000000 01 01 00 01 00 00 00 01 |........| 00000008 quando executado: [mario@zrmt forum]$ ./cast 1 257 16777473 72057594054705409 O char vai interpretar o primeiro byte, o short os dois primeiros, o int os quatro e o long todos os oito. Mas tambem posso estar terrivelmente errado. Link to comment Share on other sites More sharing options...
unc4nny Posted April 8, 2020 at 04:37 PM Author Share Posted April 8, 2020 at 04:37 PM 7 minutes ago, Marioh said: Bom, o jeito que eu entendo os casts é simplesmente um modo de interpretar os bytes dentro daquele endereço. Faz sentido mano. Deu pra dar uma esclarecida agora, brigadao cara Link to comment Share on other sites More sharing options...
fredericopissarra Posted April 8, 2020 at 10:42 PM Share Posted April 8, 2020 at 10:42 PM 8 horas atrás, unc4nny disse: ...Minha duvida eh, como que funciona o casting da funcao para uma string?... De novo, a dúvida ainda está confusa... "casting de função para string"? Em primeiro lugar, não existem "strings" em C (mas sim arrays de chars, onde o último char é um '\0')... Em segundo lugar, o identificador de uma função é um ponteiro, bem como o identificador de um array é convertido para um ponteiro. No seu exemplo, eu suponho que a função crc32() tenha o protótipo: uint32_t crc32( unsigned char *ptr, size_t size ); Quando o argumento ptr poderia ser, muito bem, definido como um ponteiro para void e, neste caso, qualquer casting de ponteiro na passagem deste argumento para a função seria supérfluo (void * aponta para qualquer coisa). Este é o mesmo caso de chamadas à função malloc(), por exemplo: char *p; p = malloc( 16 ); // aloca 16 bytes e devolve o ponteiro. Casting aqui é desnecessário porque malloc() tem o protótipo: void *malloc( size_t size ); Como o @Marioh disse ai em cima, casting é uma maneira de reinterpretar um tipo. Por exemplo: int x = 1, y = 2; float z; // O casting aqui é "obrigatório" porque senão a divisão será feita // com INTEIROS, resultando num INTEIRO que depois será convertido para // float... Com o casting, a divisão será entre valores em PONTO FLUTUANTE. z = (float) x / y; // z = 0.5; z = x / y; // isso resulta em 0.0! Casting pode ser usado para forçar a barra da atualização de um ponteiro também: char *p; ... // inicializa p em algum lugar... ... *(int *)p++ = 1; // aqui p[0]=1, p[1] até p[3]=0 (little endian). // mas, p será avançado em 4 posições... (sizeof(int)). Quando fazemos a conversão de tipos de menor precisão para maior, não precisamos de castring também. A promoção de tipos funciona direitinho... Para fazer a "demoção" de tipos o castring pode ser necessário para evitar avisos do compilador: char a; int b = 10; a = (char)b; // casting para evitar (?) warnings... nem sempre evita! b = a; // castring desnecessário. Agora... no seu exemplo, você está passando um ponteiro para uma função (checa) para a função crc32(). O que é válido, mas LER a memória onde a função foi codificada é um "comportamento indefinido" (undefined behavior) - escrever nessa memória, provavelmente causará um SEGMENTATION FAULT - um erro. Note que, no seu caso, o identificador checa equivale ao ponteiro: _Bool (*checa)( char *, int ); Se seu crc32() for definido como: uint32_t crc32( unsigned char *, size_t ); Então o pontiero terá que sofrer casting para evitar avisos... Note que isso pode não funcionar em todas as plataformas. Algumas assumem ponteiros para região de código com tamanho diferente da ponteiros para região de dados... Outras não permitem isso... Link to comment Share on other sites More sharing options...
fredericopissarra Posted April 8, 2020 at 10:49 PM Share Posted April 8, 2020 at 10:49 PM PS: "CAST" é uma daquelas palavras em inglês difíceis de fixar... "CAST" significa elenco (teatro), mas também "jogar" (como em "cast a spell" ou "jogar um feitiço"). Mas, também é o nome que se dá ao suporte usado quando quebramos um braço ou uma perna (um "molde")... Esse último parece ser o neologismo para "casting", no contexto de C... Link to comment Share on other sites More sharing options...
Marioh Posted April 9, 2020 at 03:16 PM Share Posted April 9, 2020 at 03:16 PM Quote Então o pontiero terá que sofrer casting para evitar avisos... Note que isso pode não funcionar em todas as plataformas. Algumas assumem ponteiros para região de código com tamanho diferente da ponteiros para região de dados... Outras não permitem isso... @fredericopissarra Uma duvida, a arquitetura de harvard seria assim? Link to comment Share on other sites More sharing options...
fredericopissarra Posted April 9, 2020 at 07:10 PM Share Posted April 9, 2020 at 07:10 PM 3 horas atrás, Marioh disse: @fredericopissarra Uma duvida, a arquitetura de harvard seria assim? Era o que eu tinha em mente mesmo! ? Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.