这是我处理四个 16 位无符号整数输入数字之间的最大数字(80x86+ 处理器兼容)的第一个解决方案:
Procedure Max4; Assembler;
{ Input: AX, BX, CX, DX
Output: AX= MAX(AX,BX,CX,DX).
Temp: DI}
Asm
{ Input: AX, BX
Output: AX= MAX(AX,BX).
Temp: DI}
Sub AX,BX
CmC
SbB DI,DI
And AX,DI
Add AX,BX
{ Input: CX, DX
Output: CX= MAX(CX,DX).
Temp: DI}
Sub CX,DX
CmC
SbB DI,DI
And CX,DI
Add CX,DX
{ Input: AX, CX
Output: AX= MAX(AX,CX).
Temp: DI}
Sub AX,CX
CmC
SbB DI,DI
And AX,DI
Add AX,CX
End;
我的过程 Max4(),相当于 AX=Max4(AX,BX,CX,DX),有效
非常适合 AX=Max(AX,BX) 子例程
返回两个数字之间的最大值
并且使用了三次:
AX=Max(Max(AX,BX),Max(CX,DX))
AX=Max(AX,BX) 子例程工作如下:
1) Diff=AX-BX.
2) If Diff>=0 then AX is the greatest number,
Output= Diff+BX= AX-BX+BX= AX.
3) If Diff<0 then BX is the greatest number,
must set Diff to 0,
Output= Diff+BX= 0+BX= BX.
在大会中:
{ Input: AX, BX
Output: AX= MAX(AX,BX).
Temp: DI}
Sub AX,BX
{Diff= AX-BX}
CmC
{If Diff>=0 -> FCarry=1 else FCarry=0}
SbB DI,DI
{If Diff>=0 -> DI=DI-DI-1==-1 else DI=DI-DI-0==0}
And AX,DI
{If Diff>=0 -> Diff=(Diff & -1)==Diff else Diff=(Diff & 0)==0}
Add AX,BX
{AX= Diff+BX}
但此解决方案仅适用于无符号 16 位数字,并且仅处理一个最大数字(不要进行乘法运算)。
下一个解决方案可以在 80x86+ 处理器上正常工作 (适用于有符号整数;处理两个最大的数字):
Function Max42R(A,B,C,D:Integer):LongInt; Assembler;
Asm
Mov AX,A
Mov BX,B
Mov CX,C
Mov DX,D
{1ø swap (when needed), 1ø scan}
Cmp AX,BX
JLE @01
XChg AX,BX
{2ø swap (when needed), 1ø scan}
@01:Cmp BX,CX
JLE @02
XChg BX,CX
{3ø swap (when needed), 1ø scan}
@02:Cmp CX,DX
JLE @03
XChg CX,DX
{1ø swap (when needed), 2ø scan}
@03:Cmp AX,BX
JLE @04
XChg AX,BX
{2ø swap (when needed), 2ø scan}
@04:Cmp BX,CX
JLE @05
XChg BX,CX
{DX is the first greatest number;
CX is the second greatest number}
@05:Mov AX,DX
Mul CX
End;
它是冒泡排序算法的变体。
在冒泡排序中,你必须比较数组中每一对相邻的数字
如果第一个大于第二个,则交换它们;如果发生交换,则重复数组扫描,直到对数组进行排序。
但在第一次扫描后,数组的最后一个值总是最大的数。
假设四个输入值是在一个虚拟数组中,我只在需要时交换前三对寄存器,以获得第一大价值,
那是在最后一个寄存器中。之后,我交换前两对寄存器,仅在需要时,得到第二大值,即倒数第二个
注册。
Max4()程序可以在80386+处理器上编写如下(支持32位有符号整数;处理一个最大的数) :
Function Max4I(A,B,C,D:Integer):Integer; Assembler;
{ Input: EAX, EBX, ESI, EDI
Output: EAX= MAX(EAX,EBX,ESI,EDI).
Temp: CX.
EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push EBX
Push EDI
Push ESI
{------------------------}
Mov EAX,A
Mov EBX,B
Mov ESI,C
Mov EDI,D
{ Input: EAX, EBX
Output: EAX= MAX(EAX,EBX).
Temp: ECX}
Sub EAX,EBX
Mov ECX,0
SetL CL
Dec ECX
And EAX,ECX
Add EAX,EBX
{ Input: EAX, ESI
Output: EAX= MAX(EAX,ESI).
Temp: ECX}
Sub EAX,ESI
Mov ECX,0
SetL CL
Dec ECX
And EAX,ECX
Add EAX,ESI
{ Input: EAX, EDI
Output: EAX= MAX(EAX,EDI).
Temp: ECX}
Sub EAX,EDI
Mov ECX,0
SetL CL
Dec ECX
And EAX,ECX
Add EAX,EDI
{------------------------}
Pop ESI
Pop EDI
Pop EBX
End;
终于得到了两个最大的最终解决方案
四个 32 位有符号整数之间的数字(80386+ 处理器)。
它作为 Max42R() 函数工作:
Function Max42(A,B,C,D:Integer):Integer; Assembler;
{ Input: EAX, EBX, ESI, EDI
Output: EDI= 1° MAX(EAX,EBX,ESI,EDI).
ESI= 2° MAX(EAX,EBX,ESI,EDI).
Temp: ECX, EDX.
EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push EBX
Push EDI
Push ESI
Mov EAX,A
Mov EBX,B
Mov ESI,C
Mov EDI,D
{ Input: EAX, EBX
Output: EAX= MIN(EAX,EBX).
EBX= MAX(EAX,EBX).
Temp: ECX, EDX}
Sub EAX,EBX
Mov EDX,EAX
Mov ECX,0
SetGE CL
Dec ECX
And EAX,ECX
Add EAX,EBX
Not ECX
And EDX,ECX
Add EBX,EDX
{ Input: EBX, ESI
Output: EBX= MIN(EBX,ESI).
ESI= MAX(EBX,ESI).
Temp: ECX, EDX}
Sub EBX,ESI
Mov EDX,EBX
Mov ECX,0
SetGE CL
Dec ECX
And EBX,ECX
Add EBX,ESI
Not ECX
And EDX,ECX
Add ESI,EDX
{ Input: ESI, EDI
Output: ESI= MIN(ESI,EDI).
EDI= MAX(ESI,EDI).
Temp: ECX, EDX}
Sub ESI,EDI
Mov EDX,ESI
Mov ECX,0
SetGE CL
Dec ECX
And ESI,ECX
Add ESI,EDI
Not ECX
And EDX,ECX
Add EDI,EDX
{ Input: EAX, EBX
Output: EAX= MIN(EAX,EBX).
EBX= MAX(EAX,EBX).
Temp: ECX, EDX}
Sub EAX,EBX
Mov EDX,EAX
Mov ECX,0
SetGE CL
Dec ECX
And EAX,ECX
Add EAX,EBX
Not ECX
And EDX,ECX
Add EBX,EDX
{ Input: EBX, ESI
Output: EBX= MIN(EBX,ESI).
ESI= MAX(EBX,ESI).
Temp: ECX, EDX}
Sub EBX,ESI
Mov EDX,EBX
Mov ECX,0
SetGE CL
Dec ECX
And EBX,ECX
Add EBX,ESI
Not ECX
And EDX,ECX
Add ESI,EDX
{EDI contain the first maximum number;
ESI contain the second maximum number}
Mov EAX,EDI
{------------------------}
Pop ESI
Pop EDI
Pop EBX
End;
如何仅在第一个大于第二个时交换两个寄存器?
这是代码(在80386+上):
{ Input: EAX, EBX
Output: EAX= MIN(EAX,EBX).
EBX= MAX(EAX,EBX).
Temp: ECX, EDX}
Sub EAX,EBX (* Diff= EAX-EBX; set Overflow flag and Sign flag *)
Mov EDX,EAX (* EDX= Diff; flags not altered *)
Mov ECX,0 (* ECX= 0; flags not altered *)
SetGE CL (* If Sign flag == Overflow flag ECX= 1 else ECX=0 *)
Dec ECX (* If Diff>=0, ECX=0 else ECX=-1 *)
And EAX,ECX (* If Diff>=0, EAX=(EAX & 0)=0 else EAX=(EAX & -1)=EAX *)
Add EAX,EBX (* EAX= Minimum value between input n. *)
Not ECX (* If Diff<0, ECX=0 else ECX=-1 *)
And EDX,ECX (* If Diff<0, EDX=(EDX & 0)=0 else EDX=(EDX & -1)=EDX *)
Add EBX,EDX (* EBX= Maximum value between input n. *)
函数Max42可以编写也可以作为80686+处理器的下一个代码,
只需要 20 个快速 ASM 寄存器的指令:
Function Max42B(A,B,C,D:Integer):Integer; Assembler;
{ Input: EAX, EBX, ESI, EDI
Output: EDI= 1° MAX(EAX,EBX,ESI,EDI).
ESI= 2° MAX(EAX,EBX,ESI,EDI).
Temp: ECX.
EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push EBX
Push EDI
Push ESI
Mov EAX,A
Mov EBX,B
Mov ESI,C
Mov EDI,D
{ Input: EAX, EBX
Output: EAX= MIN(EAX,EBX).
EBX= MAX(EAX,EBX).
Temp: ECX}
Mov ECX,EAX
Cmp EAX,EBX
CMovGE EAX,EBX
CMovGE EBX,ECX
{ Input: EBX, ESI
Output: EBX= MIN(EBX,ESI).
ESI= MAX(EBX,ESI).
Temp: ECX}
Mov ECX,EBX
Cmp EBX,ESI
CMovGE EBX,ESI
CMovGE ESI,ECX
{ Input: ESI, EDI
Output: ESI= MIN(ESI,EDI).
EDI= MAX(ESI,EDI).
Temp: ECX}
Mov ECX,ESI
Cmp ESI,EDI
CMovGE ESI,EDI
CMovGE EDI,ECX
{ Input: EAX, EBX
Output: EAX= MIN(EAX,EBX).
EBX= MAX(EAX,EBX).
Temp: ECX}
Mov ECX,EAX
Cmp EAX,EBX
CMovGE EAX,EBX
CMovGE EBX,ECX
{ Input: EBX, ESI
Output: EBX= MIN(EBX,ESI).
ESI= MAX(EBX,ESI).
Temp: ECX}
Mov ECX,EBX
Cmp EBX,ESI
CMovGE EBX,ESI
CMovGE ESI,ECX
{EDI contain the first maximum number;
ESI contain the second maximum number}
Mov EAX,EDI
{------------------------}
Pop ESI
Pop EDI
Pop EBX
End;
嗨!