construção do ambiente de laboratório csapp e lab1wp

1. Construção do ambiente

**

Primeiro de tudo, precisamos criar uma máquina virtual do ubantu. Especificamente, o Baidu
fará um bom trabalho na máquina virtual e começará a construir o ambiente. Clique com o botão direito do mouse para abrir o terminal e digite o seguinte comando

apt-get update    //更新apt软件源
apt-get install sudo   //安装sudo
sudo apt-get install build-essential  //安装c/c++编译环境
sudo apt-get install gcc-multilib  //补充gcc的完整环境(gcc-multilib)
sudo apt-get install gdb  //安装gdb
sudo apt-get install make  //安装make

Como fazer as perguntas e como verificar certo ou errado, digite as seguintes instruções (pegue a primeira pergunta bitXor como exemplo)

make btest
./btest -f bitXor
./btest -g //总览所有题的得分

insira a descrição da imagem aqui
Uma pontuação completa significa que você fez certo
**

Dois.lab1wp

regras int (traduzido pelo Baidu, deve ser capaz de entender)

Constantes inteiras de 0 a 255 (0xFF), inclusive.
Constantes grandes como 0xffffffff não são permitidas.
Você está expressamente proibido de:

1. Use qualquer construção de controle como if, do, while, for, switch, etc.

2. Defina ou use quaisquer macros.

3. Defina quaisquer funções adicionais neste arquivo.

4. Chame qualquer função.

5. Use quaisquer outras operações como &&, | |, -, ou, ? :

6. Use qualquer forma de fundição.

7. Use qualquer tipo de dados diferente de int. Isso significa que
matrizes, estruturas ou uniões não podem ser usadas.

1. joias

//1
/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */

O significado da pergunta é usar ~, & para obter XOR
~: para cada bit do binário, altere 1 para 0 e altere 0 para 1

Para x, y, só pode haver duas combinações &, x&y e ~x & ~y, se for ~x&y ou ~y&x, não funcionará, negue ambas ou use 4 aqui, 5 para tentar, 4&
5 =0100, ~4 & ~5=1010
Isso é para continuar tentando combinar, para encontrar a resposta

int bitXor(int x, int y) {
    
    
    return ~(x & y)&~(~x&~y);
}

2. tmin

/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */

O significado da questão é encontrar o valor mínimo do código de complemento de dois, 0x10000000 é o valor mínimo, mas você só pode inserir entre 0 e 255 (0xFF), então você precisa usar shift esquerdo <<, conforme a seguir:

int tmin(void) {
    
    
    return 1 << 31;
}

3.isTmax

//2
/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */

O significado da pergunta é que se o x aceito é o valor máximo em binário, ele retorna 1, caso contrário, é 0. O
valor máximo em binário é 0x7FFF FFFF. Supondo que seja x, então x+1 é 0x8000 0000. Em desta vez, XOR os dois para obter 0xFFFF FFFF, mais um '~', você obtém 0 e, em seguida, usa a negação lógica ao retornar. No entanto, 0xFFFF FFFF e seu +1 XOR também são 0xFFFF FFFF. Neste momento, conte o +1 duas vezes '!', que é 0. Combinado com a operação AND, a implementação específica é a seguinte
:

int isTmax(int x) {
    
    
    int r=x+1;
    r=~(x^r);
    return !(r^x) &!!(x+1);   
}

4.allOddBits

/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */

O significado da pergunta é retornar 1 quando todos os bits ímpares forem 1.
Apenas 0xAAAA AAAA e 0xFFFF FFFF satisfazem todos os dígitos ímpares de 1. Neste momento, XOR é usado para julgar. Primeiro,
suponha que x seja 0xAAAA AAAA. Para fazer um valor XOR 0xAAAA AAAA com x, de modo que seja depois de 0, use lógica NÃO para mudar para 1.
Se x for 0xFFFF FFFF, você precisa adicionar uma operação AND aqui para fazer primeiro mudar para 0xAAAA AAAA e depois XOR para obter 0.
Agora, outro problema é como dar 0xAAAA AAAA à variável To atribuir um valor, aqui precisamos usar a combinação de shift esquerdo lógico e XOR para obter
o específico da seguinte forma:

int allOddBits(int x) {
    
    
    int q1=0xaa;
    int q2=q1<<8;  //q2=aa00
    int q3=q2^q1;  //q3=aaaa
    int q4=q3<<16; //q4=aaaa0000
    int q=q3^q4;  // q=aaaaaaaa
    q1=q&x; 
    return !(q1^q);
}

5.negar

/* 
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */

O significado da pergunta é obter o valor oposto
. Isso ainda precisa ser usado ~. Para cada bit, 0 se torna 1, 1 se torna 0.
Tome x=0xFFFF FFFF por exemplo, ~x=0, 0+1=1 , e
então pegue x=0x8000 Para 0001, ~x+1=0x7FFF FFFD +1=0x7FFF FFFF
é o seguinte:

