如何优化此图形精灵仿真例程?

时间:2018-01-06 18:08:27

标签: optimization x86 delphi-7 inline-assembly micro-optimization

此例程是一个窗口化的get / put-sprite仿真例程。 我是意大利人,我没有翻译过它们。 此例程能够在将图像存储在16字节对齐的缓冲区之前对图像进行翻转。 出于保密原因,我省略了预先计算程序。我从彼得·科德斯的建议中学到了充分利用LEA声明,并且是第一个个人实施的汇编者BT'指令:

Procedure Sub_MoveSprite; Assembler;

(* Sub-ROUTINE per MoveSprite (FlipX-FlipY).

 INPUT:

    EAX= Attributi immagine.
    EBX= Scarto X per origine.
    ECX= Quantità X di Pixel per LINEA.
    EDX= Quantità Y di linee da trasf.
    EBP= Scarto X per destinazione.
    ESI= OFFSET per origine.
    EDI= OFFSET per destinaz *)

Asm

     Push  EBP
     Push  EBX
     Push  ECX

     BT    EAX,Def_Target_DirX_D
     SbB   EBP,EBP
     LEA   EBP,[2*EBP+1]

     BT    EAX,Def_Source_DirX_D
     SbB   EBX,EBX
     LEA   EBX,[2*EBX+1]

@@01:Mov   AL,[ESI]
     Cmp   AL,AH
     JE    @@00
     Mov   [EDI],AL
@@00:Add   ESI,EBX
     Add   EDI,EBP
     Loop  @@01

     Mov   ECX,[ESP]

     Add   ESI,[ESP+4]
     Add   EDI,[ESP+8]

     Dec   EDX
     JNE   @@01

     Add   ESP,12

End;

如何优化?例如,将其细分为几个子例程: 在这种情况下,我不会在Y轴上翻转图像:

Procedure Sub_MoveSprite_FX0; Assembler;

{Sub-ROUTINE per MoveSprite (FlipY).

 INPUT:

    EAX= Attributi immagine.
    EBX= Scarto X per origine.
    ECX= Quantità X di Pixel per LINEA.
    EDX= Quantità Y di linee da trasf.
    EBP= Scarto X per destinazione.
    ESI= OFFSET per origine.
    EDI= OFFSET per destinaz}

Asm

     ClD

     Push  ECX

@@01:LodSB
     Cmp   AL,AH
     JE    @@00
     Mov   [EDI],AL
@@00:Inc   EDI
     Loop  @@01

     Mov   ECX,[ESP]

     Add   ESI,EBX
     Add   EDI,EBP

     Dec   EDX
     JNE   @@01

     Add   ESP,4

End;

现在这里有完整的优化代码,没有任何建议:

Procedure PutImage_FullClipp; Assembler;

