cjdb@sphinx.UUCP (09/25/87)
In debugging code written in assembly-language, I notice that MASM periodically inserts NOP's in places where they don't appear in the source. I imagine this is done to slow down the processor, but how does MASM "decide" the appropriate circumstances? Thanks in advance. -- Bitnet: lib.cb@uchicago.bitnet Internet: lib.cb@chip.uchicago.edu uucp: ..!ihnp4!gargoyle!sphinx!cjdb
jack@csccat.UUCP (Jack Hudler) (09/25/87)
In article <2306@sphinx.uchicago.edu>, cjdb@sphinx.uchicago.edu (Charles Blair) writes: > > In debugging code written in assembly-language, I notice that MASM > periodically inserts NOP's in places where they don't appear in the > source. I imagine this is done to slow down the processor, but how > does MASM "decide" the appropriate circumstances? MASM places NOPs in certian places to align some instructions on WORD boundarys or pad EVEN directives. -- See above (214)661-8960
michael@cit-vlsi.Caltech.Edu (Michael Lichter) (09/25/87)
Keywords: In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: > >In debugging code written in assembly-language, I notice that MASM >periodically inserts NOP's in places where they don't appear in the >source. I imagine this is done to slow down the processor, but how >does MASM "decide" the appropriate circumstances? Unlike some other assemblers that force/allow you to decide whether you want 8-bit or 16-bit relative calls and jumps, MASM decides for itself. Not being able to determine whether it can get away with the shorter instruction on the first pass, MASM reserves three bytes. If the offset is small enough, you get [instruction] [offset] [nop], and if it's not, you get [instruction] [offset] [offset]. There are other occasions when MASM will insert instructions that you might not expect, such as WAIT instructions before any co-processor instructions. Michael
perkins@bnrmtv.UUCP (Henry Perkins) (09/25/87)
In article <2306@sphinx.uchicago.edu>, cjdb@sphinx.uchicago.edu (Charles Blair) writes: > In debugging code written in assembly-language, I notice that MASM > periodically inserts NOP's in places where they don't appear in the > source. I imagine this is done to slow down the processor, but how > does MASM "decide" the appropriate circumstances? It's not done to "slow down the processor"; it's done to make the code size/location unambiguous. There are two reasons why MASM will insert a NOP that isn't in the original code: assembler directives and short jumps. Directives like EVEN and ORG specify where the next instruction starts; the intervening space is padded with NOPs. A single NOP is used after a short jump when the assembler source did not specify (with the SHORT pseudo-op) that the JMP was the shorter, 8-bit displacement type. Rather than use the slower 16-bit displacement jump, MASM will use a short jump and add a NOP to preserve the offset of the next instruction. If you specify that the jump is to be short, of course, no NOP is inserted. -- {hplabs,amdahl,ames}!bnrmtv!perkins --Henry Perkins It is better never to have been born. But who among us has such luck? One in a million, perhap po
johnl@ima.ISC.COM (John R. Levine) (09/25/87)
In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: >In debugging code written in assembly-language, I notice that MASM >periodically inserts NOP's in places where they don't appear in the >source. I imagine this is done to slow down the processor, but how >does MASM "decide" the appropriate circumstances? No, the 8088 is plenty slow already without any help from the assembler. You'll probably find that the NOPs always follow a two-byte jump that is jumping to an address later in the program. On the first pass, the assembler assumes that it'll need a three-byte jump, but finds on the second pass that the target is close enough that a two-byte jump, which is faster, will do. It puts in the NOP to avoid changing the addresses of all later code. It is possible to write assemblers that get the short vs. long jumps correct in almost all cases. Every Unix assembler I've seen on machines with such jumps does so, at least as far back as the PDP-11 fifth edition ca. 1974. It turns out that getting the correct jump in every case is an NP complete problem, so barring a major advance in complexity theory, it's too hard. Getting the right answer in most cases is pretty easy. There's a classic paper by Szymanski in the CACM about 10 years ago that explains it all. -- John R. Levine, IECC, PO Box 349, Cambridge MA 02238-0349, +1 617 492 3869 { ihnp4 | decvax | cbosgd | harvard | yale }!ima!johnl, Levine@YALE.something The Iran-Contra affair: None of this would have happened if Ronald Reagan were still alive.
ching@amd.AMD.COM (Mike Ching) (09/25/87)
In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: > >In debugging code written in assembly-language, I notice that MASM >periodically inserts NOP's in places where they don't appear in the >source. I imagine this is done to slow down the processor, but how >does MASM "decide" the appropriate circumstances? > More likely that these NOPs follow forward branches. MASM leaves space for a 3-byte jump instruction during its first pass and fills the third byte with a NOP if a two byte instruction is all that is necessary. The NOPs are never executed and don't slow down the processor. mike ching
ayac071@ut-ngp.UUCP (William T. Douglass) (09/26/87)
In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: > The NOPs are never executed and don't slow down the >processor. Actually, I thought that NOPs did an OR of the AX register on itself (or some similar operation that causes no change to data.) As such, they DO affect the execution time involved. Could someone knowledgeable confirm or refute this? Bill Douglass ayac071@ngp.UUCP
bright@dataio.Data-IO.COM (Walter Bright) (09/28/87)
In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: >In debugging code written in assembly-language, I notice that MASM >periodically inserts NOP's in places where they don't appear in the >source. I imagine this is done to slow down the processor, but how >does MASM "decide" the appropriate circumstances? The only place I have seen it done is following a JMP instruction where the target address is a forward reference. The reason is that MASM is 2 passes, on the first pass the values of all symbols must be determined. JMP can be 2 or 3 bytes, depending on how far away the target is. Since the target is forward referenced, MASM assumes worst case and allocates enough space for a 3 byte JMP. On pass 2, if the target is close enough that it can be a 2 byte JMP, MASM creates a 2 byte JMP followed by a NOP to fill in the 'hole'. If you want only a 2 byte JMP, use the JMP SHORT mnemonic.
brian@ncrcan.UUCP (Brian Onn) (09/29/87)
In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >.... The NOPs are never executed and don't slow down the >processor. > >mike ching Sorry, but the NOPS are always executed (how would the processor know that it is in fact a NOP, if it didn't execute it) and each execution takes a finite, albeit minimal amount of execution time.
frisk@krafla.UUCP (09/29/87)
>In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: > >Actually, I thought that NOPs did an OR of the AX register on itself (or some >similar operation that causes no change to data.) As such, they DO affect the >execution time involved. >Could someone knowledgeable confirm or refute this? The NOP operation is really XCHG AX,AX and takes just as long to execute as XGHG AX,BX (3 clock cycles). This - however - is less than the instruction fetch time. . . . -- Fridrik Skulason University of Iceland UUCP frisk@rhi.uucp BIX frisk This line intentionally left blank ...................
dalegass@dalcsug.UUCP (09/30/87)
I think people are sorta missing the point about the NOP never being executed: NOP's are *of course* executed when the program passes over them, but the point about this NOP stuck in after a JMP, is that the NOP is never even passed over, because of the JMP right before it. -dalegass@dalcsug.uucp
halvers@italy.UUCP (09/30/87)
In article <309@ncrcan.UUCP> brian@ncrcan.UUCP () writes: >In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >>.... The NOPs are never executed and don't slow down the >>processor. >> >>mike ching > >Sorry, but the NOPS are always executed (how would the processor know that >it is in fact a NOP, if it didn't execute it) and each execution takes >a finite, albeit minimal amount of execution time. Not in this case, since Mike was talking about NOP's padding unconditional jump instructions, i.e. mov bx,ax jmp somewhere_else -----+ nop <--- never reached | v next: lea addr *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Pete Halverson ARPA: halverson@ge-crd.ARPA General Electric Company UUCP: halvers@desdemona.steinmetz.UUCP Corporate R & D halvers@desdemona.steinmetz.ge.com Schenectady, NY "Money for nothin' and your MIPS for free"
jvc@prism.UUCP (09/30/87)
>>(Charles Blair) writes: >> The NOPs are never executed and don't slow down the >>processor. >Bill Douglass writes: >Actually, I thought that NOPs did an OR of the AX register on itself (or some >similar ... ) As such, they DO affect the execution time involved. Could >someone knowledgeable confirm or refute this? Yes, NOPs are executed when encountered. They are actually XCHG AX,AX which requires 3 clock cycles to execute. HOWEVER, when the NOP is used as a pad when the assembler decides that it only needs a 2-byte JMP opcode (it decides this on the second pass after already reserving 3 bytes for a forward jump) , the NOP will never (under normal circumstances) be executed. This should be obvious since the JMP isn't going to be a JMP to that NOP (the very next byte). The only way THAT NOP will ever be executed is if you jump or branch to its address (which you'd probably never do). Think about it. FYI -- Use of SHORT operator: "The SHORT operator is used to tighten up code. Two different JMP instructions will perform identically in many cases. The 3-byte JMP opcode can force execution to any place within the current code segment. A 2-byte JMP opocode can be used to transfer control to within +127 to -128 bytes of the jump instuction." "The assembler will use the shorter form whenever it knows that the short jump is valid, that is, when the jump is backward to a label it has already processed. But the assembler has no way of knowing if a forward jump can use the 2-byte opcode. The purpose of the SHORT operator is to tell the assembler that the short form of the JMP opcode is possible" The above two paragraphs taken from Dan Rollins' "IBM PC 8088 Macro Assembler Programming", C1985. jvc@mirror.tmc.com
smvorkoetter@watmum.UUCP (09/30/87)
In article <309@ncrcan.UUCP> brian@ncrcan.UUCP () writes: >In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >>.... The NOPs are never executed and don't slow down the >>processor. >> >>mike ching > >Sorry, but the NOPS are always executed (how would the processor know that >it is in fact a NOP, if it didn't execute it) and each execution takes >a finite, albeit minimal amount of execution time. I believe what Mr. Ching means is that NOPs after a jump are never executed. Thus, if you have an unconditional jump followed by a NOP like: jmp foo nop bar: more-instructions Then the NOP after the jump will never be executed since there is no way to get to it. Stefan Vorkoetter Symbolic Computation Group University of Waterloo
lotto@wjh12.UUCP (09/30/87)
In article <309@ncrcan.UUCP> brian@ncrcan.UUCP () writes: >In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >>.... The NOPs are never executed and don't slow down the >>processor. >Sorry, but the NOPS are always executed (how would the processor know that Mild flame... I wish people would think before posting. The first article stated: "NOPs are inserted after JMPs that were found not to require the full three bytes." NOPs after JMPs are NOT going to be executed because IP is probably never going to point to them. If you DO execute a NOP, of course it will take (some) time. You did prefetch the instruction, but this always happens for the bytes following a JMP anyway, and that was not what the argument was about. It is dangerous to quote someone out of context, but if you are going to take them to task, at least READ the whole article! Mild flame off... -- Gerald Lotto - Harvard Chemistry Dept. UUCP: {seismo,harpo,ihnp4,linus,allegra,ut-sally}!harvard!lotto ARPA: lotto@harvard.harvard.edu
feg@clyde.UUCP (09/30/87)
In article <309@ncrcan.UUCP>, brian@ncrcan.UUCP (Brian Onn) writes: > In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: > >.... The NOPs are never executed and don't slow down the > >processor. > > > >mike ching > > Sorry, but the NOPS are always executed (how would the processor know that > it is in fact a NOP, if it didn't execute it) and each execution takes > a finite, albeit minimal amount of execution time. True enough, IF the processor executes the NOP. However, what was discussed was the substitution by the assembler of a two byte unconditional jmp for the three bytes set aside on pass 1. Obviously, the processor never gets to execute the NOP in such a case. Forrest Gehrke
ching@amd.UUCP (09/30/87)
Read the article. I was talking about a NOP following a branch. mike ching
carsten@cernvax.UUCP (09/30/87)
Even if the NOP is not executed, it has to be loaded into the instruction register (the CPU's cannot foresee the NOP (yet))! Hence it slows down the CPU! Carsten Andersen carsten@cernvax ..... hamlet() { if ((be) || (!be)) question(); }
perkins@bnrmtv.UUCP (09/30/87)
In article <309@ncrcan.UUCP>, brian@ncrcan.UUCP (Brian Onn) writes: > In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: > >.... The NOPs are never executed and don't slow down the > >processor. > > > >mike ching > > Sorry, but the NOPS are always executed (how would the processor know that > it is in fact a NOP, if it didn't execute it) and each execution takes > a finite, albeit minimal amount of execution time. Here's the original text that Brian abridged: More likely that these NOPs follow forward branches. MASM leaves space for a 3-byte jump instruction during its first pass and fills the third byte with a NOP if a two byte instruction is all that is necessary. The NOPs are never executed and don't slow down the processor. mike ching The short jump transfers execution to some instruction other than the NOP; the NOP is NEVER executed. The processor DOESN'T "know" that it's a NOP; it never has a chance to execute it (although it does put it in its prefetch queue). Execution of a NOP takes a finite but NON-minimal amount of time; a NOP (same as XCHG AX,AX) takes 3 bus cycles, whereas the minimum for an instruction is 2 bus cycles (example: CLD, which I generally use in preference to NOP because I keep the direction flag cleared anyway). Sorry, Brian, but I think that's a first: a one-sentence posting with THREE errors. Better luck next time, and for now I recommend "The 8086 Book" by Rector & Alexy (Osborne/McGraw-Hill Books). -- {hplabs,amdahl,ames}!bnrmtv!perkins --Henry Perkins It is better never to have been born. But who among us has such luck? One in a million, perhaps.
farren@gethen.UUCP (10/01/87)
In article <309@ncrcan.UUCP> brian@ncrcan.UUCP () writes: >In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >>.... The NOPs are never executed and don't slow down the >>processor. >> >>mike ching > >Sorry, but the NOPS are always executed (how would the processor know that >it is in fact a NOP, if it didn't execute it) and each execution takes >a finite, albeit minimal amount of execution time. Sigh. Given an instruction sequence like: jmp label nop label: the NOP will NOT be executed, and, in fact, barring certain aspects of pipelining, will never even be SEEN by the processor. Control flow will jump right over that instruction every time. The processor, in fact, does NOT know that the instruction is a NOP - it knows nothing about it at all - it could be any value, but is a NOP for convenience and readability. -- ---------------- Mike Farren "... if the church put in half the time on covetousness unisoft!gethen!farren that it does on lust, this would be a better world ..." gethen!farren@lll-winken.arpa Garrison Keillor, "Lake Wobegon Days"
hollen@mana.UUCP (10/01/87)
In article <309@ncrcan.UUCP> brian@ncrcan.UUCP () writes: >In article <4478@amd.AMD.COM> ching@amd.UUCP (Mike Ching) writes: >>.... The NOPs are never executed and don't slow down the >>processor. >> >>mike ching > >Sorry, but the NOPS are always executed (how would the processor know that >it is in fact a NOP, if it didn't execute it) and each execution takes >a finite, albeit minimal amount of execution time. Sorry, Brian, but in almost all cases, the NOP's ARE NEVER EXECUTED. This is because the assembler places them just after a JMP instruction. Since the path of execution goes AROUND the NOP, it is not executed. Reading the several replies to the original question would have told you this. Dion Hollenbeck (619) 455-5590 x2814 Megatek Corporation, 9645 Scranton Road, San Diego, CA 92121 {sdcsvax,hplabs}!hp-sdd!megatek!hollen {sdcsvax,seismo}!esosun!
perkins@bnrmtv.UUCP (10/02/87)
In article <6375@ut-ngp.UUCP>, ayac071@ut-ngp.UUCP (William T. Douglass) writes: > Actually, I thought that NOPs did an OR of the AX register on itself (or some > similar operation that causes no change to data.) ORing a register with itself sets the flags. OR AX,AX is the simplest way of determining if AX is positive, negative, or zero. NOP is XCHG AX,AX. Since XCHG doesn't affect flags, this actually causes no data to change. -- {hplabs,amdahl,ames}!bnrmtv!perkins --Henry Perkins It is better never to have been born. But who among us has such luck? One in a million, perhaps.
perkins@bnrmtv.UUCP (10/03/87)
In article <539@cernvax.UUCP>, carsten@cernvax.UUCP (carsten) writes: > Even if the NOP is not executed, it has to be loaded into the instruction > register (the CPU's cannot foresee the NOP (yet))! Hence it slows down > the CPU! Nope. Instruction pre-fetch operates at least as fast (2 bus cycles per byte -- one each for segment and offset) as instruction execution. The only penalty occurs on the first instruction after a branch: that instruction has to be fetched before it can be executed. (There are actually some exceptions, such as when a co-processor hogs the bus and prevents the Bus Interface Unit from fetching instructions, but these are rare.) -- {hplabs,amdahl,ames}!bnrmtv!perkins --Henry Perkins It is better never to have been born. But who among us has such luck? One in a million, perhaps.
kad@ttrdc.UUCP (Keith Drescher) (10/06/87)
In article <2306@sphinx.uchicago.edu> cjdb@sphinx.uchicago.edu (Charles Blair) writes: > >In debugging code written in assembly-language, I notice that MASM >periodically inserts NOP's in places where they don't appear in the >source. I imagine this is done to slow down the processor, but how >does MASM "decide" the appropriate circumstances? > If MASM does insert nops it probably is not to slow down the processor (why would anyone want to slow down the processor) but instead to "pad" a branch instruction that was assumed to be a far reference by pass one and then found to be a near reference by pass 2. Just a thought -KD -- Keith Drescher (kad@ttrdc) | ... You can check out any AT&T | time you like - but you can Computer Systems Division, Skokie, Il. | never leave ... PATH: ...!ihnp4!ttrdc!kad | - Hotel California