<?xml version="1.0" encoding="ISO-8859-1"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>DOS ain't dead</title>
<link>http://www.bttr-software.de/forum/</link>
<description>DOS ain't dead</description>
<language>en</language>
<item>
<title>FlWriter version 1.2 released</title>
<content:encoded><![CDATA[<i>Post by georgpotthast, 17.05.2012, 21:37:</i><br /><br />I implemented the suggestions regarding FlWriter in the other thread and released version 1.2 of FlWriter now: <a href="http://code.google.com/p/nanox-microwindows-nxlib-fltk-for-dos/downloads/list">FlWriter 1.2</a><br />
<br />
List of changes:<br />
<br />
- can import Microsoft docx and Openoffice odt files now<br />
- calls Ghostscript to display PDF and PS files on the screen<br />
- linked unrtf into FlWriter instead of being a separate utility<br />
- f.bat calls HDPMI to gain more memory when opening a DOS shell<br />
- reduced size of gs386.exe<br />
- italic text is now correctly written into the PS file<br />
- does not remove empty lines in the text when saving<br />
<br />
So go ahead and give it a try :-) <br />
<br />
Georg]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11495</link>
<pubDate>Thu, 17 May 2012 21:37:57 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from RayeR, 17.05.2012, 01:25:</i><br /><br />Sorry guys, I'm little bit loosing in your high-tech discussion. Just asking if I have to modify something in cm's code? I checked in BOCHS and on real PC too.<br />
<code><br />
NEW_INT13H:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;INT XX do PUSHF, clear IF,TF, PUSH CS,IP (6B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; PUSHF&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;store flags (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; CMP&nbsp; &nbsp; &nbsp;DL,ROMDISK_DRIVE;related to our diskdisku?<br />
&nbsp; &nbsp; &nbsp; &nbsp; JE&nbsp; &nbsp; &nbsp; @NEW_INT13H_HUB ;if yes continue below else<br />
&nbsp; &nbsp; &nbsp; &nbsp; POPF&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;restore flags (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; INT&nbsp; &nbsp; &nbsp;OLD_INT13H&nbsp; &nbsp; &nbsp; ;call old INT 13h handler<br />
&nbsp; &nbsp; &nbsp; &nbsp; PUSH&nbsp; &nbsp; BP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;store BP (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; MOV&nbsp; &nbsp; &nbsp;BP,SP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;set BP to current SP<br />
&nbsp; &nbsp; &nbsp; &nbsp; PUSH&nbsp; &nbsp; AX&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;store AX (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; LAHF&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;load flags[7:0] to AH that was returned by old INT 13h handler<br />
&nbsp; &nbsp; &nbsp; &nbsp; MOV&nbsp; &nbsp; &nbsp;[BP+6],AH&nbsp; &nbsp; &nbsp; &nbsp;;replace previously saved flags[7:0] of INT caller on stack by current flags (SS is implicit)<br />
&nbsp; &nbsp; &nbsp; &nbsp; POP&nbsp; &nbsp; &nbsp;AX&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;restore AX (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; POP&nbsp; &nbsp; &nbsp;BP&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;restore BP (2B)<br />
&nbsp; &nbsp; &nbsp; &nbsp; IRET&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;return from ISR, do POP IP,CS,F (6B)<br />
</code>]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11494</link>
<pubDate>Thu, 17 May 2012 01:25:07 GMT</pubDate>
</item>
<item>
<title>Assembler optimisation - speed, size, etc</title>
<content:encoded><![CDATA[<i>Reply from cm, 16.05.2012, 16:59:</i><br /><br /><i>&gt; Size matters A LOT, especially when you are dealing with DOS programs, and<br /></i><i>&gt; even more when you are dealing with TSR's.  To me, this is not necessarily<br /></i><i>&gt; the size of the executable program file itself, but the amount of memory it<br /></i><i>&gt; ultimately requires.<br /></i>
<br />
So actually we could draw a distinction between &quot;executable size on disk&quot; and &quot;process size in memory&quot;. The latter can even, if applicable, further be split into &quot;transient memory usage&quot; and &quot;resident memory usage&quot;.<br />
<br />
Speaking of which, I'm just now writing an experimental program where I expect the core loop's speed might noticeably affect &quot;user&quot; experience, so to say. Hence, while I could have optimised it for size as usual, I instead put most of that loop into a macro and then use that to write several different variants of the loop code to be used in various circumstances. (For example, the default pair of the loop's variants only handles continuous single file regions up to 8 KiB. In 99% of usage cases, that will suffice, but I added an alternative pair that is able to handle regions up to 512 MiB instead - this is only executed when needed.) This program only ever executes its code in a transient/&quot;foreground&quot; process, so a bit of &quot;wasted&quot; code size isn't very relevant.<br />
<br /><i>&gt; In most<br /></i><i>&gt; (but not all) situations, speed is a relatively minor concern.<br /></i>
<br />
I'd say the speed of most code generally is rather unimportant. To improve timing, one should focus on the parts of their code that the program actually spends a lot of time in. Putting a lot of effort into optimising all of a program's code for speed is unnecessary.<br />
<br /><i>&gt; Even then,<br /></i><i>&gt; though, the speed issues don't usually involve specific CPU instructions,<br /></i><i>&gt; but more a &quot;philosophy&quot; of how to write the program (e.g., minimizing the<br /></i><i>&gt; number of switches between PM and V86/RM).<br /></i>
<br />
True. Just recently, I noticed that a program I was using/developing employed a rather suboptimal algorithm for table lookup. It wasn't a critical problem (at least not on modern CPUs), it just wasn't designed very well. Purely for amusement, I set up a sort of benchmark for the affected algorithm, and determined that my (very simplistic) improvement consistently sped that section up by more than ten times.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11493</link>
<pubDate>Wed, 16 May 2012 16:59:38 GMT</pubDate>
</item>
<item>
<title>Assembler optimisation - how to avoid a jump?</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 16.05.2012, 16:42:</i><br /><br />I'll just to add another two cents worth of opinion.<br />
<br />
There are at least four general categories of things to keep in mind when writing code: speed, size, compatibility, and maintainability.  To me, those are listed in reverse order of priority, though there is a constant balancing act.<br />
<br />
The most important is maintainability, which at a minimum means lots of comments and &quot;logical&quot; organization of the code.<br />
<br />
Compatibility with other programs and standards (even if de facto), even if it means a larger program size, is generally more important than the size.<br />
<br />
Size matters A LOT, especially when you are dealing with DOS programs, and even more when you are dealing with TSR's.  To me, this is not necessarily the size of the executable program file itself, but the amount of memory it ultimately requires.<br />
<br />
Optimizing for speed is an almost endless chasing of your tail, and is not usually very productive.  Something that is optimized for one particular manufacturer or model or stepping (or even cache size) of CPU doesn't mean it is optimized for every scenario, even if you avoid using any special CPU-specific instructions.  You can do certain things in your code that can help the speed if the CPU uses pipelines (and that don't hurt performance if the CPU doesn't have pipelines), but even those can make the code more confusing (harder to understand) and therefore less maintainable.  In most (but not all) situations, speed is a relatively minor concern.  Even then, though, the speed issues don't usually involve specific CPU instructions, but more a &quot;philosophy&quot; of how to write the program (e.g., minimizing the number of switches between PM and V86/RM).]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11492</link>
<pubDate>Wed, 16 May 2012 16:42:46 GMT</pubDate>
</item>
<item>
<title>Assembler optimisation - how to avoid a jump?</title>
<content:encoded><![CDATA[<i>Reply from Rugxulo, 16.05.2012, 10:34:</i><br /><br /><i>&gt; I measured my original code, CM's code and another variant found on<br /></i><i>&gt; internet:<br /></i>
<br />
Could depend on many factors.<br />
<br /><i>&gt; VARIANT 1:<br /></i><i>&gt; <code>sub edx,ecx<br /></i><i>&gt; jnc @RLE_CLIP_MOVE_CONT<br /></i><i>&gt; add ecx,edx<br /></i><i>&gt; @RLE_CLIP_MOVE_CONT:</code><br /></i>
<br />
6 bytes<br />
<br /><i>&gt; VARIANT 2:<br /></i><i>&gt; <code>sub edx, ecx<br /></i><i>&gt; rcr eax, 1<br /></i><i>&gt; sar eax, 31<br /></i><i>&gt; and eax, edx<br /></i><i>&gt; add ecx, eax</code><br /></i>
<br />
11 bytes<br />
<br /><i>&gt; VARIANT 3:<br /></i><i>&gt; <code>sub edx,ecx<br /></i><i>&gt; sbb eax,eax<br /></i><i>&gt; and eax,edx<br /></i><i>&gt; add ecx,eax</code><br /></i>
<br />
8 bytes<br />
<br /><i>&gt; Differences are small. Variants 2 and 3 are slightly faster then V1.<br /></i>
<br />
Jumps usually aren't that expensive, and branch prediction makes them reasonable. Of course, Darek Mihocka says avoid them where possible (e.g. his BOCHS optimizations), but it's such a common thing for x86 that I've never even bothered worrying about it.<br />
<br />
I think even correctly taken jumps cost 2 cycles on a 486. Pentium assumed all backwards jumps were taken and forwards weren't. On a P4, you could also use jump hints, but I'd doubt it would help (much, if at all, might even hurt, who knows).<br />
<br />
It gets more complicated because of EFLAGS and register dependencies, which may or may not cause AGIs (esp. on 486). And some of the more CISC-y instructions (RCR, I assume) will probably not be pariable on a Pentium. PPro/686 has the whole 4-1-1 microcode bullcrap, and don't forget that pipelines fill up faster on older machines, hence sometimes smaller code is better.<br />
<br /><i>&gt; Difference between V2 and V3 is only borderly significant, maybe V3 is<br /></i><i>&gt; sligtly faster but measurement would be must done in pure DOS, not in Win98<br /></i><i>&gt; I am running just now.<br /></i><i>&gt; I made test only on Pentium 4 machine, due lack of time I haven't tested on<br /></i><i>&gt; my Pentium III.<br /></i>
<br />
Pentium 4 has no barrel shifter, so VARIANT 2 will always be slower there (I think?).<br />
<br />
There's honestly nothing horrible about any of these versions, they all work more or less the same. The difference is very very minor. You also have to worry about on-chip cache size, instruction timings, latency / thoroughput, code and data alignment, and avoid nearby self-modifying code. You're probably more limited by OS calls or HD or RAM access speeds.<br />
<br />
It's fun to &quot;pretend&quot; to even barely (0.0001%) understand this stuff, but it's so incredibly arcane and (almost) useless, impossible, etc. (in my unprofessional opinion). There is no easy answer, and I'd doubt anybody really does it well across various x86 subarchitectures. (Some newer ones broke old optimizations, so that really sucks.) I wouldn't worry about it (or choose the safer path of cm and myself, optimize for size!).]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11491</link>
<pubDate>Wed, 16 May 2012 10:34:46 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 15.05.2012, 20:13:</i><br /><br /><i>&gt; This only works if you restore the flags from [bp+6] into the actual flags<br /></i><i>&gt; first, and in that case you'll re-enable TF and IF (if set in the saved<br /></i><i>&gt; flags word) too early - before even calling the ROM BIOS's handler, here.<br /></i><i>&gt; <br /></i><i>&gt; Edited: Actually I did some tests just now because I wasn't sure, and if<br /></i><i>&gt; you do a popf (setting TF) right before an int instruction, then it will<br /></i><i>&gt; trap only after the int has been called. (Verified in Real and (JEMM's)<br /></i><i>&gt; Virtual 86 Mode on my machine.) I don't know/am not sure that the same is<br /></i><i>&gt; true of interrupts and IF respectively though.<br /></i><i>&gt; <br /></i><i>&gt; Then, of course, it would still notionally trap/interrupt too early (ie<br /></i><i>&gt; before popping bp in your above suggestion, instead of after/before the<br /></i><i>&gt; caller's next instruction), but you already know that.<br /></i>
<br />
I'm not sure the TF isn't being &quot;honored&quot; before the INT is being issued, though that's possible (I know there are delays in exactly when an IF change takes effect, but am not sure about TF).  When the INT 85h is issued, the CPU automatically tampers with TF &amp; IF and the ISR will never have TF set on entry, no matter what it was set to when the INT was issued.  There is the potential that the POP BP and the RETF 2 will run with TF set, but that shouldn't actually hurt anything (though I suppose it could potentially confuse the debugger that set the TF).  The state of IF during the few instructions after the INT returns shouldn't hurt anything, either.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11490</link>
<pubDate>Tue, 15 May 2012 20:13:29 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from cm, 15.05.2012, 18:53:</i><br /><br /><i>&gt; INT 85h<br /></i><i>&gt; POP BP<br /></i><i>&gt; RETF 2<br /></i><i>&gt; <br /></i><i>&gt; RETF n usually doesn't even cross my mind as a way to end an ISR, since it<br /></i><i>&gt; has the potential to do undesirable things with the flags as discussed<br /></i><i>&gt; earlier.  In this case, though, it would work just fine, and is more<br /></i><i>&gt; efficient than the IRET solution.<br /></i>
<br />
This only works if you restore the flags from [bp+6] into the actual flags first, and in that case you'll re-enable TF and IF (if set in the saved flags word) too early - before even calling the ROM BIOS's handler, here.<br />
<br />
Edited: Actually I did some tests just now because I wasn't sure, and if you do a popf (setting TF) right before an int instruction, then it will trap only after the int has been called. (Verified in Real and (JEMM's) Virtual 86 Mode on my machine.) I don't know/am not sure that the same is true of interrupts and IF respectively though.<br />
<br />
Then, of course, it would still notionally trap/interrupt too early (ie before popping bp in your above suggestion, instead of after/before the caller's next instruction), but you already know that.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11489</link>
<pubDate>Tue, 15 May 2012 18:53:38 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 15.05.2012, 18:45:</i><br /><br />This morning I thought of an even smaller way to &quot;clean up&quot; after the INT 85h:<br />
<br />
INT 85h<br />
POP BP<br />
RETF 2<br />
<br />
RETF n usually doesn't even cross my mind as a way to end an ISR, since it has the potential to do undesirable things with the flags as discussed earlier.  In this case, though, it would work just fine, and is more efficient than the IRET solution.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11488</link>
<pubDate>Tue, 15 May 2012 18:45:03 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 14.05.2012, 21:42:</i><br /><br /><i>&gt; This will set the Interrupt Flag and/or Trap Flag too early (inside your<br /></i><i>&gt; code) if they were clear for your entry and set for the calling code. Right<br /></i><i>&gt; here, that might not be a concern, but in general this is incorrect and<br /></i><i>&gt; should be avoided (especially if your handler does not return to the caller<br /></i><i>&gt; right after the call it made has returned).<br /></i>
<br />
You are correct.  If you need to do a bunch of &quot;clean-up&quot; or additional processing after issuing the INT 85h (more than simply restoring BP like we do here), you would probably at least want to issue an STI (or CLI, as appropriate).  In this example, the state of TF and IF don't affect or significantly delay anything critical, so it doesn't really matter.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11487</link>
<pubDate>Mon, 14 May 2012 21:42:23 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from cm, 14.05.2012, 20:21:</i><br /><br /><i>&gt; Which is why you may need to be careful when using the INT 85h approach,<br /></i><i>&gt; and make sure the flags in your code immediately before you issue the call<br /></i><i>&gt; are what they should be (the same as what's at your [BP+6]), e.g.:<br /></i>
<br />
This will set the Interrupt Flag and/or Trap Flag too early (inside your code) if they were clear for your entry and set for the calling code. Right here, that might not be a concern, but in general this is incorrect and should be avoided (especially if your handler does not return to the caller right after the call it made has returned).]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11486</link>
<pubDate>Mon, 14 May 2012 20:21:30 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 14.05.2012, 20:16:</i><br /><br /><i>&gt; Anyway In my case I cannot store old vector in my code segment, it's rom<br /></i><i>&gt; segment and I don't have writable memory so this is why I placed into<br /></i><i>&gt; IVT...<br /></i>
<br />
Which is why you may need to be careful when using the INT 85h approach, and make sure the flags in your code immediately before you issue the call are what they should be (the same as what's at your [BP+6]), e.g.:<br />
<br />
  PUSH [BP+6]<br />
  POPF<br />
  INT  85h<br />
<br />
You should also make sure that the flags that are returned by INT 85h are stored unchanged at your [BP+6] when you exit, e.g:<br />
<br />
  INT 85h<br />
  PUSHF<br />
  POP  [BP+6]<br />
  POP  BP<br />
  IRET<br />
<br />
This assumes that BP is not a parameter you need to &quot;pass through&quot;, which is usually a safe assumption (safer than that you do not need to pass the flags through, anyway).  There are ways (more complicated, of course) if you need to pass the original BP through as well.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11485</link>
<pubDate>Mon, 14 May 2012 20:16:38 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from RayeR, 14.05.2012, 18:50:</i><br /><br /><i>&gt; (or whatever).  But, it is important that you do not simply CALL the old<br /></i><i>&gt; ISR like this, unless you're 100% sure your flags haven't changed since the<br /></i><i>&gt; start of your ISR handler:<br /></i><i>&gt; <br /></i><i>&gt; PUSHF<br /></i><i>&gt; CALL CS:[OldVector]<br /></i>
<br />
Anyway In my case I cannot store old vector in my code segment, it's rom segment and I don't have writable memory so this is why I placed into IVT...]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11484</link>
<pubDate>Mon, 14 May 2012 18:50:02 GMT</pubDate>
</item>
<item>
<title>redundant override in &quot;ss:bp&quot; for clarity</title>
<content:encoded><![CDATA[<i>Reply from cm, 14.05.2012, 18:47:</i><br /><br /><i>&gt; My assembler does not insert them, so in my code I put the<br /></i><i>&gt; SS: in there as a form of documentation, to remind myself that I'm working<br /></i><i>&gt; with the stack and not &quot;regular&quot; memory.<br /></i>
<br />
I merely insure to always put bp as the first addend if I address memory using it. So that I'd always use [bp+XX...],  never [XX...+bp]. This way, I can (at least in my own source) quickly tell what segment registers an explicitly specified address uses; it'll either begin with an override &quot;[Xs:&quot; (indicating that segment register naturally), or with &quot;[bp&quot; (indicating ss), or neither of those (indicating ds).<br />
<br />
To regularly use your method, I'd of course first have to extend NASM to have it optimise away redundant overrides - so I lacked that feature in the first place. On the other hand, I might have preferred the convention described above even if I had it, because I sometimes do tend to save some typing if I think it'd be overly redundant.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11483</link>
<pubDate>Mon, 14 May 2012 18:47:44 GMT</pubDate>
</item>
<item>
<title>indirect far jmp - calling old INT problem</title>
<content:encoded><![CDATA[<i>Reply from bretjohn, 14.05.2012, 18:30:</i><br /><br />FWIW, these days (I didn't used to do this) most of my ISR's start as follows:<br />
<br />
  PUSH BP<br />
  MOV  BP,SP<br />
  PUSHF<br />
  STI<br />
  CLD<br />
  ...<br />
<br />
At least in theory, the only difference between the flags at [BP+6] (what will be returned to the caller) and at [BP-2] (the flags I'm working with at the start of my code) will potentially be IF and TF.  However, this is only guaranteed to be the case if I'm the first ISR in the chain and the CPU is the one providing the stack and flag and register input.  If I'm not first, then that may not be the case unless all of the ISR's further up the chain all did things &quot;correctly&quot;.<br />
<br />
Unless a particular INT sub-function uses one of the flags as an input parameter (rare, but does happen, like INT 15.4F, and should never happen in an IRQ handler), making sure the input flags to the next ISR are the same ones that you got isn't necessarily a big deal, since it can test the flags on the stack (at [BP+6]) instead of just doing an immediate JC/JNC (or whatever).  But, it is important that you do not simply CALL the old ISR like this, unless you're 100% sure your flags haven't changed since the start of your ISR handler:<br />
<br />
  PUSHF<br />
  CALL CS:[OldVector]<br />
<br />
In most of my ISR's, if I need to call the old ISR, that's the first thing I do, so I haven't messed with any flags yet and it's not a problem.  If this isn't the case for you, though, at an absolute minimum, you should do a &quot;PUSH [BP+6]&quot; instead of a &quot;PUSHF&quot; here (or something similar).  It is also important that you do this for all interrupts, not just the ones where you think/know it may matter (like INT 15h), since there can be extensions and overloads and other things you don't know about.  You should &quot;emulate&quot; exactly the same thing the CPU does.  I think this may be a major cause over the years of TSR's needing to get installed in a particular order for unknown reasons.<br />
<br />
If I JMP to the old ISR, I do this, guaranteeing that the old ISR gets the same input flags that I did:<br />
<br />
  ...<br />
  POPF<br />
  POP  BP<br />
  JMP  CS:[OldVector]<br />
<br />
If I need to return CF as a parameter, I do one or the other of the following as appropriate, guaranteeing that CF is the only modified flag:<br />
<br />
  OR   B [BP+6],1       ;Set return CF<br />
  AND  B [BP+6],(NOT 1) ;Clear return CF<br />
<br />
Obviously, some of the details need to be modified to some degree if [OldVector] isn't stored in your own memory, or if you need to CALL the old ISR at the middle/end of your ISR instead of the beginning, or ...<br />
<br />
To make code that is &quot;correct&quot;, it's not always possible to make it as small as you would like it to be.<br />
<br />
<br />
Also FWIW, not all assemblers will just automatically insert the SS: override OpCode if you do something like this:<br />
<br />
  OR B SS:[BP+6],1<br />
<br />
Some are &quot;smart enough&quot; to know that the SS: override isn't needed, and some aren't.  My assembler does not insert them, so in my code I put the SS: in there as a form of documentation, to remind myself that I'm working with the stack and not &quot;regular&quot; memory.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11482</link>
<pubDate>Mon, 14 May 2012 18:30:44 GMT</pubDate>
</item>
<item>
<title>Assembler optimisation - variant 3, sbb</title>
<content:encoded><![CDATA[<i>Reply from cm, 14.05.2012, 18:22:</i><br /><br /><i>&gt; VARIANT 3:<br /></i><i>&gt; <code>sub edx,ecx</code><br /></i><i>&gt; <code>sbb eax,eax</code><br /></i><i>&gt; <code>and eax,edx</code><br /></i><i>&gt; <code>add ecx,eax</code><br /></i>
<br />
Oh yeah, I forgot about sbb for that.<br />
<br /><i>&gt; Difference between V2 and V3 is only borderly significant, maybe V3 is<br /></i><i>&gt; sligtly faster but measurement would be must done in pure DOS, not in Win98<br /></i><i>&gt; I am running just now.<br /></i>
<br />
Hmm, even if variant 3 is only a little faster or about equally fast, it's less code and makes the source easier to understand.]]></content:encoded>
<link>http://www.bttr-software.de/forum/forum_entry.php?id=11481</link>
<pubDate>Mon, 14 May 2012 18:22:11 GMT</pubDate>
</item>
</channel>
</rss>
