R..*_*R.. 14
sbb %eax,%eax如果进位标志设置,则将-1存储在eax中;如果清除则将0存储在eax中.没有必要预先将eax清除为0; 从中减去eax会为你做这件事.这种技术非常强大,因为您可以将结果用作位掩码来修改计算结果,而不是使用条件跳转.
您应该知道,只有通过内联asm块内部执行的算术设置才能测试进位标志.您无法测试在C代码中执行的计算的进位,因为编译器可以通过各种方式优化/重新排序会破坏进位标志的内容.
Nic*_*kis 10
使用条件跳转jc(如果进位则跳转)或jnc(如果不进位则跳转).
或者你可以存储进位标志,
;; Intel syntax
mov eax, 0
adc eax, 0 ; add with carry
Run Code Online (Sandbox Code Playgroud)
然而,x86汇编程序专用快速 ALU标志测试指令名为SETcc,其中cc是期望的ALU标志.所以你可以写:
setc AL //will set AL register to 1 or clear to 0 depend on carry flag
or
setc byte ptr [edx] //will set memory byte on location edx depend on carry flag
or even
setc byte ptr [CarryFlagTestByte] //will set memory variable on location CarryFlagTestByte depend on carry flag
Run Code Online (Sandbox Code Playgroud)
使用SETcc指令可以测试进位,零,符号,溢出或奇偶校验等标志,一些SETcc指令允许一次测试两个标志.
编辑: 在德尔福提出增加简单的测试,消失约任期疑问快
procedure TfrmTest.ButtonTestClick(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
mov al, 0
adc al, 0
loop @repeat
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
mov ecx, 1000000
@repeat:
setc al
setc al
setc al
setc al
loop @repeat
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii));
end;
Run Code Online (Sandbox Code Playgroud)
使用指令setc的循环(1M迭代)比使用adc instriuction的循环快5倍以上.
编辑:添加第二个测试,其中存储在寄存器CL中的寄存器AL中的测试结果是更现实的情况.
procedure TfrmTestOtlContainers.Button1Click(Sender: TObject);
function GetCPUTimeStamp: int64;
asm
rdtsc
end;
var
ii, i: int64;
begin
i := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
shl edx, 1
mov al, 0
adc al, 0
add cl, al
end;
i := GetCPUTimeStamp - i;
ii := GetCPUTimeStamp;
asm
xor ecx, ecx
mov edx, $AAAAAAAA
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
shl edx, 1
setc al
add cl, al
end;
ii := GetCPUTimeStamp - ii;
caption := IntToStr(i) + ' ' + IntToStr(ii);
end;
Run Code Online (Sandbox Code Playgroud)
使用SETcc指令的Rutine部分仍然更快,约20%.