int negate(int x) {
    
    
  return ~x + 1;  
}

6. isAsciiDigit

/* 
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */

O significado da pergunta é que se 0x30 <= x <= 0x39, o retorno é 1,
ou seja, se x-0x30>=0&&x-0x39<=0 for retornado como 1,
aqui x-0x39>=0 deve ser alterado para x-0x3a<0 para uma boa representação, é claro, também pode ser 0x39-x>0
e, em seguida, combinado com lógica não '!' e operação OR,
como segue:

int isAsciiDigit(int x) {
    
    
      
      return !(((x+~0x30+1)>>31)|!((x+~0x3a+1)>>31));             
}

7. condicional

/* 
 * conditional - same as x ? y : z
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */

O significado da pergunta é perceber x?y:z, ou seja, se x é verdadeiro, então o valor é y, caso contrário, z primeiro
usa duas negações lógicas para mudar o valor diferente de zero para 1 e o valor para 0 ainda é 0.
Se x for verdadeiro, torna-se x=0xFFFF FFFF, o que é benéfico para a operação AND
. Se não for verdadeiro, use a inversão lógica para alterar x=0 para 0xFFFF FFFF
da seguinte maneira:

int conditional(int x, int y, int z) {
    
    
   x=!!x; //先将x化为0或1
   int a=(x<<31)>>31;
   return (a & y)+(~a&z);
}

8.éMenosOuIgual

/*

  • isLessOrEqual - se x <= y então retorne 1, senão retorne 0
  • Exemplo: isLessOrEqual(4,5) = 1.
  • Operações legais: ! ~ & ^ | + << >>
  • Operações máximas: 24
  • Classificação: 3
    */
    Significado do título: Se x<=y retorna 1, caso contrário, é 0.
    Primeiro, use XOR e negação lógica para julgar se x e y são iguais e, se forem iguais, é 1

Se eles não são iguais, então x é um número negativo, e quando y é um número positivo, ou seja, quando o bit de sinal de x é 1 e o bit de sinal de y é 0, podemos tentar fazê-lo retornar a 1 . Primeiro, deixe x e y deslocarem para a direita em 31 ao mesmo tempo
. , Neste momento, x é 0xFFFF FFFF, y é 0, use a negação lógica para fazer x 0 e, em seguida, use a operação OR para fazer com que x e y voltem para 0 e, finalmente,
use uma negação lógica para torná-lo 1. De fato, embora o método considerado considere apenas que x é um número negativo e y é um número positivo, ele também é aplicável quando y é um número negativo e x é um número positivo.

Em seguida, considere que quando os bits de sinal de x e y são consistentes, primeiro use XOR para determinar se os bits de sinal são consistentes e, em seguida, use apenas x+~y+1=xy para obter o número 0xFFFF FFFF e use duas negações lógicas para transformá-lo em 1 e, em seguida, dar as duas operações AND

Qualquer uma das três condições acima pode ser satisfeita
da seguinte forma:

int isLessOrEqual(int x, int y) {
    
    
    int equal= !(x^y);
     
    int xh=x>>31;
    int yh=y>>31;
    int wudi=!((!xh)|yh);

    int yf=~y+1;
    int same=!(xh^yh);
    int jian=!!((x+yf)>>31);
    return equal|wudi|(same&jian);	
}

9.logicalNeg

/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */

Significado da pergunta: Use os símbolos acima para realizar a negação lógica
para alterar o número que não é 0 para 0 e para alterar 0 para 1. Pense nisso, 0 e seu número oposto são 0 e, ao contrário, a soma dos números que não são 0 Seu sinal de número oposto deve ter um 1
ou operação para obter -1 e, finalmente, adicionar um 1 para satisfazer
o específico da seguinte forma:

int logicalNeg(int x) {
    
    
     int xfh=(~x+1)>>31;  
     int xh=x>>31; 
     return (xh | xfh)+1; 
}

10.howManyBits

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */

Objetivo do título: Para determinar quantos dígitos o número de entrada tem,
primeiro precisamos inverter o número negativo, e qualquer que seja o número positivo, é principalmente para a conveniência de julgar o número de dígitos
. precisa usar o método da dicotomia, primeiro determine se existem 16 dígitos
e, em caso afirmativo, julgue se existem 24 bits; caso contrário, julgue se existem 8 bits e, em seguida, julgue assim 8, 4, 2, 1, 0
Não vamos falar sobre isso aqui, basta colocar o código diretamente

int howManyBits(int x) {
    
    
   int sign = x >> 31;
   x = (~sign & x) | (sign & ~x); //取反
   int b16 = !!(x >> 16) << 4;//判断是否有16位
   x >>= b16;

   int b8 = !!(x >> 8) << 3; 
   x >>= b8;

  int b4 = !!(x >> 4) << 2;
  x >>= b4;

  int b2 = !!(x >> 2) << 1; 
  x >>= b2;

  int b1 = !!(x >> 1);
  x >>= b1;

  int b0 = x;
  return b16 + b8 + b4 + b2 + b1 + b0 + 1;//+1是因为就如果像0这样的数,判定的时候是有1位的
}

