编译器如何判断指令的操作数是有符号还是无符号,然后相应地设置条件代码寄存器

时间:2013-07-02 09:51:38

标签: assembly x86

例如,对于以下C表达式,

int x =-1; 
unsigned y = 1; 
if(x>y) 
x+=y;

在编译时,程序集版本可以如下所示,

(假设x在%eax中,y在%edx中)

mov $-1 %eax
mov $1 %edx
mov %eax %edp
add %edx %edp
cmp %eax %edx
cmovg %edp %eax 

当基于〜(SF ^ OF)&amp; ~ZF的评估执行cmovg时,当CPU执行指令cmp%eax%edx时,CF也会被设置吗?注意,二进制形式负数-1与2 <&lt; 32-1。

相同

2 个答案:

答案 0 :(得分:0)

它从变量的类型中提取此类信息。编译器在语义分析阶段执行此操作,它将语义信息添加到解析树并构建符号表。还有一些information。理解编译器的好书是this一个

答案 1 :(得分:0)

你的意思是问“ cpu 如何判断操作数是否已签名”?因为这就是你的问题。答案是:它没有。值既没有签名也没有真正的无符号,它们只是“一堆”。指令可以有有符号或无符号的变体,例如分支(但不是比较),除法,右移和长乘法。加法,减法(和比较,它只是影响标志的减法)和短乘法(你没有得到额外的上半部分)没有签名和无符号版本,但是一个版本对两者都是正确的。结果不受签名的影响。

对于那些结果不受签名影响的指令,标志有时是。无论哪种方式,ZF和SF显然是相同的,但是当溢出时,签名显然很重要。但由于OF和CF是单独的标志,因此可以设置不同的值。

例如,mov eax, -2 \ add eax, eax设置CF因为有无符号溢出,但它没有设置OF,因为没有签名溢出。你可以把它解释为没有溢出的带符号的加法,或者作为无符号的加法溢出(或者甚至两者都有,但这几乎从来没用过),但唯一的区别在于你关心的标志

编译器显然知道应该签名什么以及应该是无符号的,因此可以在sarshr(右移)和idiv和{之间进行选择。 {1}}(对于除法),它为divcmovcc选择了CC。