INF1018 - Software Básico

Aulas de Laboratório

Código de Máquina

  1. Traduza a função abaixo para assembler:

    int foo (int x) {
      return x+1;
    }
    

  2. Use gcc -c prog.s para traduzir seu programa para linguagem de máquina (o gcc vai gerar um arquivo prog.o). Veja qual o código de máquina que seu programa gera, usando ou objdump -d prog.o ou a opção -Wa,-al do gcc.

  3. Escreva agora um programa em C como descrito a seguir. Esse programa deve criar um array de bytes (unsigned char) preenchido com o código de máquina visto no item anterior. A seguir, ele deve converter o endereço do array para um endereço de função. Para isso, declare o tipo ponteiro para função recebendo int e retornando int, conforme abaixo:

    typedef int (*funcp) (int x);
    
    A seguir, atribua o endereço do array a uma variável do tipo acima:
    funcp f = (funcp)a;
    
    Agora, você pode chamar f como se fosse uma função C normal. Faça isso no seu programa. Será necessário compilar seu programa com gcc -Wall -Wa,--execstack seuprograma.c. Execute o programa resultante.

  4. Modifique o programa anterior para ele criar no array o equivalente às duas funções abaixo:

    int bar (int x) {
      return  x+2;
    }
    int foo (int x) {
      return bar(x)+1;
    }
    

    (Se quiser, gere o código de máquina diretamente a partir de C, com gcc -c -O0 prog.c.) Observe que o código gerado contém a instrução de chamada:

    e8 fc ff ff ff 
    
    Nessa instrução, o byte e8 representa o código de call, e os quatro bytes seguintes, o deslocamento da função chamada em relação à instrução seguinte (em little endian!). Esse deslocamento NÃO está correto no arquivo .o. Calcule qual deve ser o deslocamento para a chamada de foo a bar e complete o código corretamente.

    Seu programa C deve chamar a função foo. No entanto, ela não está no início do array de código a. Vamos fazer isso de duas maneiras:

    1. atribua a seu ponteiro para função o endereço da posição do array onde começa a função foo. Execute o programa.
    2. [mais elegante!] insira, no início do seu array com código, um jmp para a posição onde começa foo. O código do jmp é e9 seguido de 4 bytes com o deslocamento do endereço desejado em relação ao endereço da próxima isntrução. Volte a atribuir a seu ponteiro de função o ponteiro para o início do código, como antes. Execute o programa.