x86组件rcl al,1在al等于零时未清除进位标志

时间:2019-10-01 12:29:28

标签: assembly x86

标题概括起来。

如果在调用rcl指令且al为零时预先设置了进位标志,则最高位(0)不会移入进位。

以下代码演示:

mov al,0
stc
setc byte ptr [before]
rcl al,1 ; rotate left one bit through carry flag (multiply by 2 once)
setc byte ptr [after]

所以输出:

before = 01
after = 01

未清除进位标志,这与预期的一样。阅读英特尔手册:

The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation; they shift the
bits in the destination operand to the left (toward more significant bit locations). For each shift count, the most
significant bit of the destination operand is shifted into the CF flag, and the least significant bit is cleared (see
Figure 7-7 in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1).

在我看来,如果源值为零,那么什么也不做,这是不正确的!

1 个答案:

答案 0 :(得分:0)

我的问题的明显原因(有3个)是C优化器剪切代码,因为它不知道汇编代码对某些变量有任何影响。

(我的代码示例涉及6809/6309 CPU仿真器)

我将总结三个问题。

  1. rcl汇编指令似乎未设置进位标志。

    (本文中记录)

  2. 通过优化编译C代码时,汇编代码的运行速度将降低100-1000倍。

    (不可能的示例)

  3. 某些代码需要混淆才能使代码完全正常工作。

以下代码:

static void(*JmpVec1[256])(void) = { ... };
...
unsigned char memByte = MemRead8(PC_REG++);
JmpVec1[memByte](); // Execute instruction pointed to by byte @ PC_REG
CycleCounter += instcycl1[memByte]; // Add instruction cycles

仅在使用以下代码时有效:

static void(*JmpVec1[256])(void) = { ... };
...
unsigned char memByte = MemRead8(PC_REG++);
if (memByte == 0x34) // Just doesn't like instruction 0x34 Pushs register_list
{
    JmpVec1[memByte](); // Execute instruction pointed to by PC_REG
}
else
{
    JmpVec1[memByte](); // Execute instruction pointed to by PC_REG
}
CycleCounter += instcycl1[memByte]; // Add instruction cycles

由于C代码不知道437条仿真指令中的任何指令在做什么,或者这些指令产生什么影响,为什么选择0x34指令来停止工作是一个谜。

解决问题并允许我删除混淆的代码并允许我重新启用C优化的原因是,使CycleCounter(int)变量易失。

解决了我所有的问题!

这个问题更加复杂,因为vscode中没有反汇编支持,这使得调试汇编例程非常困难。

如果有人在Linux上使用良好的C /汇编IDE,请发表评论。