只是在寻找其他东西时遇到了这个问题,可能有点晚了,但也许它对其他人有用。AFAIAC 所有的 C 程序员都应该从编写汇编程序开始。
无论如何,扩展符号比提案容易得多。只需确保您使用有符号变量,然后使用 2 个班次即可。
long value; // 32 bit storage
value=0xffff; // 16 bit 2's complement -1, value is now 0x0000ffff
value = ((value << 16) >> 16); // value is now 0xffffffff
如果变量是有符号的,则 C 编译器将 >> 转换为保留符号的算术右移。此行为与平台无关。
因此,假设值以 0x1ff 开头,那么我们有,<< 16 将 SL(左移)该值,因此 instr 现在是 0xff80,然后 >> 16 将 ASR 值因此 instr 现在是 0xffff。
如果您真的想享受宏的乐趣,请尝试这样的方法(GCC 中的语法在 MSVC 中没有尝试过)。
#include <stdio.h>
#define INT8 signed char
#define INT16 signed short
#define INT32 signed long
#define INT64 signed long long
#define SIGN_EXTEND(to, from, value) ((INT##to)((INT##to)(((INT##to)value) << (to - from)) >> (to - from)))
int main(int argc, char *argv[], char *envp[])
{
INT16 value16 = 0x10f;
INT32 value32 = 0x10f;
printf("SIGN_EXTEND(8,3,6)=%i\n", SIGN_EXTEND(8,3,6));
printf("LITERAL SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,0x10f));
printf("16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value16));
printf("32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value32));
return 0;
}
这会产生以下输出:
SIGN_EXTEND(8,3,6)=-2
LITERAL SIGN_EXTEND(16,9,0x10f)=-241
16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241
32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241