簡體   English   中英

如何處理 C 中的負數?

[英]How do I deal with negative numbers in C?

我正在嘗試用 C 編寫一種非常基本的匯編語言。每條指令有 32 位,前 8 位是操作碼,接下來的 24 位包含一個立即值(如果指令帶有一個。否則它只是零)。 操作碼被定義為簡單的數字。 例如PUSHC被定義為1

現在我想測試操作碼和立即值是否可以正確分離。

我寫了以下定義:

#define SIGN_EXTEND(i) ((i) & 0x00800000 ? (i) | 0xFF000000 : (i))      // Handles negative Immediate Values (i)
#define IMMEDIATE(x) SIGN_EXTEND(x & 0x00FFFFFF)                        // Returns the Immediate Value of an instruction (x)
#define OPCODE(x) (x >> 24)                                             // Returns the Opcode of an instruction (x)
#define OP(o) ((o) << 24)                                               // An instruction with an Opcode (o)
#define OPI(o, i) (OP(o) | IMMEDIATE(i))                                // An instruction with an Opcode (o) and an Immediate Value (i)

在方法void runProg(uint32_t prog[]) {...}中,我按順序傳遞一個包含匯編程序指令的數組,以逗號分隔,如下所示:

uint32_t progTest[] = {OPI(PUSHC, 3), OPI(PUSHC, 4}, OP(ADD), OP(HALT)};
runProg(progTest);

這是runProg的作用:

void runProg(uint32_t prog[]) {
    int pc = -1;            // the program counter
    uint32_t instruction;

    do {
        pc++;
        instruction = prog[pc];
        printf("Command %d : 0x%08x -> Opcode [%d] Immediate [%d]\n",
               pc, instruction, OPCODE(instruction), IMMEDIATE(instruction));
    } while (prog[pc] != OP(HALT));

}

所以它以十六進制形式打印出完整的命令,然后是操作碼,然后是立即值。 這適用於我定義的所有指令。 上面的測試程序給出了這個 output:

Command 0 : 0x01000003 -> Opcode [1] Immediate [3]
Command 1 : 0x01000004 -> Opcode [1] Immediate [4]
Command 2 : 0x02000000 -> Opcode [2] Immediate [0]
Command 3 : 0x00000000 -> Opcode [0] Immediate [0]

現在問題來了:

命令PUSHC僅適用於正值。 將第一個PUSHC調用的立即值更改為-3會產生以下結果:

Command 0 : 0xfffffffd -> Opcode [255] Immediate [-3]
Command 1 : 0x01000004 -> Opcode [1] Immediate [4]
Command 2 : 0x02000000 -> Opcode [2] Immediate [0]
Command 3 : 0x00000000 -> Opcode [0] Immediate [0]

如您所見,立即值顯示正確,但命令缺少操作碼。

IMMEDIATE(x)的定義從

#define IMMEDIATE(x) SIGN_EXTEND(x & 0x00FFFFFF)

#define IMMEDIATE(x) (SIGN_EXTEND(x) & 0x00FFFFFF)

產生完全相反的結果,其中 Opcode 被正確分隔,但立即值是錯誤的:

Command 0 : 0x01fffffd -> Opcode [1] Immediate [16777213]
Command 1 : 0x01000004 -> Opcode [1] Immediate [4]
Command 2 : 0x02000000 -> Opcode [2] Immediate [0]
Command 3 : 0x00000000 -> Opcode [0] Immediate [0]

因此,我比較確定我對SIGN_EXTEND(i)的定義是有缺陷的。 但是,我似乎無法確定。

非常感謝有關如何解決此問題的任何想法!

0x01fffffd是正確的; 8位操作碼域包含0x01,24位立即數域包含0xfffffd,即-3的24位二進制補碼編碼。 編碼時,無需符號擴展; IMMEDIATE宏傳遞一個(大概)32 位二進制補碼值,它的工作只是將其減少到 24 位,而不是擴展它。 所以它只需要是#define IMMEDIATE(x) ((x) & 0xffffff) 當你想解釋立即字段時,比如打印,那么你需要從 24 位轉換為 32 位。為此,你需要一個不同的宏,就像你有不同的宏來編碼操作代碼( OPI )和解碼/提取/解釋操作碼( OPCODE )。

您可以使用此 function 解釋立即字段:

static int InterpretImmediate(unsigned x)
{
    //  Extract the low 24 bits.
    x &= (1u<<24) - 1;

    /*  Flip the sign bit.  If the sign bit is 0, this
        adds 2**23.  If the sign bit is 1, this subtracts 2**23.
    */
    x ^= 1u<<23;

    /*  Convert to int and subtract 2**23.  If the sign bit started as 0, this
        negates the 2**23 we added above.  If it started as 1, this results in
        a total subtraction of 2**24, which produces the two’s complement of a
        24-bit encoding.
    */
    return (int) x - (1u<<23);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM