Skip to content

11 - Revisão

Na aula de hoje iremos revisar nossas atividades com Assembly e representação de inteiros.

Quando tiver dúvidas, chame o professor ou os ninjas!

Importante

Esta aula tem duas partes:

  • Exercícios de revisão (ex1.c, ex2.c, ex3.c e ex4.c)
    • Siga o roteiro para desenvolvê-los
  • Simulado de prova
    • Veja mais detalhes no final do roteiro!

Ex1.c

Abra o código-fonte ex1.c e confira a função main. Compile e execute o exercício 1. Em seguida, responda:

Exercise

O valor apresentado na saída confere com o presente no código? Por que isto acontece?

Answer

O valor -1 em complemento de 2 é representado como uma sequência de 1's. Ao ser atribuído em uma unsigned short, teremos dezesseis 1's, mas que serão interpretados como unsigned. Somando 2^0 + 2^1 + \dots + 2^{15} = 65535

Exercise

Qual o maior valor que pode ser armazenado em uma variável unsigned short?

Answer

A variável será de 2 bytes sem sinal, assim o maior valor é 2^{16}-1 = 65535

Exercise

O que acontece quando tentamos armazenar um valor maior que o suportado pelo tipo de dados? Ex: atribuir 80000 para uma unsigned short.

Answer

Apenas os 16 bits menos significativos serão considerados.

Ex2.c

Neste exercício iremos fazer engenharia reversa de Assembly para C. Os códigos-fonte estão disponíveis no repositório, mas evite abri-los antes de ter feito pelo menos uma primeira versão da engenharia reversa.

Compile o ex2.c com

$ gcc -Wall -std=c99 -Og ex2.c -c -o ex2.o

Abra o arquivo ex2.o com o gdb sem abrir o código-fonte e responda:

Exercise

Liste as variáveis globais e funções existentes.

Answer

Funções func1 e func2. Sem variáveis globais.

Analise a função func1 com o gdb e responda:

Exercise

Com base nos registradores utilizados, escreva a assinatura da função func1.

Answer

void func1(unsigned short *vec)
A partir de um ponteiro armazenado em %rdi, são feitas várias atribuições espaçadas em dois bytes, indicando ser um ponteiro para short.

Exercise

Em movw $0x0,(%rdi), qual a operação realizada e o que significa o trecho (%rdi)?

Answer

A operação é vec[0] = 0 ou *vec = 0. Como a operação é um MOV, então (%rdi) representa uma dereferenciação de ponteiro.

Tip

Veja a seção Acesso a elementos constantes da aula 09 - Arrays

Exercise

Em movw $0x14,0x4(%rdi), qual a operação realizada e o que significa o trecho 0x4(%rdi)?

Answer

A operação é vec[2] = 20. Em 0x4(%rdi), indicamos que queremos acessar o endereço %rdi + 4 bytes.

Tip

Acese na aula 05-Condicionais a explicação sobre as variântes da instrução mov

Exercise

Faça uma versão legível em C da função func1.

Answer

void func1(unsigned short *vec) {
    vec[0] = 0;
    vec[1] = 10;
    vec[2] = 20;
}

Analise a função func2 com o gdb e responda:

Exercise

Com base nos registradores utilizados, escreva a assinatura da função func2.

Answer

void func2(int *vec, int n)
Caso restem dúvidas, chame os professores.

Exercise

Qual a operação realizada em lea (%rax,%rax,4),%edx na função func2?

Answer

É uma operação aritmética onde o valor armazenado em %rax é multiplicado por 5 e armazenado em %edx.

Exercise

Qual a operação realizada em add %edx,%edx na função func2?

Answer

É uma operação aritmética onde o valor armazenado em %edx é somado consigmo mesmo e armazenado em %edx. Isto é equivalente a fazer var = var * 2.

Exercise

Você conseguiria agregar as operações lea (%rax,%rax,4),%edx e add %edx,%edx em uma única operação aritmética mais simples?

Answer

Supondo que %eax representa a variável i, então a junção das duas operações é equivalente a fazer i * 10, cujo resultado é armazenado em %edx.

Exercise

Faça uma versão em C do código acima usando somente if-goto. Escreva, então, ao lado desta versão um código legível em C.

Answer

Versão if-goto:

