0% acharam este documento útil (0 voto)
2 visualizações3 páginas

(8/20 Valores) Grupo I: Departamento de Engenharia Informática Licenciatura em Engenharia Informática

O documento é uma folha de consulta para um exame de Arquitetura de Computadores na Licenciatura em Engenharia Informática. Ele contém instruções sobre a anulação da prova em caso de infração, além de questões que abordam conceitos de programação em C e assembly, incluindo manipulação de memória e operações lógicas. O exame é dividido em grupos com questões de verdadeiro ou falso, desenvolvimento de funções e análise de código.

Enviado por

augusto
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
2 visualizações3 páginas

(8/20 Valores) Grupo I: Departamento de Engenharia Informática Licenciatura em Engenharia Informática

O documento é uma folha de consulta para um exame de Arquitetura de Computadores na Licenciatura em Engenharia Informática. Ele contém instruções sobre a anulação da prova em caso de infração, além de questões que abordam conceitos de programação em C e assembly, incluindo manipulação de memória e operações lógicas. O exame é dividido em grupos com questões de verdadeiro ou falso, desenvolvimento de funções e análise de código.

Enviado por

augusto
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

folha de consulta

Departamento de Engenharia Informática


ˆ Autorizada apenas a consulta da
ocial.
Licenciatura em Engenharia Informática ˆ
ˆ
A infração implica, no mínimo, a ANULAÇÃO da prova.
Quando omissa a arquitetura, considere Linux/x86-64.
Responda aos grupos II, III, IV e V em folhas A4
Arquitetura de Computadores (ARQCP) ˆ
separadas.
2023/24  Caso não responda a algum grupo tem de
entregar uma folha relativa a esse grupo.

Versão: A Exame: Época Nota mínima: 7.5/20 valores Duração: 120 minutos
recurso/melhoria
Número: Nome:

(8/20 valores) Grupo I


