Article View: alt.lang.asm
Article #155Re: Fast 386 code (and min() and max())
From: Sean 'Captain Napalm' Conner
Date: Sat, 09 Jan 1993 21:01
Date: Sat, 09 Jan 1993 21:01
92 lines
3594 bytes
3594 bytes
In article <1993Jan5.151702.20426@netcom.com> tm@netcom.com (Toshiyasu Morita) writes: > >Alright, next question: > >What general guidelines are there to follow to write fast 386/486 code? >What's fast, what's not? > Some quick hacks: Avoid most of the specialized instructions (like xlat, enter and loop), as the more general ones have been optimized to Hell and back and now run faster than the specialized instructions that replaced them. ADD r,r is faster than SHL r,1 and posibly two ADDs are faster than SHL r,2. And in this same vein, never MUL or DIV by a power of two, use shifts (or ADDs 8-) Have the desinations for JMPs, Jccs, or CALLs on long word boundaries (if you can spare the memory). Even word boundaries are better than having a destination end on an odd address (at the very least, the beginning of each subroutine should start on an even address). Since the 486 is pipelined, you may have to play around with instruction ordering to get best performance. A fragement like: mov ax,[si] add si,2 mov [di],ax add di,2 is slow because SI is being used to generate an address, and then modified in the following instruction, causing the pipeline to stall (to wait for the first instruction to finish using SI). A better way is to: mov ax,[si] add di,2 ;allow ref to AX and SI ;to finish mov [di],ax ;ADD DI is quick, won't ;stall pipeline add si,2 ;now we can update SI Basically, memory references have the potiential to stall the pipeline. Be careful in the way you order the instructions (only for a 486+) FP operations are (for the basic operations + - * /) as fast as (or faster) than the same integer based instructions on the 386/486, and may (not sure on the 486) execute concurrently as the 386 instructions, so the best bet would be to interspace FP operations with 386/486 operations (that way, the main CPU won't have to wait for the FPU to finish). Avoid conditional jumps. They stall the pipeline. While it may be tempting to write: foo: mov ax,[esi] ;get 16 bit quantity cwd ;sign extend into EAX mov [edi],eax add esi,2 add edi,4 dec cx jnz foo A faster loop is to unroll it a few times: foo1: mov ax,[esi] cwd mov [edi],eax dec cx jz endfoo mov ax,2[esi] cwd mov 4[edi],eax add esi,4 add edi,8 dec cx jnz foo1 endfoo: and adjust the count properly (I could have unrolled the loop two more times if I wasn't lazy 8-). In 16 bit mode, 32 bit instructions take a bit longer to execute (more to decode). In 32 bit mode, 16 bit instructions take a bit longer to execute (again, more to decode). Register to register operations are the fastest. Memory to memory operations are the slowest (or course). Well, that's about all I can remember off the top of my head (I don't have my 386 reference manual handy with me right now). Hope this helps some. -spc (Remember all of the optimizations for the 8088 you learned? Well, throw them out the window, here comes the 386 8-)
Technical Details
Message-ID:
<1993Jan9.210159.27965@cybernet.cse.fau.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!usc!wupost!news.miami.edu!cybernet!pineal.math.fau.edu!spcReferences:
<1993Jan5.151702.20426@netcom.com>Show Full Headers
Complete Article Headers
Newsgroups: alt.lang.asm Path: arc1-ca.pugleaf.net!sparky!uunet!usc!wupost!news.miami.edu!cybernet!pineal.math.fau.edu!spc From: spc@pineal.math.fau.edu (Sean 'Captain Napalm' Conner) Subject: Re: Fast 386 code (and min() and max()) Message-ID: <1993Jan9.210159.27965@cybernet.cse.fau.edu> Sender: news@cybernet.cse.fau.edu Organization: Florida Atlantic University, but who cares? References: <1993Jan5.151702.20426@netcom.com> Date: Sat, 9 Jan 1993 21:01:59 GMT Lines: 93