{Calcola la CLIPPING REGION.

 INPUT:
 -----:
 EAX     : Byte_0 = BkCol, nuovo colore sfondo OBPVBuff (Ex simmetria verticale).
           Byte_1 = SpCol, nuovo colore sfondo SPRITE.
           Byte_2 = MaskCol, colore maschera/FIGURA.
           Byte_3 = Attributi EXTRA:
                    Bit0= 0 -> Col. predef. dello sfondo di OBPVBuff.
                          1 -> Il Col. dello sfondo di OBPVBuff è BkCol.
                    Bit1= 0 -> Col. predef. dello sfondo.
                          1 -> Il Col. dello sfondo è SpCol.
                    Bit2= 0 -> Rappresenta lo SPRITE.
                          1 -> Rappresenta lo sfondo dello SPRITE.
                    Bit3= 0 -> L' immagine non è uno SPRITE.
                          1 -> L' immagine è uno SPRITE;
                    Bit4= 0 -> L' immag. non è uno maschera.
                          1 -> L' immag. è uno maschera di colore MaskCol.
                    Bit5= 0 -> Put-IMAGE.
                          1 -> Get-IMAGE.
                    Bit6= 0 -> Nessuna simmetria orizzontale.
                          1 -> Simmetria orizzontale.
                    Bit7= 0 -> Nessuna simmetria verticale.
                          1 -> Simmetria verticale.
 EBX     = Dimensioni X e Y della finestra sul BUFFER VIDEO
           (specif. 0, la Dim. sarà consid. = a quella del BUFFER VIDEO).
 ECX     = COORDINATE X e Y dell' immagine OBP di origine.
 EDX     = COORDINATE X e Y della finestra sul BUFFER VIDEO.
 ESI     = PUNTATORE all' immagine OBP di origine.
 EDI     = PUNTATORE al BUFFER VIDEO OBP di destinazione.

 OUTPUT:
 ------:
 EAX     : Byte_0 = Colore sfondo OBPVBuff.
           Byte_1 = Colore sfondo SPRITE.
           Byte_2 = MaskCol, colore maschera/FIGURA.
           Byte_3 = Attributi EXTRA:
                    Bit0= 0 -> Il dithering inizia per 0.
                          1 -> Il dithering inizia per 1.
                    Bit1= 0 -> Col. predef. dello sfondo.
                          1 -> Il Col. dello sfondo è SpCol.
                    Bit2= 0 -> Rappresenta lo SPRITE.
                          1 -> Rappresenta lo sfondo dello SPRITE.
                    Bit3= 0 -> L' immagine non è uno SPRITE.
                          1 -> L' immagine è uno SPRITE;
                    Bit4= 0 -> L' immag. non è uno maschera.
                          1 -> L' immag. è uno maschera di colore MaskCol.
                    Bit5= 0 -> Put-IMAGE.
                          1 -> Get-IMAGE.
                    Bit6= 0 -> Incremento X destinazione = 1.
                          1 -> Incremento X destinazione (FlipX) = -1.
                    Bit7= 0 -> Incremento X origine = 1.
                          1 -> Incremento X origine (FlipX)= -1.
 EBX     = Scarto X per origine.
 ECX     = Quantità X di Pixel per LINEA.
 EDX     = Quantità Y di linee.
 EBP     = Scarto X per destinazione.
 ESI     = PUNTATORE ai dati da trasferire per l' origine.
 EDI     = PUNTATORE alla destinazione dei dati da trasferire.
 FCarry  = 1 -> ERRORE, i registri di OUTPUT
                non contengono valori attendibili.
         = 0 -> Ok, tutti i registri di OUTPUT
                contengono valori attendibili}