void func2(int *vec, int n) {
    int i = 0;
    int aux;

        goto test;

    loop:

        aux = i * 5;
        aux = aux + aux;

        vec[i] = aux;

        i = i + 1;
    test:    
        if (i < n) {
            goto loop:
        }

        return;
}

Versão C:

void func2(int *vec, int n) {
    for (int i = 0; i < n; i++) {
        vec[i] = i * 10;
    }
}
Caso restem dúvidas, chame os professores.

Ex3.c

Neste exercício iremos fazer engenharia reversa de Assembly para C. Os códigos-fonte estão disponíveis no repositório, mas evite abri-los antes de ter feito pelo menos uma primeira versão da engenharia reversa.

Compile o ex3.c com:

$ gcc -Wall -std=c99 -Og ex3.c -o ex3

Abra o arquivo ex3 com o gdb sem abrir o código-fonte e responda:

Exercise

Liste as funções e variáveis globais disponíveis.

Answer

Variável global v_global. Funções func1, func2, func3, func4 e main.

Exercise

Faça a tradução das funções func1 e func2. Existe alguma semelhança?

Answer

Ambas fazem operações com registradores. Porém func2 faz a leitura de algum valor de memória e armazenando no retorno da função, uma variável global. Já func1 apenas faz uma operação aritmética com o parâmetro recebido.

int func1(int n) {
    int x = 10;
    return x + n;
}

int func2(int n) {
    return v_global + n;
}

Tip

Fique atento a chamadas de variáveis globais. Utilize o comando x para imprimir o conteúdo de um endereço. Veja mais em https://sourceware.org/gdb/current/onlinedocs/gdb#Memory

Exemplo:

x/d  0x100

x/s  0x100

Exercise

Defina a assinatura da função func3 e faça sua tradução para C.

Answer

int func3(int n, int mult) {
    return v_global + n * mult;
}

Exercise

Defina a assinatura da função func4. Faça uma versão em C do código acima usando somente if-goto. Escreva, então, ao lado desta versão um código legível em C.

Answer

Versão if-goto:

void func4() {
    res = func1(5);

    if (res <= 20) {
        goto faz_algo;
    }

    printf("O novo valor eh maior que 20");

    retorna:
        return;

    faz_algo:
        printf("O novo valor nao eh maior que 20");
        goto retorna;

}

Versão C:

void func4() {
    int aux = func1(5);
    if (aux > 20) {
        printf("O novo valor eh maior que 20");
    } else {
        printf("O novo valor nao eh maior que 20");
    }
}

Ex4.c

Neste exercício iremos fazer engenharia reversa de Assembly para C. Os códigos-fonte estão disponíveis no repositório, mas evite abri-los antes de ter feito pelo menos uma primeira versão da engenharia reversa.

Compile o ex4.c com:

$ gcc -Wall -std=c99 -fno-stack-protector -Og ex4.c -o ex4

Abra o arquivo ex4 com o gdb sem abrir o código-fonte e responda:

Exercise

Defina a assinatura da função ex4. Faça uma versão em C do código acima usando somente if-goto. Escreva, então, ao lado desta versão um código legível em C.

Answer

Versão if-goto:

int ex4() {
    unsigned short n; // variavel na pilha
    int ret;
    int i;
    int aux;
    scanf("%hu", &n);
    i=1;

    goto test;

    loop:
        ret = ret + i*4;
        i = i+1;       
    test:
        aux = n;
        if (aux > i) {
            goto loop;
        }
        return ret;
}

Versão C:

#include <stdio.h>

int ex4() {
    unsigned short n;

    scanf("%hu", &n);

    int res = 0;
    int i = 1;

    while (i < n) {
        res += (i*4);
        i++;
    }

    return res;
}

int main() {
    return 0;
}

Tip

Observe sempre as chamadas de variáveis globais e strings (relativos a %rip) e acessos à stack (relativos a %rsp).

Simulado de prova

Além dos exercícios de revisão feitos na aula, você encontrará no repositório da disciplina um arquivo simulado_ai.zip.

Na AI, vocês receberão um arquivo semelhante a este. No dia da prova, você terá que baixar o zip, descompactar, resolver os exercícios, compactar novamente e anexar no Blackboard.

Tip

Leia o README.md ou README.html para saber o que é esperado em cada questão!

Tip

Leia o README.md ou README.html para saber como você será avaliado!