Ir para conteúdo

SpaceHoll0w

Membros
  • Postagens

    10
  • Registro em

  • Última visita

Posts postados por SpaceHoll0w

  1. 17 horas atrás, Felipe.Silva disse:

    Essas diretivas CFI (Call Frame Information) geram informações que são usadas pelo depurador de código. A sigla CFA é de Canonical Frame Address que seria o endereço do stack pointer antes de entrar na função atual.

    A diretiva `.cfi_def_cfa` é usada para definir o valor do CFA. O primeiro parâmetro é um número que identifica um registrador e o segundo um valor numérico sinalizado (offset). O valor do CFA é definido como o valor desse registrador somado ao offset no segundo parâmetro.

    No caso o número 1 identifica o registrador EAX/RAX, o que não faz muito sentido ao meu ver. Essa diretiva foi tirada de um código real?

    Um exemplo real que peguei aqui foi:

    .cfi_def_cfa 7, 8

    Onde o 7 é o registrador RSP. Então essa diretiva está gerando informação para dizer para o depurador: "Nesse exato momento o CFA é RSP+8"

    Você pode desabilitar essas diretivas com a flag -fno-asynchronous-unwind-tables, daí o código fica mais legível. Exemplo:

    $ gcc exemplo.c -o exemplo.s -S -fno-asynchronous-unwind-tables

    Referências

    "No caso o número 1 identifica o registrador EAX/RAX, o que não faz muito sentido ao meu ver", sim foi tirado de um codigo de verdade, acredite, olhe... (muito obrigado pela resposta  amigo) 

     

    cfi.PNG

  2. 14 horas atrás, Felipe.Silva disse:

    Isso é só um rótulo (label) e não faz absolutamente nada. A sintaxe para declarar um rótulo é igual a sintaxe da linguagem C, colocando o nome do rótulo seguido de dois-pontos.

    Um rótulo é meramente um "nome" que pode ser usado para obter o endereço de memória do byte que está logo em seguida onde o rótulo foi declarado. Repare nesse código aí:

    .LC0:
    	.string "ola"

    Logo após a declaração do rótulo há uma pseudo-instrução .string que recebe uma expressão de string como parâmetro. O que ela faz é simplesmente despejar os bytes da string aonde foi invocada. Portanto o rótulo .LC0 é um "nome" para o endereço da string "ola".

    Repare que no finalzinho do print esse rótulo é utilizado (na penúltima instrução):

    	call	__x86.get_pc_thunk.ax
    	addl	$_GLOBAL_OFFSET_TABLE, %eax
    	subl	$12, %esp
    	leal	.LC0@GOTOFF(%eax), %edx
    	pushl	%edx

    Esse call na primeira instrução é um "truque" que o GCC faz para obter endereços relativos. Para entender isso sugiro que leia isso aqui.

    A instrução leal (penúltima) é usada para obter o endereço daquela string e armazenar no registrador EDX, logo em seguida esse endereço é empilhado.

    ---

    O próprio Mente Binária tem um livro de Assembly que explica algumas coisas à respeito. O capítulo "Programando junto com C" será especialmente útil para você pois ele lida com o GAS e explica como código C funciona após compilado (em Assembly):

    https://mentebinaria.gitbook.io/assembly/programando-junto-com-c

    vlw amigo! agora só falta entender uma outra parte do codigo.

  3. 46 minutos atrás, Fernando Mercês disse:

    Opa, a instrução não tá completa aí.. falta o segundo argumento do MOV, mas é o seguinte:

    A sintaxe Intel, que é essa que você usou o exemplo, funciona assim:

    instrução argumento1, argumento2, argumento3...

    No caso do MOV, que é uma instrução de cópia de dados e por isso possui dois argumentos, o destino vem primeiro e a origem depois. Então é:

    mov destino, origem

    Então no seu exemplo:

    mov dword ptr ds:[eax + 0x30]

    Ou seja, você colocou só o destino, por isso a instrução tá incompleta, mas tudo bem, talvez sua dúvida seja no destino mesmo. Esse destino aí diz o seguinte:

    Copie uma DWORD (palavra dupla, ou seja, 32-bits/4 bytes) para o endereço apontado pelo registrador EAX, mas some 0x30 (48 em decimal) a este endereço antes. Ou seja, suponha que tenhamos o valor 0x950000 no registrador EAX e a instrução completa seja:

    mov dword ptr ds:[eax + 0x30], 0xffffffff

    Após executar essa instrução, o valor 0xffffffff será copiado para o endereço 0x950030 (que é o tal EAX + 0x30). O ds vem de data segment e já dá a dica que este é um segmento de dados. No caso de executáveis de Windows, provavelmente este endereço estará na seção .data, já que está sendo usado para escrita (o valor é copiado para lá) e esta seção em geral possui permissão de escrita quando mapeada em memória.

    Abraço,

    Fernando

    vlw mano!

×
×
  • Criar Novo...