Asm

     Sub   ESP,60         {Definisce le variabili locali sullo STACK}

  (* Attr        {[ESP+00]: Attributi SPRITE}
     X           {[ESP+04]: COORDINATA X immagine da trasferire}
     Y           {[ESP+08]: COORDINATA Y immagine da trasferire}
     DimX        {[ESP+12]: Dimensione X immagine da trasferire}
     DimY        {[ESP+16]: Dimensione Y immagine da trasferire}
     WindX       {[ESP+20]: COORDINATA X finestra sul BUFFER VIDEO}
     WindY       {[ESP+24]: COORDINATA Y finestra sul BUFFER VIDEO}
     DimWindX    {[ESP+28]: Dimensione X finestra sul BUFFER VIDEO}
     DimWindY    {[ESP+32]: Dimensione Y finestra sul BUFFER VIDEO}
     ADimX       {[ESP+36]: Dimens. X immagine da trasf. allineata ai 16 BYTE}
     ADimScrX    {[ESP+40]: Dimensione X BUFFER VIDEO allineata ai 16 BYTE}
     SourcePtr   {[ESP+44]: PUNTATORE all' immagine OBP di origine}
     TargetPtr   {[ESP+48]: PUNTATORE alla destinazione dei dati da trasferire}
     FlipX       {[ESP+52]: Maschera x simmetria orizzontale}
     FlipY       {[ESP+56]: Maschera x simmetria verticale} *)

    {Preparazione iniziale e controllo coerenza parametri}

    {  SI<1 |   DI<1 |       CL |  FSign
     -------+--------+----------+-------
          0 |      0 | -0 -0  0 |      0
          0 |      1 | -0 -1 -1 |      1
          1 |      0 | -1 -0 -1 |      1
          1 |      1 | -1 -1 -2 |      1
     -------+--------+----------+-------}

     Cmp   ESI,1          {Se IMAGE=NIL, ...}
     SbB   EBP,EBP        {... EBP vale -1, altrim. vale 0}

     Cmp   EDI,1          {Se OBPVBuff=NIL, ...}
     SbB   EBP,0          {... EBP vale EBP-1, altrim. vale EBP}

     StC                  {Se IMAGE=NIL o se OBPVBuff=NIL, imposta FCarry=1 ...}
     JS    @@Ex           {... ed esce}

    {-----------------------------------}

     Mov   EBP,[ESI]      {Carica Dim_XY(IMAGE) IN EBP}
     Add   ESI,DimOBP_H   {ESI punta all' area dati di IMAGE}
     Mov   [ESP+44],ESI   {Salva ESI su SourcePtr}

    {-----------------------------------}

     MovSX ESI,BP         {Estende con SEGNO ...}
     Or    ESI,ESI        {... la Dim. X di IMAGE IN ESI; ...}
     StC                  {... se è <=0, imposta FCarry=1 ...}
     JLE   @@Ex           {... ed esce}

     Or    EBP,EBP        {Estende con SEGNO ...}
     SAR   EBP,16         {... la Dim. Y di IMAGE IN EBP; ...}
     StC                  {... se è <=0, imposta FCarry=1 ...}
     JLE   @@Ex           {... ed esce}

    {-----------------------------------}

     Mov   [ESP+12],ESI   {Salva la Dim. X di IMAGE con 0 esteso su DimX}
     Mov   [ESP+16],EBP   {Salva la Dim. Y di IMAGE con 0 esteso su DimY}

    {-----------------------------------}

     Mov   EBP,ESI        {Calcola, IN EBP, la Dim. X di IMAGE ...}
     And   EBP,R_OBP_Al-1 {...}
     Neg   EBP            {...}
     Add   EBP,R_OBP_Al   {...}
     And   EBP,R_OBP_Al-1 {...}
     Add   EBP,ESI        {... allineata ai 16 BYTE e ...}
     Mov   [ESP+36],EBP   {... la salva su ADimX}

    {-----------------------------------}

     Mov   ESI,[EDI]      {Carica Dim_XY(OBPVBuff) IN ESI}
     Add   EDI,DimOBP_H   {EDI punta all' area dati di OBPVBuff}
     Mov   [ESP+48],EDI   {Salva EDI su TargetPtr}

    {-----------------------------------}

     MovSX EDI,SI         {Estende con SEGNO ...}
     Or    EDI,EDI        {... la Dim. X di OBPVBuff IN EDI; ...}
     StC                  {... se è <=0, imposta FCarry=1 ...}
     JLE   @@Ex           {... ed esce}

     Or    ESI,ESI        {Estende con SEGNO ...}
     SAR   ESI,16         {... la Dim. Y di OBPVBuff IN ESI; ...}
     StC                  {... se è <=0, imposta FCarry=1 ...}
     JLE   @@Ex           {... ed esce}

    {-----------------------------------}

     Test  EAX,_Def_Attr_New_BkCol {Se il Bit0 di Attr.MODE <> 0 ...}
     JNE   @@00           {... usa il nuovo colore dello sfondo di OBPVBuff}

     Mov   EBP,[ESP+48]   {Carica TargetPtr IN EBP e ...}
     Mov   AL,[EBP]       {... carica IN AL il colore sfondo di OBPVBuff}

@@00:Test  EAX,_Def_Attr_New_SpCol {Se il Bit1 di Attr.MODE <> 0 ...}
     JNE   @@01           {... usa il nuovo colore dello sfondo di IMAGE}

     Mov   EBP,[ESP+44]   {Carica SourcePtr IN EBP e ...}
     Mov   AH,[EBP]       {... carica IN AH il colore sfondo di IMAGE}

@@01:BT    EAX,Def_Attr_FlipY_D {Bit7(Attr.MODE)<>0? Si: FCarry=1; no: FCarry=0}
     SbB   EBP,EBP        {Se Bit7 di Attr.MODE <>0, EBP=-1, altrim. EBP=0}
     Mov   [ESP+56],EBP   {Imposta FlipY=EBP}

     BT    EAX,Def_Attr_FlipX_D {Bit6(Attr.MODE)<>0? Si: FCarry=1; no: FCarry=0}
     SbB   EBP,EBP        {Se Bit6 di Attr.MODE <>0, EBP=-1, altrim. EBP=0}
     Mov   [ESP+52],EBP   {Imposta FlipX=EBP}

     And   EBP,_Def_Target_DirX {EBP contiene il Bit6 di Attr.MODE}
     And   EAX,-1-_Def_Source_DirX-_Def_Dither {CANC. Bit0 e Bit7 di Attr.MODE}

     Test  EAX,_Def_Attr_Get_Image {Se il Bit5 di Attr.MODE=0 ...}
     JE    @@02           {... salta}

     XChg  AL,AH          {Scambia i colori dello sfondo di IMAGE e OBPVBuff}
     Add   EAX,EBP        {Scambia il Bit6 Col Bit7 di Attr.MODE}

@@02:Mov   [ESP],EAX      {Salva Attr.MODE su Attr}

    {-----------------------------------}

     Mov   EAX,EDI        {Calcola, IN EAX, la Dim. X di OBPVBuff ...}
     And   EAX,R_OBP_Al-1 {...}
     Neg   EAX            {...}
     Add   EAX,R_OBP_Al   {...}
     And   EAX,R_OBP_Al-1 {...}
     Add   EAX,EDI        {... allineata ai 16 BYTE e ...}
     Mov   [ESP+40],EAX   {... la salva su ADimScrX}

    {-----------------------------------}

     MovSX EAX,CX         {Calcola, IN EAX, la coord. X di IMAGE, ...}
     Mov   [ESP+4],EAX    {... con SEGNO esteso e la salva su X}

     Or    ECX,ECX        {Calcola, IN ECX, la coord. Y di IMAGE, ...}
     SAR   ECX,16         {... con SEGNO esteso e ...}
     Mov   [ESP+8],ECX    {... la salva su Y}

    {-----------------------------------}

     MovSX EAX,DX         {Estende con SEGNO la coord. X ...}
     Or    EAX,EAX        {... della finestra sul BUFFER VIDEO IN EAX; ...}
     StC                  {... se è <0, imposta FCarry=1 ...}
     JS    @@Ex           {... ed esce}

     Or    EDX,EDX        {Estende con SEGNO la coord. Y ...}
     SAR   EDX,16         {... della finestra sul BUFFER VIDEO IN EDX; ...}
     StC                  {... se è <0, imposta FCarry=1 ...}
     JS    @@Ex           {... ed esce}

    {-----------------------------------}

     Mov   [ESP+20],EAX   {Salva la coord. X fin. BUFFER Vid. con 0 e. su WindX}
     Mov   [ESP+24],EDX   {Salva la coord. Y fin. BUFFER Vid. con 0 e. su WindY}

    {-----------------------------------}

     MovSX ECX,BX         {Estende con SEGNO la dimens. X ...}
     Or    ECX,ECX        {... della finestra sul BUFFER VIDEO IN ECX; ...}
     StC                  {... se è <0, imposta FCarry=1 ...}
     JS    @@Ex           {... ed esce}

     JNE   @@03           {Se la dimens. X della finestra sul BUFFER VIDEO ...}
     Mov   ECX,EDI        {... è =0, la imposta con la Dim. X di OBPVBuff}

@@03:Add   EAX,ECX        {Se la coord. X della finestra sul BUFFER VIDEO ...}
     Cmp   EDI,EAX        {... più la Dim. X finestra sul BUFFER VIDEO ...}
     JB    @@Ex           {... > Dim. X di OBPVBuff, esce (FCarry=1)}

    {-----------------------------------}

     Or    EBX,EBX        {Estende con SEGNO la dimens. Y ...}
     SAR   EBX,16         {... della finestra sul BUFFER VIDEO IN EBX ...}
     StC                  {... se è <0, imposta FCarry=1 ...}
     JS    @@Ex           {... ed esce}

     JNE   @@04           {Se la dimens. Y della finestra sul BUFFER VIDEO ...}
     Mov   EBX,ESI        {... è =0, la imposta con Dim. Y di OBPVBuff}

@@04:Add   EDX,EBX        {Se la coord. Y della finestra sul BUFFER VIDEO ...}
     Cmp   ESI,EDX        {... più la Dim. Y finestra sul BUFFER VIDEO ...}
     JB    @@Ex           {... > Dim. Y di OBPVBuff, esce (FCarry=1)}

    {-----------------------------------}

     Mov   [ESP+28],ECX   {Salva la Dim.X fin. BUFFER Vid. con 0 e. su DimWindX}
     Mov   [ESP+32],EBX   {Salva la Dim.Y fin. BUFFER Vid. con 0 e. su DimWindY}

    {Calcola scarti XLow (ESI) e XHigh (ECX)}

     Mov   EDI,[ESP+4]    {Carica, IN EDI, la coord. X di IMAGE}
     Mov   EBX,[ESP+12]   {Carica, IN EBX, la Dim. X di IMAGE}

     XOr   ESI,ESI        {Imposta XLow=0}
     XOr   ECX,ECX        {Imposta XHigh=0}

     Or    EDI,EDI        {Se EDI>=0 ...}
     JNS   @@05           {... salta}

     Add   EDI,EBX        {Imposta EDI=EDI+EBX; ...}
     StC                  {... se EDI<0, ...}
     JS    @@Ex           {... imposta FCarry=1 ed esce}

     Mov   ESI,[ESP+4]    {Imposta XLow con la coord. X di IMAGE}
     Neg   ESI            {Imposta XLow=-XLow}
     Mov   DWord Ptr [ESP+4],0 {Imposta la coord. X di IMAGE a 0}

     Jmp   @@06           {Salta}

@@05:Cmp   EDI,[ESP+28]   {Se EDI>=Dim. X della finestra su OBPVBuff ...}
     CmC                  {...}
     JB    @@Ex           {... imposta FCarry=1 ed esce}

     Add   EDI,EBX        {Imposta EDI=EDI+EBX}

@@06:Cmp   EDI,[ESP+28]   {Se EDI<=Dim. X della finestra su OBPVBuff ...}
     JBE   @@07           {... salta}

     Mov   ECX,EDI        {Imposta ...}
     Sub   ECX,[ESP+28]   {... XHigh=EDI-Dim. X della finestra su OBPVBuff}

    {Calcola scarti YLow (EDI) e YHigh (EBX)}

@@07:Mov   EAX,[ESP+8]    {Carica, IN EAX, la coord. Y di IMAGE}
     Mov   EDX,[ESP+16]   {Carica, IN EDX, la Dim. Y di IMAGE}

     XOr   EDI,EDI        {Imposta YLow=0}
     XOr   EBX,EBX        {Imposta YHigh=0}

     Or    EAX,EAX        {Se EAX>=0 ...}
     JNS   @@08           {... salta}

     Add   EAX,EDX        {Imposta EAX=EAX+EDX; ...}
     StC                  {... se EAX<0, ...}
     JS    @@Ex           {... imposta FCarry=1 ed esce}

     Mov   EDI,[ESP+8]    {Imposta YLow con la coord. Y di IMAGE}
     Neg   EDI            {Imposta YLow=-YLow}
     Mov   DWord Ptr [ESP+8],0 {Imposta la coord. Y di IMAGE a 0}

     Jmp   @@09           {Salta}

@@08:Cmp   EAX,[ESP+32]   {Se EAX>=Dim. Y della finestra su OBPVBuff ...}
     CmC                  {...}
     JB    @@Ex           {... imposta FCarry=1 ed esce}

     Add   EAX,EDX        {Imposta EAX=EAX+EDX}

@@09:Cmp   EAX,[ESP+32]   {Se EAX<=Dim. Y della finestra su OBPVBuff ...}
     JBE   @@10           {... salta}

     Mov   EBX,EAX        {Imposta ...}
     Sub   EBX,[ESP+32]   {... YHigh=EAX-Dim. Y della finestra su OBPVBuff}

    {Prepara i registri di OUTPUT EAX, EBX, ECX, EDX, EDI, ESI}

@@10:Cmp   DWord Ptr [ESP+56],-1 {Se FlipY=-1 ...}
     Mov   EAX,EDI        {...}
     CMovE EDI,EBX        {...}
     CMovE EBX,EAX        {... scambia YHigh con YLow}

    {-----------------------------------}

     Add   EBX,EDI        {    EBX=  YHigh+YLow}
     Neg   EBX            {    EBX= -YHigh-YLow}
     Add   EBX,[ESP+16]   {    EBX=  DimY-YHigh-YLow;         N.righe da trasf.}

     StC                  {Se non CI sono righe da trasf.,    FCarry=1 ...}
     JE    @@Ex           {... esce}

    {-----------------------------------}

     Cmp   DWord Ptr [ESP+52],-1 {Se FlipX=-1 ...}
     Mov   EAX,ESI        {...}
     CMovE ESI,ECX        {...}
     CMovE ECX,EAX        {... scambia XHigh con XLow}

    {-----------------------------------}

     Add   ECX,ESI        {    ECX=  XHigh+XLow}
     Neg   ECX            {    ECX= -XHigh-XLow}
     Add   ECX,[ESP+12]   {    ECX=  DimX-XHigh-XLow;         N.Col. da trasf.}

     StC                  {Se non CI sono colonne da trasf.,  FCarry=1 ...}
     JE    @@Ex           {... esce}

    {-----------------------------------}

     Mov   EBP,ESI        {    EBP=  XLow}
     XOr   EBP,EDI        {    EBP=  XLow ^ YLow}
     And   EBP,1          {    EBP=  (XLow ^ YLow) & 1}
     ShL   EBP,Def_Dither_D {  EBP=  ((XLow ^ YLow) & 1)<<24}
     Or    [ESP],EBP      {    Attr.MODE= Attr.MODE | ((XLow ^ YLow) & 1)}

    {-----------------------------------}

     Mov   EBP,ECX        {    EBP= -XLow-XHigh+DimX}
     Dec   EBP            {    EBP= -XLow-XHigh+DimX-1}
     And   EBP,[ESP+52]   {    EBP= (-XLow-XHigh+DimX-1) & FlipX}

     Add   EBP,[ESP+4]    {    EBP=  X+[-XLow-XHigh+DimX-1]}
     Add   EBP,[ESP+20]   {    EBP=  X+[-XLow-XHigh+DimX-1]+WindX}

     Mov   EAX,EBX        {    EAX= -YLow-YHigh+DimY}
     Dec   EAX            {    EAX= -YLow-YHigh+DimY-1}
     And   EAX,[ESP+56]   {    EAX= (-YLow-YHigh+DimY-1) & FlipY}

     Add   EAX,[ESP+8]    {    EAX=  Y+[-YLow-YHigh+DimY-1]}
     Add   EAX,[ESP+24]   {    EAX=  Y+[-YLow-YHigh+DimY-1]+WindY}

     Mul   DWord Ptr [ESP+40] {EDX:EAX= (Y+[-YLow-YHigh+DimY-1]+WindY)*ADimScrX}

     Add   EAX,EBP        {    EAX= (Y+[-YLow-YHigh+DimY-1]+WindY)*ADimScrX+ ...}
                          {...       +X+[-XLow-XHigh+DimX-1]+WindX}
     Add   [ESP+48],EAX   {TargetPtr=(Y+[-YLow-YHigh+DimY-1]+WindY)*ADimScrX+...}
                          {...        +X+[-XLow-XHigh+DimX-1]+WindX+TargetPtr}

    {-----------------------------------}

     Mov   EAX,EDI        {    EAX=  YLow}

     Mul   DWord Ptr [ESP+36] {EDX:EAX=  YLow*ADimX}

     Add   EAX,ESI        {    EAX=  YLow*ADimX+XLow}
     Add   [ESP+44],EAX   {SourcePtr=YLow*ADimX+XLow+SourcePtr}

    {-----------------------------------}

     Mov   EDX,EBX        {    EDX=  DimY-YHigh-YLow;         N.righe da trasf.}

     Mov   EBX,ECX        {    EBX=  DimX-XHigh-XLow}
     Neg   EBX            {    EBX= -DimX+XHigh+XLow}
     Mov   EAX,EBX        {    EAX= -DimX+XHigh+XLow}

     Add   EBX,[ESP+36]   {    EBX= -DimX+XHigh+XLow+ADimX;   scarto X per Orig}
     Add   EAX,[ESP+40]   {    EAX=-DimX+XHigh+XLow+ADimScrX; scarto X per Dest}

  (*   SX= Scarto X per Dest. (EAX)
     NCol= N.Col. da trasf. (ECX)
     ------+-------+---------------
     FlipX | FlipY | ScartoXDest
        0  |    0  |         SX
        0  |   -1  | -2*NCol-SX)
       -1  |    0  |  2*NCol+SX
       -1  |   -1  |        -SX *)

     LEA   EDI,[2*ECX]    {    EDI=  2*ECX}
     Mov   EBP,[ESP+52]   {    ...}
     XOr   EBP,[ESP+56]   {... EBP= FlipX ^ FlipY}
     And   EDI,EBP        {    EDI=  2*NCol & (FlipX ^ FlipY)}
     Add   EAX,EDI        {    EAX=  SX+2*NCol & (FlipX ^ FlipY)}

     XOr   EAX,[ESP+56]   {Se FlipY=-1 allora EAX=-EAX ...}
     Sub   EAX,[ESP+56]   {... altrimenti EAX è inalterato}

     Mov   EBP,EAX        {    EBP= Scarto X per Dest}

     Mov   EDI,[ESP+48]   {    EDI= PTR Dest.}
     Mov   ESI,[ESP+44]   {    ESI= PTR Orig.}
     Mov   EAX,[ESP]      {    EAX= Attr}

     Test  EAX,_Def_Attr_Get_Image {Se il Bit5 di Attr.MODE=0 ...}
     JE    @@Ex           {... salta}

     XChg  ESI,EDI        {    Scambia PTR Orig. con PTR Dest.}
     XChg  EBX,EBP        {    Scambia scarto X per Orig. con scarto X per Dest}

     ClC                  {    FCarry=0;                      nessun ERRORE}

    {-----------------------------------}

@@Ex:LEA   ESP,[ESP+60]   {    Reimposta lo STACK-POINTER;    esce}

End;

Procedure MoveImage(Image:T_Image_Ptr;
                    Prop:T_Long_Attrib_Ptr;
                    OBPVBuff:Pointer;
                    Clipp:T_Clipp_Rect_Ptr); Assembler;

{Disegna un immagine con CLIPPING REGION.

 INPUT:
 EAX   = PUNTATORE a RECORD di definizione dell' immagine.
 EDX   = PUNTATORE alle proprietà dell' immagine.
 ECX   = PUNTATORE al BUFFER VIDEO IN formato OBP.
 Clipp = PUNTATORE al RECORD della CLIPPING REGION.

 PARAMETERs order:
 1°=EAX; 2°=EDX; 3°=ECX}

Asm

     Push  EBX
     Push  EDI
     Push  ESI
     Push  EBP

     Mov   ESI,Image      {EAX}
     Mov   EBX,Prop       {EDX}
     Mov   EDI,OBPVBuff   {ECX}
     Mov   EDX,Clipp

     Mov   EAX,EBX

     Or    EBX,EBX
     JE    @@00

     Mov   EAX,[EBX]
     Mov   EBX,[EBX+4]

@@00:Push  EBX

     Or    ESI,ESI
     JE    @@01

     Mov   ECX,[ESI]
     Mov   ESI,[ESI+4]

     Mov   EBX,EDX

     Or    EDX,EDX
     JE    @@02

     Mov   EDX,[EBX]      {Clipp.XY}
     Mov   EBX,[EBX+4]    {Clipp.Dim_XY}

@@02:Call  PutImage_FullClipp
     JB    @@01

  (* _DirX | _Sprite | ShadowTable | _Mask | _BackG | FUNCTION
     ------+---------+-------------+-------+--------+---------
         0 |       0 |           0 |     0 |      0 | Sub_MoveImage_FX0
         0 |       0 |           0 |     0 |      1 | Sub_MoveImage_FX0
         0 |       0 |           0 |     1 |      0 | Sub_MoveImageMask_FX0
         0 |       0 |           0 |     1 |      1 | Sub_MoveImageMask_FX0
         0 |       0 |           1 |     0 |      0 | Sub_MoveImageShadow_FX0
         0 |       0 |           1 |     0 |      1 | Sub_MoveImageShadow_FX0
         0 |       0 |           1 |     1 |      0 | Sub_MoveImageShadow_FX0
         0 |       0 |           1 |     1 |      1 | Sub_MoveImageShadow_FX0
         0 |       1 |           0 |     0 |      0 | Sub_MoveSprite_FX0
         0 |       1 |           0 |     0 |      1 | Sub_MoveSpriteBk_FX0
         0 |       1 |           0 |     1 |      0 | Sub_MoveSpriteMask_FX0
         0 |       1 |           0 |     1 |      1 | Sub_MoveSpriteBkMsk_FX0
         0 |       1 |           1 |     0 |      0 | Sub_MoveSpriteShad_FX0
         0 |       1 |           1 |     0 |      1 | Sub_MoveSprBkShad_FX0
         0 |       1 |           1 |     1 |      0 | Sub_MoveSpriteShad_FX0
         0 |       1 |           1 |     1 |      1 | Sub_MoveSprBkShad_FX0
         1 |       0 |           0 |     0 |      0 | Sub_MoveImage
         1 |       0 |           0 |     0 |      1 | Sub_MoveImage
         1 |       0 |           0 |     1 |      0 | Sub_MoveImageMask
         1 |       0 |           0 |     1 |      1 | Sub_MoveImageMask
         1 |       0 |           1 |     0 |      0 | Sub_MoveImageShadow
         1 |       0 |           1 |     0 |      1 | Sub_MoveImageShadow
         1 |       0 |           1 |     1 |      0 | Sub_MoveImageShadow
         1 |       0 |           1 |     1 |      1 | Sub_MoveImageShadow
         1 |       1 |           0 |     0 |      0 | Sub_MoveSprite
         1 |       1 |           0 |     0 |      1 | Sub_MoveSpriteBk
         1 |       1 |           0 |     1 |      0 | Sub_MoveSpriteMask
         1 |       1 |           0 |     1 |      1 | Sub_MoveSpriteBkMask
         1 |       1 |           1 |     0 |      0 | Sub_MoveSpriteShadow
         1 |       1 |           1 |     0 |      1 | Sub_MoveSpriteBkShadow
         1 |       1 |           1 |     1 |      0 | Sub_MoveSpriteShadow
         1 |       1 |           1 |     1 |      1 | Sub_MoveSpriteBkShadow *)

     Test  EAX,_Def_DirX
     JE    @@03

     Test  EAX,_Def_Attr_Sprite
     JNE   @@04

     Cmp   DWord Ptr [ESP],0
     JNE   @@05

     Test  EAX,_Def_Attr_Mask
     JNE   @@06

     Call  Sub_MoveImage
     Jmp   @@01

@@06:Call  Sub_MoveImageMask
     Jmp   @@01

@@05:Call  Sub_MoveImageShadow
     Jmp   @@01

@@04:Cmp   DWord Ptr [ESP],0
     JNE   @@07

     Test  EAX,_Def_Attr_Mask
     JNE   @@08

     Test  EAX,_Def_Attr_BackG
     JNE   @@09

     Call  Sub_MoveSprite
     Jmp   @@01

@@09:Call  Sub_MoveSpriteBk
     Jmp   @@01

@@08:Test  EAX,_Def_Attr_BackG
     JNE   @@10

     Call  Sub_MoveSpriteMask
     Jmp   @@01

@@10:Call  Sub_MoveSpriteBkMask
     Jmp   @@01

@@07:Test  EAX,_Def_Attr_BackG
     JNE   @@11

     Call  Sub_MoveSpriteShadow
     Jmp   @@01

@@11:Call  Sub_MoveSpriteBkShadow
     Jmp   @@01

@@03:Test  EAX,_Def_Attr_Sprite
     JNE   @@12

     Cmp   DWord Ptr [ESP],0
     JNE   @@13

     Test  EAX,_Def_Attr_Mask
     JNE   @@14

     Call  Sub_MoveImage_FX0
     Jmp   @@01

@@14:Call  Sub_MoveImageMask_FX0
     Jmp   @@01

@@13:Call  Sub_MoveImageShadow_FX0
     Jmp   @@01

@@12:Cmp   DWord Ptr [ESP],0
     JNE   @@15

     Test  EAX,_Def_Attr_Mask
     JNE   @@16

     Test  EAX,_Def_Attr_BackG
     JNE   @@17

     Call  Sub_MoveSprite_FX0
     Jmp   @@01

@@17:Call  Sub_MoveSpriteBk_FX0
     Jmp   @@01

@@16:Test  EAX,_Def_Attr_BackG
     JNE   @@18

     Call  Sub_MoveSpriteMask_FX0
     Jmp   @@01

@@18:Call  Sub_MoveSpriteBkMsk_FX0
     Jmp   @@01

@@15:Test  EAX,_Def_Attr_BackG
     JNE   @@19

     Call  Sub_MoveSpriteShad_FX0
     Jmp   @@01

@@19:Call  Sub_MoveSprBkShad_FX0

@@01:Add   ESP,4

     Pop   EBP
     Pop   ESI
     Pop   EDI
     Pop   EBX

End;

1 个答案:

答案 0 :(得分:1)

在优化速度时不要使用the slow loop instruction,除非AMD CPU实际上并不慢。

通过使用movzx进行字节加载,避免部分寄存器减速。 (lodsb比movzx + inc esi慢,所以也不要使用它。有关更多x86性能优化的信息,请参阅http://agner.org/optimize/。 (以及the x86 tag wiki中的链接。)

您的第二个功能只是基于字节不是特殊透明值的混合。使用SSE2优化pcmpeqb,然后与pand / pandn + por混合。或SSE4.1 pblendvb

SSSE3 pshufb可让您更有效地向所有位置广播一个字节。

特别是如果你制作一个具有固定宽度的版本,如16,24或32像素宽,你可以避免在标量清理代码中需要很多处理奇数宽度。但是,对于可能重叠的第一个/最后一个未对齐的矢量存储,任何宽于16的东西都应该是可行的。

是的,制作函数的不同版本而不是传递整数翻转/无翻转参数可能是好的,特别是如果你使用SSSE3翻转pshufb(或多个SSE2 shuffle,甚至是标量{{ 1}})。使用bswap,您可以进行身份​​随机播放(使矢量保持不变而不是反转),但为没有翻转的情况设置一个单独的循环会更加有效,因为它不会使用{{ 1}}。