2011-08-28 60 views
0

我有一个简单的高级汇编程序,我正在学习位移和旋转的来龙去脉。我有这个简单的程序,可以在单个字节中移位。为什么没有设置进位标志?

static 
var: int8 := 127; 

begin test1; 

stdout.put(var, nl); 
shl(1, var); 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 
end test1; 

由于字节设置为127,应该通过左移一次是01111111

当然,作为最后一位保留签约进位标志应提高?

然而,这并不是看起来会发生的事情,实际上所有的字节都会左移一次,因此字节现在是11111110或-2。

如果每次都发生这种情况,什么情况会导致进位标志置位?

平台是赢得7 64位

+0

可能重复的[关于组件CF(进位)和(溢出)标志(http://stackoverflow.com/questions/791991/ about-assembly-cfcarry-and-ofoverflow-flag) – Amber

+0

我认为“转移”的意图是 – WaelJ

+0

@paul,对不起,我已经改变了代码来反映我的问题。 –

回答

8

如前所述其他人则需要将127位乘以2位,以便进位标志实际设置。但是你说它仍然不起作用;这是我最好的猜测原因:

我不熟悉HLA及其库函数,但是,作为编写程序集时的一般规则,您应始终假定调用库函数可能会更改任意方式,除非有一些文件另有说明。许多指令可以更改标志,所以除非库函数显式保存了入口标志并在退出时恢复标志(例如通过将它们与pushf和指令一起保存在堆栈中),它们可以以任何状态结束。

在你的代码,您必须将shl和进位标志的测试之间的stdout.put库例程的调用:

shl(2, var); /* I'm assuming you've already changed 1 to 2 here */ 
stdout.put(var, nl); 
if (@C) then stdout.put("carry set"); endif; 

我猜stdout.put被清除标志。

因此,尝试后移把测试立即:

shl(2, var); 
if (@C) then stdout.put("carry set", nl); endif; 
stdout.put(var, nl); 
+0

是的,完美的,谢谢! –

0

看来你正在使用的移位指令是一个逻辑移位器,即它不会留下符号位不变。尝试(在x86指令SAR和SAR)寻找一个算术移位指令

+0

不,算术左移是sal,这个shl是非算术移位指令。 –

+0

@Jason Sill:固定。谢谢 – WaelJ

+0

@WaelJ:为什么我在手册中找不到任何'ras','las'说明? – phoxis

1

左(SAL)和换档逻辑左移位运算(SHL)指令执行 相同的操作;他们将目标操作数中的位移到左边(朝着更高有效位位置的 )。对于每个移位计数,该 目标操作数的最显著位将移入CF标志,最低显著位清零

移位算术右移(SAR)和转移逻辑右(SHR)指令将目标操作数的位 移到右侧(朝向较低有效位位置)。对于每个 移位计数,目标操作数的最低有效位移入CF 标志中,并且最高有效位根据指令 类型设置或清零。 SHR指令清除最重要的位(请参阅英特尔® 64和IA-32架构软件开发人员手册,第1卷中的图7-8)。 SAR 指令设置或清除最高有效位,以对应目标操作数中原始值的符号(最高位为 )。实际上,SAR 指令填充空位位置的移位值和未移位的符号 值

OF标志仅在1位移位时受影响。对于左移,如果结果的最高有效位与CF标志相同(即,原始操作数的前两位 相同),OF标志被设置为0;否则,它被设置为1.对于SAR指令,OF标志被清除所有1位移位。对于SHR指令,OF标志是 设置为原始操作数的最高有效位。

CF标志包含最后位的值移出所述目的地操作数的;对于SHL和SHR指令,其中的 未定义,其中计数大于或等于目标操作数的大小(以位为单位) 。 OF标志仅受1位移位的影响(参见上面的“说明”);否则,它是未定义的。根据结果​​设置SF,ZF和PF标志 。如果计数为0,则标志不受影响。对于非零计数,AF标志未定义。

UPDATE 这里是什么手册告诉。仅用于设置CF和换档操作循环体被示出:

IF instruction is SAL or SHL 
    THEN 
     CF ← MSB(DEST); 

    ELSE (* Instruction is SAR or SHR *) 
     CF ← LSB(DEST); 
FI; 
IF instruction is SAL or SHL 
    THEN 
     DEST ← DEST ∗ 2; 
    ELSE 
     IF instruction is SAR 
      THEN 
       DEST ← DEST/2; (* Signed divide, rounding toward negative infinity *) 
      ELSE (* Instruction is SHR *) 
       DEST ← DEST/2 ; (* Unsigned divide *) 
     FI; 
FI; 
tempCOUNT ← tempCOUNT – 1; 

根据上面DEST = 01111111SHL使得CF = MSB (DEST) = 0DEST = DEST * 2这是DEST = 127 * 2 = 254,其是二进制11111110和在2的补表示解释它是-2十进制。

来源:Intel 64 and IA32 Architectures Software Developer Manual Volume 2

+0

这并没有真正的帮助。从你粘贴的第一段(来源?),最重要的位应该已经移入CF标志。但是,显然这不会发生。 –

+0

在'01111111'的'var'结果中应用'shr'到'11111110'?所有的文字都是来源的副本,我已经在下面链接了。 – phoxis

+0

我应该注意我正在使用高级汇编语言,而不仅仅是汇编语言。所以进位标志不应该设置为127,但是-2是什么?如果这些位是11111110,那么由于MSB是1,所以进位标志是否应该设置?如果我更改上面的代码以将-2指定给var,则情况并非如此。无论我的操作是否MSB为1,都设置了进位位。 –

1

最显著位为0 - 如果你想获得一个1进位标志,那么就需要转移由2位向左,即

shl(2, var); // [X] 01111111 -> [1] 11111100 
+0

即使我左移2,得到-4,进位位未被设置。 –