Jump to content

fredericopissarra

Membros
  • Posts

    374
  • Joined

  • Last visited

Everything posted by fredericopissarra

  1. Você ainda não entendeu que `char` não é um "caractere"... é um tipo INTEIRO onde, dentro dele CABE o código de um. Experimente isso: printf( "%d\n", 'a' );
  2. O mais complicado você já fez: PS: Sorry.... não precisa do header cstring não...
  3. Hehehe... juro que quase comemorei aqui... Fiquei imaginando containers inteiros sendo jogados no mar... 🙂
  4. Sorry... demonstração errada... Essa é a certa.
  5. DDR? (Data Direction Register). Um bit 0 significa entrada, bit 1 significa saída. PORT? (são os bits das portas). Aliás... se é para implementar um relógio, é melhor usar interrupção gerada pelo timer do microcontrolador do que tentar temporizar isso num loop. Faltam MUITOS detalhes com relação a esse seu código: Com qual frequência de clock está trabalhando? Qual é o significado dos bits nas portas B, C e D, usadas no código? (Qual é o circuito?) O troço é apenas um relógio? Onde as horas, minutos e segundos estão sendo mostradas? etc...
  6. Qual é exatamente o problema? Ainda, qual compilador? Para qual PIC (assumo que seja PIC)? Uma melhoria pequenininha no seu código, em anexo porque esse forum não mantém o formato de códigos fonte com fontes monoespaçadas! Note que, embora tenha extensões, alguns detalhes que não seguem a spec ISO 9899 eu mudei. cfp.c
  7. lista de classificação: List<double> lista de alunos: List<int> método da classe: public double CalcMean( List<double> classfications, List<int> qtyStudents ) { // seu código aqui... }
  8. Não... mas você pode dizer que ele está quebrado à partir do quilometro 23 (0x17) começando no quilometro 1280 (0x50 * 16). Ou seja, no quilometro 1303.
  9. Aumentando um cadinho a resposta do Felipe.Silva (e reforçando alguns pontos): Em primeiro lugar, query strings são limitadas, senão pelo seu browser, pelo menos pelo webserver. Eu acho (assim como ficou implícito na resposta do Felipe) que o limite é de 32 KiB (mas, já ouvi falar de 4 KiB ou menos). Se você precisar enviar mais dados tem que usar o método POST que, em teoria, tem um limite muito maior. Se você gerar um script que faça bilhões de requisições (não dá pra fazer no mesmo computador!) o site não cai porque o webserver tem um limite de conexões simultâneas. As demais ele simplesmente desconecta. Isso é diferene de enviar bilhões de "pacotes" TCP para o servidor alvo, por exemplo. No caso de uma aplicação, geralmente não se expõe a conexão com o banco de dados diretamente. Então, o limite do tamanho de uma query (outro tipo de query - uma query SQL) não está diretamente relacionada com a http query.
  10. Um "macete" para evitar ficar lembrando os offsets na pilha é usar estruturas (exemplo com o NASM, código para i386): struc fmastkf .retaddr: resd 1 ; CALL colocar isso na pilha. .a: resd 1 .b: resd 1 .c: resd 1 endstruc fma_: mov eax,[esp+fmastkf.b] ; O compilador preferiu pegar b primeiro... imul eax,[esp+fmastkf.a] ; ... e multiplicar por a. add eax,[esp+fmastkf.c] ret O empilhamento, na chamada de fma_(), é claro, é feito de trás para frente. Assim, como a é empilhado por último, ele fica mais próximo de retaddr.
  11. Pois é... nos antigos 8086 até o 80286 só tínhamos os registradores AX, BX, CX, DX, SI, DI, BP, SP, além do IP e FLAGS e os seletores. Nos modos de endereçamento era possível usar apenas BX ou BP como endereço base e SI ou DI como índice e, ao usar BP o seletor SS era usado (ao usar BX, DS era usado). Nos 386 isso mudou e qualquer registrador de uso geral pode ser usado como base e índice, mas a seleção automática de SS quando usados ESP ou EBP continua valendo. Quanto ao "sinônimo" de código otimizado eis um exemplo simples: int fma_( int a, int b, int c ) { return a*b+c; } Se você compilar isso sem o uso de alguma opção de otimização: $ cc -S -o test1.s test.c Obterá algo assim: fma_: push rbp ; Prólogo mov rbp, rsp mov [rbp-4], edi ; Armazena os argumentos. mov [rbp-8], esi mov [rbp-12], edx ; Multiplica e soma, pegando os argumentos da pilha. mov eax, [rbp-4] imul eax, [rbp-8] mov edx, eax mov eax, [rbp-12] add eax, edx pop rbp ; Epílogo ret Note que, apesar os argumentos serem passados por registradores o compilador armazenou os argumentos na pilha (porque os argumentos são locais à função) e os leu, pela segunda vez, antes das operações... E os prólogo e epílogo estão lá... Basta adicionar -O2 na compilação para obter um código otimizado: fma_: imul edi, esi lea eax, [rdi+rdx] ret Sem armazenamento local e sem aquela preparação para o stack frame. No modo x86-64 a falta de otimização leva a aquela redundância de cópia/leitura... No modo i386 é um pouco melhor, uma vez que os argumentos já são passados pela pilha (exceto nos casos de convenções como fastcall, por exemplo): ; Sem -O2 fma_: push ebp mov ebp, esp mov eax, [ebp+8] imul eax, [ebp+12] mov edx, eax mov eax, [ebp+16] add eax, edx pop ebp ret ------------------------------ ; Com -O2 fma_: mov eax, [esp+8] imul eax, [esp+4] add eax, [esp+12] ret Note, no entanto que a função otimizada não usa EBP e acessa os argumentos diretamente da pilha.
  12. Nos modos de operação real (16 bits) e i386 (32 bits), sempre que se usa ESP ou EBP numa referência à memória, automaticamente o seletor de segmento SS é usado. Por exemplo: mov eax,[esp] ; Lê dword de SS:ESP mov eax,[ebp] ; Lê dword de SS:EBP Assim, EBP pode ser usado para apontar para qualquer lugar da pilha. Em códigos não otimizados os compiladores de linguagens de alto nível usam EBP para marcar o ínicio do stack frame usado pela função. Desse jeito: f: push ebp ; salva EBP na pilha para recuperar depois. mov ebp,esp ; EBP agora têm o endereço desse novo "topo" da pilha. A partir daí você pode manipular ESP como bem entender (PUSHes, POPs) que EBP conterá o endereço da "base" do stack frame. No final da função basta recuperar o antigo valor de EBP e sair: pop ebp ; Recupera EBP da pilha. ret Mas, isso não significa que EBP seja "especializado" como registrador de "base" da pilha. Somente sua associação com SS é que o torna "especial". Mas, ele pode ser usado como um registrador de uso geral como os demais (EAX, EBX, ECX, EDX, ESI e EDI). Eu disse que esse "macete" é usado em códigos antigos e não otimizados porque é perfeitamente possível usar ESP para acessar memória em códigos de 32 e 64 bits (não é possível em 16 bits usando SP - a não ser usando ESP). E, de fato, o uso do prólogo (ajustar EBP) e o epílogo (recuperar o EBP) não é muito desejável por questões de performance e tamanho de código (compiladores como GCC, por exemplo, se usadas otimizações, implementam a opção -fomit-frame-pointer, que evitam a criação do prólogo e epílogo). Então, sim... no contexto de uma função, pode-se pensar no EBP como a "base" do stack frame. No contexto do processador, no entanto, ele é um registrador de uso geral como qualquer outro, exceto que referências à memória, usando-o, são associadas ao seletor SS, ao invés do seletor DS.
  13. Regra geral: TODA equação, ao ser codificada usando ponto flutuante, tem que ser condicionada para evitar condições de overflow e underflow... É bom lembrar que tipos em ponto flutuante têm menor precisão binária que os mesmos tipos, do mesmo tamanho, inteiros e que o domínio da representação desses valores (em ponto flutuante) não são ℝ, mas sim ℚ (domínio dos "racionais" -- o que, se pensar bem, é óbvio). Sobre a alegação de precisão menor... O tipo long long int tem 63 bits de precisão (1 para o sinal), enquanto double tem 53 -- a estrutura de ambos os tipos e de 64 bits. A mesma coisa acontece com int e float (31 e 24, respectivamente). "Precisão" NÃO se refere à quantidade de "algarismos depois da vírgula"...
  14. Só uma dica com relação ao Teorema de Pitágoras... Ao fazer: Se a e/ou b forem muito grandes, você poderá obter +INFINTE (overflow) como resposta. A mesma coisa acontece com a exponenciação que você usou... Uma aproximação melhor e menos provável de obter overflow é selecionando o maior dos dois valores (suponha: a) e fazer: Desde que a != 0 (neste caso h=|b|). Eis a simplificação: Assim, (b/a)², no máximo, será um valor subnormal (entre 0 e 1) e a podera ser bem mais próximo do máximo valor suportado da precisão do tipo em ponto flutuante. Além de diminuir o esforço ao calcular apenas uma potência simples. A função: #include <math.h> #define swap(a,b) \ { double t; t = (a); (a) = (b); (b) = t; } double hipotenuse(double a, double b) { double tmp; if ( isnan(a) || isnan(b) ) return NAN; if (b > a) swap( a, b ); if (a < 0.0) return NAN; if ( a == 0.0 ) return fabs(b); // Poderíamos usar 'return -b' porque b pode ser igual a 0.0, o que resultaria em -0.0, // que, para todos os efeitos, é a mesma coisa que +0.0. tmp = b / a; return a * sqrt(1.0 + tmp*tmp); }
  15. #include <stdio.h> #include <string.h> #include <stdlib.h> void verifica ( char txt[200], char aux[200], int b, char txt_orig[200] ); void criptografar ( char txt[200], int b ); int main() { char txt[200], aux[200], txt_orig[200]; int a, b; // FIXME: Onde é que esse 'a' é usado? FILE *arqp, *arqp2; arqp = fopen ( "arqp.txt", "r" ); if ( arqp == NULL ) { printf ( "Deu erro" ); system ( "pause" ); // FIXME: Não use system()! exit ( 1 ); } // FIXME: O arquivo de saída também pode não conseguir ser aberto! // Onde está o teste? // Aliás, você não o está usando abaixo! arqp2 = fopen ( "arqp2.txt", "w+" ); printf ( "String original: " ); // FIXME: feof() não faz o que você pensa que ele faz. // feof() retorna um flag setado no stream DEPOIS // que uma operação de leitura é feita! while ( !feof ( arqp ) ) { // FIXME: fgets() também pode falhar! // Ainda: Uma linha pode ter mais que 200 chars... fgets ( txt, 200, arqp ); // FIXME: Uma linha lida de um arquivo termina com '\n' (exceto, // talvez, a última linha - se não terminar com '\n'). // Isso está certo? b = strlen ( txt ); // FIXME: puts() sempre imprime um '\n' extra. puts ( txt ); strcpy ( txt_orig, txt ); criptografar ( txt, b ); // FIXME: Não era para gravar no outro arquivo? //fputs(arqp2,txt); } // FIXME: Porque à partir do 2º caracter? char *txt_novo = txt + 1; printf ( "\nString criptografada: %s", txt_novo ); verifica ( txt, aux, b, txt_orig ); fclose ( arqp ); fclose ( arqp2 ); } void criptografar ( char txt[200], int b ) { char txaux; int i; // FIXME: Note que b é o tamanho da string. // Na primeira iteração o '\0' final da string é // copiado no primeiro char do buffer. for ( i = 0; i < b; i++ ) { txaux = txt[i]; txt[i] = txt[b]; txt[b] = txaux; b--; } } void verifica ( char txt[200], char aux[200], int b, char txt_orig[200] ) { int i; printf ( "\nString verificada: " ); // FIXME: O mesmo problema acima. for ( i = 0; i <= b; i++ ) { aux[i] = txt[i]; txt[i] = txt[b]; txt[b] = aux[i]; b--; } printf ( "%s", txt ); if ( strcmp ( txt_orig, txt ) == 0 ) printf ( "\nAs frases estão iguais\n" ); else printf ( "\nAs frases estão diferentes\n" ); }
  16. Ninguém aqui vai fazer seus exercícios escolares por você.
  17. Fernando, o "shellcode" ai não está na pilha.
×
×
  • Create New...