-2

Cコードで16ビットから32ビットへの符号拡張を実装するにはどうすればよいですか?
ビット演算子を使用することになっています。足し算と引き算も必要です。誰かが私を正しい方向に向けることができますか? 私は最初の4つをやったが、残りは混乱している. forケースの 1 つで、どこかにループを組み込む必要があります。

算術演算子 ( +-/*)を使用することは許可されておらず、ifステートメントも使用できません。

現在編集中の switch ステートメントのコードは次のとおりです。

unsigned int csc333ALU(const unsigned int opcode,
               const unsigned int argument1,
               const unsigned int argument2) {
unsigned int result;

switch(opcode) {
  case(0x01): // result = NOT argument1
    result = ~(argument1);
    break;
  case(0x02): // result = argument 1 OR argument 2
    result = argument1 | argument2;
    break;
  case(0x03): // result = argument 1 AND argument 2
    result = argument1 & argument2;
    break;
  case(0x04): // result = argument 1 XOR argument 2
    result = argument1 ^ argument2;
    break;
  case(0x05): // result = 16 bit argument 1 sign extended to 32 bits
    result = 0x00000000;
    break;
  case(0x06): // result = argument1 + argument2
    result = 0x00000000;
    break;
  case(0x07): // result = -argument1. In two's complement, negate and add 1.
    result = 0x00000000;
    break;
  default:
    printf("Invalid opcode: %X\n", opcode);
    result = 0xFFFFFFFF;
  }
4

3 に答える 3

1

16 ビットの数値を 32 ビットに符号拡張するには、ビット 15 を上位ビットにコピーする必要があります。これを行う単純な方法は、ビット 15 をビット 16 にコピーし、次に 17、次に 18 というように 16 命令を使用することです。ただし、以前にコピーしたビットを使用し、次のように毎回コピーしたビット数を 2 倍にすることで、より効率的に行うことができます。

unsigned int ext = (argument1 & 0x8000U) << 1;
ext |= ext << 1;
ext |= ext << 2;
ext |= ext << 4;
ext |= ext << 8;
result = (argument1 & 0xffffU) | ext;

2 つの 32 ビット数値を「手動で」追加するには、ビット単位で簡単に行うことができます。

unsigned carry = 0;
result = 0;
for (int i = 0; i < 32; i++) {
    // Extract the ith bit from argument1 and argument 2.
    unsigned a1 = (argument1 >> i) & 1;
    unsigned a2 = (argument2 >> i) & 1;
    // The ith bit of result is set if 1 or 3 of a1, a2, carry is set.
    unsigned v = a1 ^ a2 ^ carry;
    result |= v << i;
    // The new carry is 1 if at least two of a1, a2, carry is set.
    carry = (a1 & a2) | (a1 & carry) | (a2 & carry);
}

減算は、ほぼ同じコードで機能します。2 の補数演算a - bと同じです。a + (~b+1)単純に 1 を追加することは許可されていないため、 の代わりに に初期化carryすることで同じことを達成できます。10

unsigned carry = 1;
result = 0;
for (int i = 0; i < 32; i++) {
    unsigned a1 = (argument1 >> i) & 1;
    unsigned a2 = (~argument2 >> i) & 1;
    unsigned v = a1 ^ a2 ^ carry;
    result |= v << i;
    carry = (a1 & a2) | (a1 & carry) | (a2 & carry);
}

否定を行わずに 2 の補数を見つけるには、同様のアイデアが適用されます。ビットごとに否定してから追加し1ます。追加1は を追加するより簡単なargument2ので、コードはそれに応じて簡単になります。

result = ~argument1;
unsigned carry = 1;
for (int i = 0; i < 32 && carry; i++) {
    carry &= (result >> i);
    result |= (1 << i);        
}
于 2015-03-30T02:32:50.323 に答える
0

short intからint....への符号拡張を取得するには

short int iShort = value;

int i = iShort;  // compiler automatically creates code that performs sign extension

注: からiiShort に移動すると、コンパイラ ワーリングが生成されます。

ただし、他の状況では...

比較する必要はありません&。単一ビットが 0 または 1 になるため、計算の一部を必ず int としてキャストしてください。

int i = (short int argument&0x8000)? (int)(0xFFFF000 | (int)argument) : (int)argument;
于 2015-03-25T04:36:41.047 に答える