在C中签名扩展一个数字

时间:2013-04-25 17:22:48

标签: c

我无法通过提取部分字符串来尝试对数字进行签名扩展。当它是负数时会出现问题,它会将数字包装到正数。 这是我的代码:

//  printf("add1 \n");
unsigned short r1 = (instruction>>6)&7;
signed short amount = (instruction& 31);   //right here! i am trying to get the last 5 bits and store it in a register but i can't figure out how to make it negative if it is negative
//  printf("\namount is %d \n", amount);
unsigned short dest = (instruction>>9)&7;
state->regs[dest] = state->regs[r1]+amount;
setCC(state,state->regs[r1]+amount);

5 个答案:

答案 0 :(得分:2)

使用位域:

union {
      int a;
      struct {
         int a:5;
         int b:3;
         unsigned int c:20;
      } b;
} u = 0xdeadbeef;

int b = u.b.b;  // should sign extend the 3-bit bitfield starting from bit 5

答案 1 :(得分:1)

对于位模式,使用十六进制常量而不是十进制通常更容易。

signed short amount = (instruction & 0x1F);

然后对符号进行符号扩展,检查符号位(假设此处的符号位是5个提取位中最左边的)。 如果已设置,则执行二进制反转并添加1. 取5位值的2的补码(反转并加1),然后取全宽结果的2的补码(反转并添加1)。

if (amount & 0x10)
    amount = ~(amount^0x1F + 1) + 1;

例如

             5-bit "bitfield"
             X XXXX
0000 0000 0001 1111
0000 0000 0000 0000 invert x ^ 0x1F (= 1 1111)
0000 0000 0000 0001 add 1
1111 1111 1111 1110 invert ~
1111 1111 1111 1111 add 1

0000 0000 0001 0000
0000 0000 0000 1111 invert x ^ 0x1F (= 1 1111)
0000 0000 0001 0000 add 1
1111 1111 1110 1111 invert ~
1111 1111 1111 0000 add 1

糟糕!更简单:

-(x^0x1F + 1)  Assuming the machine operates with 2's-complement

0000 0000 0001 0110
0000 0000 0000 1001 invert
0000 0000 0000 1010 add 1 (yielding the full-width absolute value)
1111 1111 1111 0101 negate

答案 2 :(得分:1)

以下是如何签名扩展5位二进制补码值而无需测试:

int amount = (instruction & 31) - ((instruction & 16) << 1);

更一般地说,字段宽度为n,非零且小于int中的位数,您可以写:

int amount = (instruction & ~(~1U << (n - 1) << 1)) -
             ((instruction & (1U << (n - 1)) << 1);

答案 3 :(得分:0)

您可以检查符号位并相应地修正结果:

int width_of_field = 5;
signed short amount = (instruction& 31);
if (amount & (1 << width_of_field >> 1)) // look at the sign bit
{
    amount -= 1 << width_of_field; // fix the result
}

或者,使用左移然后右移:

width_of_field = 5;
signed short amount = (instruction& 31);
// It is possible to omit the "& 31", because of the left shift below
amount <<= 16 - width_of_field;
amount >>= 16 - width_of_field;

注意:必须使用两个语句来避免促销对int(可能有32位)的影响。

答案 4 :(得分:0)

摘自Hacker's Delight 2-6。假设必须对5位数据进行符号扩展(符号位的值为16)。

最佳情况:如果高位全为零:

    <ns0:MainNode xmlns:ns0="http://test/system">
    <ParentTag>
        <tagRequest>
            <Data1>FirstName</Data1>
            <Data2>LastName</Data2>
            <Value1>50</Value1>
            <BooleanValue1>false</BooleanValue1>
            <Address>
                <StreetName>0000000</StreetName>
                <StreetNo>00000000000000</StreetNo>
            </Address>
        </tagRequest>
    </ParentTag>
    </ns0:MainNode>

下一个最佳情况(与OP的 <?xml version='1.0' ?> <xsl:stylesheet version="1.0" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> <xsl:template match="/"> <ns0:MainNode xmlns:ns0="http://test/system"> <xsl:copy-of select="soapenv:Envelope/soapenv:Body/*" /> </ns0:MainNode> </xsl:template> <xsl:template match="Street-No"> <xsl:element name= "StreetNo"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> </xsl:stylesheet> 一样):如果高位包含必须丢弃的数据:

(i ^ 16) - 16