我正在学习嵌入式系统类简介。在我阅读时,我遇到了一个关于进位和溢出位实现的有趣问题。我知道什么是进位和溢出位,但我想不出有人会使用进位的情况。我认为的一个原因是调整记忆。有人可以解释这个问题吗?
谢谢!
答案 0 :(得分:8)
进位标志对于有效地对比处理器的累加器或寄存器更宽的数据执行算术和逻辑运算非常有用。这可能不是现代64位处理器的问题,但早期的微处理器和一些当前的微控制器可能仍然只有8位或16位累加器。进位位允许使用单个累加器对任何多字长度进行加/减和移位/旋转。除了基本加,减,移位和旋转指令(开始对多字数据进行操作)之外,还有随身携带,减借,随携带移位和随身携带指令(对后续单词进行操作)。并且为了促进这样的代码序列,INC reg
和DEC reg
指令(用于指针和循环计数器修改)不会修改(并因此保留)进位标志,即使它们是算术指令。
某些微控制器(例如Intel 8051)也将进位标志用作其单位端口I / O操作的读取目标或写入源。
在各种算术和逻辑运算上设置或清除进位和溢出标志(以及可能的一些其他标志,例如半进位,符号或零标志,具体取决于处理器架构)。应该查询处理器的指令集,了解存在哪些标志以及通过指令修改它们的条件。
答案 1 :(得分:5)
在机器指令中使用进位来测试无符号变量的less_than / greater_than条件,或循环终止条件,因为从0减去1会导致设置进位。
同样在汇编语言中,可以使用诸如加法之类的算术运算来轻松实现任意精度算术。
程序员在高级语言中通常不会看到进位。
溢出位很少使用 - 但正如语义所示,它可以并且应该由科学算法使用,其正确性必须在指定的有符号整数范围内得到保证。 add reg1, reg2; JO exception_handler
允许有效测试,如果处理有符号整数的算法产生正确的结果。同样适用于减法和整数乘法(IMUL),但不适用于整数除法,之后所有(算术)标志都是未定义的。
答案 2 :(得分:2)
这是一个使用进位标志的代码的简单示例:
int main (void)
{
unsigned int smallnum;
unsigned int largenum;
unsigned int temp_num;
printf("Enter a number: ");
scanf("%d", &smallnum);
printf("Enter a bigger number: ");
scanf("%d", &largenum);
temp_num = smallnum - largenum;
if (smallnum < largenum)
{
printf("Carry Flag SET!");
}
else
{
printf("Carry Flag CLEAR!");
}
return(EXIT_SUCCESS);
}
如果我们查看列表文件,我们会看到以下内容:
48:carry.c **** if (smallnum < largenum)
82 .loc 1 48 0
83 0090 8B542418 movl 24(%esp), %edx
84 0094 8B442414 movl 20(%esp), %eax
85 0098 39C2 cmpl %eax, %edx
86 009a 730E jae L2
因此if
语句被编译为两个操作数的比较,后跟jae
或“如果高于或等于跳跃”。 jae
命令中使用的测试是检查进位标志是否等于0
。请参阅this reference以查看哪些标志会针对哪些条件跳转进行测试。
当您编写代码时,生成列表文件并查看所有条件跳转。他们中的很多人正在测试检查进位旗的状态。