Assinale no seguinte grupo se as frases são verdadeiras ou falsas (uma resposta errada desconta 50%
de uma correta).
V F
No processo de compilação usado pelo GNU Compiler Collection (GCC) o Assembler converte o código C em
1
código assembly.
Em C, o operador lógico || (OR) termina a avaliação da expressão se encontrar uma condição que seja
2
avaliada como verdade
3 Em C, a seguinte instrução n = (n  d)|(n  (32 - d); permite rodar para a esquerda d bits em n.
Em C, quando a soma de duas variáveis unsigned char u,v; é igual ou superior a 28 o valor obtido é
4
equivalente a u + v - 28 .
Em C, considere int x = 0xA0B0F0CC;. À variável short y = (short)x; é atribuído um valor
5
interpretado como negativo
6 Em C, a seguinte instrução if(x && 0x01) permite vericar se x é par ou ímpar.
7 Em C, a seguinte instrução num = 1 permite dividir o valor de num por 1.
Em C, considere char * str = (char *) malloc (40); int *c = (int *)(str + 4);. Assuma
8
que o valor de str é 0x1000, logo o valor c é 0x1004.
Em C, considere short v[] = {0x7ABB,0x5CDD}; int x = *(int*)v;. Então, na variável x ca
9
armazenado o valor 0x7ABB5CDD
10 Em C, considere char * str = malloc(strlen("arqcp")+1). A variável str é alocada na heap.
Em C, considere unsigned char x = -1; short y = 10; short z = x + y;. À variável z é
11
atribuído o valor 9.
Em C, a possibilidade de existirem várias referências para a mesma posição de memória diculta as
12
otimizações efetuadas pelo compilador
Em x86-64, reservar 8 bytes para variáveis locais de uma função pode ser conseguido através de addq $8,
13
%rsp.
Em x86-64, imediatamente após o prólogo de uma função, o valor anterior de %rbp pode ser obtido através
14
de (%rsp).
Em x86-64, a stack é sempre usada na gestão da invocação de funções, independentemente do número dos
15
seus parâmetros.
16 Em x86-64, cada opcode representa uma instrução do processador.
17 Em x86-64, a cada label é atribuído um endereço de memória.
18 Em x86-64, as diretivas (iniciadas por .) são instruções para o processador.
19 Em x86-64, o registo %rip é manipulado (alterado) de forma explícita.
20 Em x86-64, a cache hit acontece quando a variável requerida pelo processador está na memória cache.

1/ 3
(3/20 valores) Grupo II
Responda numa folha A4 separada, devidamente identicada com o número e nome do aluno e versão
do exame, que deve assinar e entregar (mesmo que não responda) no nal do exame.
1. (1v) Considere a seguinte código:
1 #include <stdio.h>
2 void func1(unsigned char *n1, unsigned char *n2){
3 *n1 = *n1 + *n2;
4 *n2 = *n1 - *n2;
5 *n1 = *n1 - *n2;
6 }
7 void func2(unsigned char *n1, unsigned char *n2){
8 *n1 = *n1 ^ *n2;
9 *n2 = *n1 ^ *n2;
10 *n1 = *n1 ^ *n2;
11 }
12 int main(){
13 unsigned char n1 = 0x5, n2 = 0x7;
14 func1(&n1, &n2);
15 printf("n1: %d \t n2: %d\n", (int) n1, (int) n2);
16 func2(&n1, &n2);
17 printf("n1: %d \t n2: %d\n", (int) n1, (int) n2);
18 return 0;
19 }

Indique o que vai aparecer na consola.

2. (2v) Usando aritmética de apontadores, desenvolva em C a função void invert_bytes(int * arr, int
len) que recebe o endereço de um array, arr e o número de elementos nesse array, len. A função deve inverter
os bytes de cada posição do array da seguinte forma, o primeiro byte passa a ser o último, o segundo, o penúltimo.
1 int vec[] = {0x00CDABCD,0x00AABCDE,0x6677CBEF};
2 invert_bytes(vec,3);
3 //vec [0] = 0xCDABCD00
4 //vec [1] = 0xDEBCAA00
5 //vec [2] = 0xEFCB7766

(3/20 valores) Grupo III


Responda numa folha A4 separada, devidamente identicada com o número e nome do aluno e versão
do exame, que deve assinar e entregar (mesmo que não responda) no nal do exame.
1. (3v) Implemente em
assembly a seguinte função: unsigned char is_greater(unsigned char * a,
unsigned char * b). A função recebe dois endereços do tipo unsigned char e retorna o maior valor. Por
exemplo:
1 unsigned char a = 0x10;
2 unsigned char b = 0x20;
3 unsigned char c = is_greater(&a,&b);
4 printf ("%#2x\n",c); // 0x20

(3/20 valores) Grupo IV


Responda numa folha A4 separada, devidamente identicada com o número e nome do aluno e versão
do exame, que deve assinar e entregar (mesmo que não responda) no nal do exame.
Considere o seguinte excerto de código que dene dois tipos de dados, student_t e class_t. Assuma a existência
de um array, students, com todos os estudantes do sistema e a função void add_student_to_class(class_t
* c, student_t * s) que permite adicionar (alocando a memória necessária) um apontador de student_t a
um registo do tipo class_t.
1 #define CLASSES_LEN 50
2 typedef struct {
3 unsigned short number;
4 char name [80];
5 }student_t;
6
7 typedef struct {
8 char designation [20];
9 student_t ** students;

2/ 3
10 unsigned short n_students;
11 }class_t;
12
13 void add_student_to_class(class_t * c, student_t * s){
14 c->n_students++;
15 if(c->n_students == 1){
16 c->students = (student_t **) malloc (sizeof (student_t *));
17 }else{
18 c->students = (student_t **) realloc (c->students, sizeof (student_t *) * c->n_students);
19 }
20 c->students[c->n_students - 1] = s;
21 }
22
23 int main(){
24 student_t students [] = {{1,"Manuel Ferreira"},{2,"Maria Joaquina"}, .....};
25 class_t* classes = (class_t *) calloc (CLASSES_LEN, sizeof(class_t));
26 .....
27 add_student_to_class(&classes[0], &students[0]);
28 add_student_to_class(&classes[1], &students[2]);
29 .....
30 //Libertar a memória
31
32 return 0;
33 }

A gura seguinte apresenta um esquema da relação entre os dois tipo de dados.

1. (3v) Assumindo que a função void add_student_to_class(class_t * c, student_t * s) é in-


vocada várias vezes na execução do programa, escreva o código na função main (a partir do comentário
//Libertar a memória) que permita libertar a memória alocada na execução do programa .

(3/20 valores) Grupo V


Responda numa folha A4 separada, devidamente identicada com o número e nome do aluno e versão
do exame, que deve assinar e entregar no nal do exame.
1. (3v) Considere o seguinte código e analise:

1 void func1(int *a, int *b){ 1 void func2(int *a, int *b){
2 *a += *b; 2 *a += 2 * (*b);
3 *a += *b; 3 }
4 } 4 int main(){
5 int main(){ 5
6 int a = 5; 6 int a = 5;
7 int b = 10; 7 int b = 10;
8 func1(&a,&b); 8 func2(&a,&b);
9 printf("%d\n", a); //25 9 printf("%d\n", a); //25
10 } 10 }

Considere, também, a seguinte armação: As funções void func1(int *a, int *b) e void func2(int
*a, int *b) são equivalentes, isto é, recebendo os mesmos dados (através dos parâmetros) produzem o mesmo
resultado. Neste caso em concreto as funções recebem dois endereços de variáveis do tipo int, a e b e o resultado
que ca armazenado em a é 25, em ambos os casos.
Mostre que esta armação é falsa, isto é, passando os mesmos parâmetros às duas funções (func1 e func2),
estas produzem resultados diferentes. Para tal reescreva somente as funções main.

3/ 3

Você também pode gostar