我有一个简单的高级装配程序,我正在学习位移和旋转的细节。我有这个简单的程序可以在一个字节中移位这些位。
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 :(得分:8)
正如其他人已经指出的那样,你需要将127移位2位,以便实际设置进位标志。但是你说它仍然不起作用;这是我最好的猜测原因:
我不熟悉HLA及其库函数,但是,作为编写程序集时的一般规则,您应该始终假设调用库函数可能会以任意方式更改标志,除非有一些文档指出除此以外。许多指令可以更改标志,因此除非库函数明确保存条目上的标志并在退出时恢复它们(例如通过使用pushf
和popf
指令将它们保存在堆栈中),它们可能会结束在任何州。
在您的代码中,您可以在stdout.put
和进位标记测试之间调用shl
库例程:
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);
答案 1 :(得分:1)
移位算术左(SAL)和移位逻辑左(SHL)指令执行 同样的操作;他们将目标操作数中的位向左移动(朝向 更重要的位位置)。对于每个班次计数,最重要的一点 目标操作数移入CF标志,最低有效位清零
和
移位算术右(SAR)和移位逻辑右(SHR)指令移位这些位 右侧的目标操作数(朝向不太重要的位位置)对于每一个 移位计数,目标操作数的最低有效位被移入CF 标志,根据指令设置或清除最高有效位 类型。 SHR指令清除最重要的位(请参见英特尔®中的图7-8) 64和IA-32架构软件开发人员手册,第1卷);特区 指令设置或清除最重要的位以对应符号(大多数 目标操作数中原始值的有效位。实际上,SAR 指令用未移位的符号填充空位位置的移位值 值
OF标志仅在1位移位时受影响。对于左移,如果结果的最高有效位与CF标志相同(即前两位),则OF标志设置为0 原来的操作数是一样的);否则,设置为1.对于SAR指令 - 对于所有1位移位,OF标志清零。对于SHR指令,OF标志是 设置为原始操作数的最高位。
也
CF标志包含从目标操作数移出的最后一位的值;它 对于计数大于或等于的SHL和SHR指令,未定义 目标操作数的大小(以位为单位)。 OF标志仅受1位移位的影响(参见上面的“描述”);否则,它是未定义的。 SF,ZF和PF标志 根据结果设置。如果计数为0,则标志不受影响。对于非 零计数,AF标志未定义。
<强>更新强>
这是手册所说的内容。仅显示用于设置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 = 01111111
和SHL
使CF = MSB (DEST) = 0
和DEST = DEST * 2
成为DEST = 127 * 2 = 254
,其中11111110
为二进制和2的赞美表示解释是十进制的-2
。
来源:Intel 64 and IA32 Architectures Software Developer Manual Volume 2
答案 2 :(得分:1)
最重要的位是0 - 如果你想让1进入进位标志,则需要向左移2位,即
shl(2, var); // [X] 01111111 -> [1] 11111100
答案 3 :(得分:0)
您正在使用的移位指令似乎是一个逻辑位移位器,即它不会保留符号位。尝试寻找算术移位指令(x86指令中的sar和sar)