regra flutuante

As regras de codificação são menos rígidas. Você pode usar loops e

controle condicional. Você pode usar números inteiros e não assinados.

Números inteiros arbitrários e constantes sem sinal podem ser usados. Você pode usar qualquer aritmética,

Executa uma comparação OR lógica em dados inteiros ou não assinados.

Você está expressamente proibido de:

1. Defina ou use quaisquer macros.

2. Defina quaisquer funções adicionais neste arquivo.

3. Chame qualquer função.

4. Use qualquer forma de fundição.

5. Use qualquer tipo de dados, exceto int ou unsigned. significa você

Arrays, estruturas ou uniões não podem ser usadas.

6. Use qualquer tipo de dados, operação ou constante de ponto flutuante.

floatScale2

/*

*floatScale2-返回表达式2*f的等效位级别

*浮点参数f。

*参数和结果都作为无符号int传递,但是它们将被解释为单精度浮点值。

*当参数为NaN时,返回参数

*合法运算:任何整数/无符号运算,包括| |,&&&。如果,虽然

*最多操作符:30

*评级:4

*/

insira a descrição da imagem aqui
Esta imagem está um pouco confusa, por favor dê uma olhada em conjunto.
O primeiro bit é o bit de sinal, os 8 bits do meio são o expoente e os últimos 23 bits são a mantissa.
s é o bit de sinal, M é a mantissa , e E é o
número de ponto flutuante do expoente . Ele é dividido nessas quatro categorias. Os normalizados são os oito dígitos do meio!=0&!=255, e os últimos são arbitrários. Os não normalizados são os oito dígitos do meio são 0, e os últimos são qualquer
valor. Infinito significa que os oito dígitos do meio são 0xFF e os últimos 23 dígitos são 0. A diferença entre NaN e infinito é que os últimos 23 bits não são 0

Intenção do título: retornar o dobro do número passado.
O valor de retorno de infinito e NaN é sua própria
normalização, então deixe apenas seu código de ordem + 1. Se não for normalizado, deixe-o deslocar um bit para a esquerda (por exemplo, binário 10 turnos restantes é 100)

O código é implementado da seguinte forma:

unsigned floatScale2(unsigned uf) {
    
    
      unsigned exp=(uf&0x7f800000)>>23;
      unsigned sign=uf>>31&0x1;
      unsigned frac=uf&0x7FFFFF;
      unsigned res;
  
    	if(exp==0xff){
    
    
     	return uf;
   	}
  	else if(exp==0){
    
    
   	 frac<<=1;//
   	 res=(sign<<31)|(exp<<23)|frac;
 	 }
 	 else{
    
    
   	 exp++;
   	 res=(sign<<31)|(exp<<23)|frac;
 	 }
  return res;
}

floatFloat2Int

/*

*float2int-返回表达式(int)f的位级等效值

*对于浮点参数f。

*参数作为无符号int传递,但它将被解释为单精度浮点值。

*任何超出范围的东西(包括NaN和infinity)都应该返回

*0x80000000u。

*合法运算:任何整数/无符号运算,包括||,&&. also if, while

*最多符号位:30

*评级:4

*/

O significado da pergunta: converta o tipo de ponto flutuante uf no tipo int
Não mais. . .
Eu não entendo o que está acontecendo com 23 e 31. . .
apenas código movido

int e = ((uf & 0x7F800000) >> 23) - 0x7F;
    int f = ((uf & 0x007FFFFF) | 0x00800000);

    if (!(uf & 0x7FFFFFFF) || e < 0)
        return 0;
    if (e > 31)
        return 0x80000000;

    if (e > 23)
        f = f << (e - 23);
    else
        f = f >> (23 - e);

    if (!(uf >> 31))
        return f;
    else
        return ~f + 1;

floatPower2

/*

*floatPower2-返回与表达式2.0^x等效的位级别

*(2.0升为x的幂)用于任何32位整数x。

*返回的无符号值应具有相同的位

*表示为单精度浮点数2.0^x。

*如果结果太小,无法表示为denorm,则返回0. 如果太大,返回+INF。

*合法运算:任何整数/无符号运算,包括| |,&&&。如果,虽然

*最多:30

*评级:4

*/

fw continua ruim
e o código de manipulação é o seguinte:

if(x>127)//overflow
      return 0x7f800000;//+inf 符号位0 阶码全1 尾数全0
 
    //规格化的 [-126,127]
    if(x>=-126)
    {
    
    
      unsigned exp = x+127;//加上bias
      return exp<<23;//只需改变阶数
    }
 
    //非规格化的 [-149,-127]
    if(x>=-149)
      return 0x1<<(x+149);//只需改变尾数
 
    //x<-149 too small to be represented
    return 0;

Acho que você gosta

Origin blog.csdn.net/m0_51295934/article/details/123409878
Recomendado
Clasificación