home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / CIS_GAME.ARJ / QASMX1.THD < prev    next >
Text File  |  1993-06-24  |  42KB  |  980 lines

  1. _____________________________ Subj: VGA Writes _____________________________
  2.  
  3. Fm: Activision/Infocom 76004,2122              # 193075 
  4. To: Dan R Corritore 70243,1110 (X)             Date: 29-Jul-92  13:24:20
  5.  
  6. Here's a question.  If I'm writing bytes/words (depending on the card) from
  7. system ram to a VGA mode 13H display, and I interleave some processing
  8. between byte/word writes, will the VGA hardare and the AT-BUS still wait
  9. state me?  In other words is:
  10.  
  11.     MOVE VID,AX
  12.     JSR SOMEWHERE
  13.     MOVE VID,AX
  14.     JSR SOMEWHERE
  15.     etc...
  16.  
  17. Faster than...
  18.  
  19.     MOVE VID,AX
  20.     MOVE VID,AX
  21.     etc.
  22.     JSR SOMEWHERE
  23.     JSR SOMEWHERE
  24.  
  25. Thanks,
  26.  
  27. William Volk
  28. ...........................................................................
  29.  
  30. Fm: Hans Peter Rushworth 100031,473            # 193218 
  31. To: Activision/Infocom 76004,2122              Date: 29-Jul-92  19:20:06
  32.  
  33. For a 386 processor (I think also for a 286), there are independant bus and
  34. execution units that are able to overlap execution to some extent. This
  35. means that external cycles should not effect instructions that are
  36. pre-fetched and ready for execution. I'm not sure to what extent the internal
  37. cache of the 486 assists here. So the answer to your question is probably
  38. yes, although I would suggest using this feature to do work on internal
  39. registers rather than CALL subroutines.
  40.  
  41. I suggest you write a test program to determine how much the improvement is.
  42. About the best way to speed performance when writing words to VGA is to
  43. ensure that the target address is on an even boundary. A simple bit of code
  44. should explain this (part stolen from BC++ memcpy) -
  45. ;
  46. ; CX = pixel count (!= 0), DS:SI-> source bitmap, ES:DI->VGA RAM
  47. ;
  48.      test    di,1  ;odd address ???
  49.      je short even ;no, begin with even address
  50.      movsb         ;make it even and move a pixel
  51.      dec     cx    ;fix pixel count (if CX was zero on entry we're in trouble)
  52. even:shr     cx,1  ;convert to words and set carry if odd number of bytes
  53.      rep     movsw ;copy stuff (doesn't effect carry) aligned so 1 mem cycle
  54.                    ;every time for a 16-bit VGA
  55.      adc     cx,cx ;inc CX (set it to 1) if carry set (ends on odd address)
  56.      rep     movsb ;NOTE: doesn't do move if CX is zero
  57.  
  58. The seperate bus I/F overlap and pre-fetch will help absorb the extra
  59. instructions. Hope that helps.
  60.  
  61. Peter.
  62. ...........................................................................
  63.  
  64. Fm: John W. Ratcliff 70253,3237                # 270346 
  65. To: Serge Mathieu 71035,2771 (X)               Date: 30-Dec-92  14:11:11
  66.  
  67. Serge,
  68.  
  69. About the VGA screen copy stuff.
  70.  
  71. I do a REP COMPSD, to do a double word compare to find all double words that
  72. are the same.  Then I do a REPNZ CMPSD to find the number of double words
  73. that are different.  Then back off the pointers, and move only the double
  74. words that are changed to screen ram, and your system ram copy of screen ram.
  75.  Then back up to the top of the loop.  I know it sounds crazy but VRAM is so
  76. slow that this turns out to be anywhere from a lot faster to many, many,
  77. times faster on really slow VGA cards.  A REP COMPSW works just as well, but
  78. use those 32 bit ops whenever you can.  The disadvantage to this method is
  79. you use up more of your precious system ram.  The advantages are huge, and I
  80. hope obvious.  
  81.  
  82. I haven't really thought about this aproache for a panning/scrolling type
  83. environment.  I think more from the simulation standpoint where you a
  84. re-rendering an entire screen, at extremely high frame rate, and most of the
  85. pixels are the same color from frame to frame, just by the nature of you
  86. rendering system.  If most of the pixels are changing, then this method
  87. sucks.   My wireframe demo points this out quite nicely.
  88. ...........................................................................
  89.  
  90. Fm: Randy @ Safari 71165,3600                  # 283754 
  91. To: Serge Mathieu 71035,2771                   Date: 22-Jan-93  19:49:11
  92.  
  93. I don't know if you got a solid reply yet but on all my systems, when
  94. blitting to video memory, writing words to odd addresses will slow the blit
  95. down by as much as 50%, depending on the video card.
  96.  
  97. In normal RAM, odd word writes will cause a penalty of 33%,  regardless of
  98. cache or processor speed. This is because instead of accessing the MMU
  99. (memory management unit) and writing once, the instruction has to write,
  100. access the MMU, and write again.
  101. ...........................................................................
  102.  
  103. Fm: John Dlugosz [ViewPoint] 70007,4657        # 341935 
  104. To: VOR Technologies Inc 71333,134 (X)         Date: 26-Apr-93  08:38:36
  105.  
  106. A word-aligned MOVSD does not save that much over MOVSW's.  The video bus is
  107. the bottleneck and it still copies the same number of bytes.
  108.  
  109. I used to know how may bus cycles it took for different kinds of transfers,
  110. but I've forgotten.  The numbers I just got empircially indicate 5 or 6 bus
  111. cycles per word.  That seems high.  But it depends on the cards buffer for
  112. recieving data before actually storing it in its own RAM, and how fast that
  113. can get processed depends on the card's timing speed (ram will be buisy
  114. displaying and can't be stored to) as well as how the card was made.  A read
  115. cycle, I recall, takes 850 to 1050 ns all told (but reads can't use the
  116. buffer). 
  117.  
  118. A single function call will take as much as 20 machine clocks (on a '386),
  119. which is _nothing_ compared to the time of copying the memory to video. About
  120. 5 pixels worth!
  121.  
  122. --John
  123.  
  124. ______________________ Subj: Local Variables On Stack ______________________
  125.  
  126. Fm: Hans Peter Rushworth 100031,473            # 261886 
  127. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 14-Dec-92  22:26:11
  128.  
  129. On the subject of tweaks, have you tried aligning all your local variables so
  130. the double words and words are all aligned? You can do this by ordering your
  131. locals so the dwords, words and bytes are all grouped together, then clearing
  132. the lower two bits of the BP, (you also have to ensure that there is a dummy
  133. dword variable at the bottom of the stack frame to cater for the potential
  134. "drop" of the BP. You also have to copy the parameters (if any) to the locals
  135. area.
  136.  
  137. I think this is potentially worthwhile for those functions that exist for a
  138. longish period of time, and where you "run out" of registers.
  139.  
  140. Peter.
  141. ...........................................................................
  142.  
  143. Fm: Hans Peter Rushworth 100031,473            # 262001 
  144. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 15-Dec-92  03:02:28
  145.  
  146. >> What's the effect of clearing the low 2-bits of BP? You're just
  147. subtracting a max of decimal 2 from the value, correct?
  148.  
  149. actually a max of 3 <g>. The reason behind this is that it makes the SS:BP
  150. point at long word address boundary. This means that if (say) you were to
  151. execute the instruction:
  152.  
  153.  LES SI, DWORD PTR [BP-4] ; (for sake of argument) reads 4 bytes of data
  154.  
  155. then a 32 bit wide data bus CPU only needs to do 1 memory bus cycle to read
  156. or write the 4 bytes of data. For this to be effective, you would organise
  157. your local variables so that all the dwords are at the top of the stack
  158. frame, all the words are under that, and finally all the bytes under that.
  159. This then guarantees that when you access a local variable, the minimum
  160. number of memory cycles are needed. Sometimes when the function is called the
  161. stack will be correctly aligned, and this makes no difference, but other
  162. times it may not. 
  163.  
  164. Peter.
  165. ...........................................................................
  166.  
  167. Fm: Mark Betz/Ass't SysOp 76605,2346           # 262161 
  168. To: Hans Peter Rushworth 100031,473 (X)        Date: 15-Dec-92  13:42:06
  169.  
  170. Right, 3. That's two bits worth, correct? <g>. Let me make sure I understand
  171. this: the idea is that the stack will be dword alligned for 32-bit accesses,
  172. and that it won't make any difference to byte-wide or word-wide accesses. One
  173. thing still confuses me (p'raps more than one). Let's say that you have a
  174. stack frame that looks like this on entry to a function:
  175.  
  176.                        dword    <-  BP + 14
  177.                        dword    <-  BP + 10
  178.                        word     <-  BP + 8
  179.                        word     <-  BP + 6
  180.                        byte     <-  BP + 4
  181.                        byte     <-  BP + 2
  182.                        word     <-  saved BP
  183.  
  184. Suppose that BP == 11CA. Clear the lower two bits and you have 11C8. Now BP
  185. points to the word right below the saved BP. Do you simply add in an offset
  186. in order to correctly address the stack values now? MOV AH  [BP+4] gets the
  187. first byte parameter from the stack, instead of MOV AH  [BP+2]. You basically
  188. have to add 2 to all of your offsets. Is that how you'd handle it?
  189.  
  190.                                                         --Mark
  191. ...........................................................................
  192.  
  193. Fm: Hans Peter Rushworth 100031,473            # 262239 
  194. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 15-Dec-92  16:10:10
  195.  
  196. The precise location of the locals [BP-n] doesn't matter naturally, but the
  197. function parameters cannot be accessed using [BP+n], so you need to copy them
  198. into the local data area, and use the local copies. Just copy the BP into
  199. BX (for example) before masking it, and then use BX to move the parameters.
  200.  
  201. Two other things:
  202.  
  203. (1) you have to allocate an extra (dummy) long word local at the bottom of
  204. the local stack frame, so that if BP is decremented by 3 accessing the
  205. bottom local won't blow the stack.
  206.  
  207. (2) You need to save the original (unmasked) BP so that you can copy this
  208. value back into SP at the end of the function, (normally you copy BP->SP),
  209. instead you just load SP from this saved value (which could be another
  210. local). Example:
  211.  
  212.    push bp             ;save stack frame
  213.    mov  bp,sp          ;new stack frame
  214.    mov  bx,bp          ;keep copy of original frame
  215.    and  bp,0FFFCh      ;align BP
  216.    sub  sp,FRAMESIZE   ;allocate space
  217.    push di             ;save register variables
  218.    push si             ;
  219.    mov  [bp-SAVEBP],bx ;save original BP
  220.    mov  ax,ss:[bx+6]   ;get arg1
  221.    mov  [bp-param1],ax ;copy it ... same for other args
  222.    --- rest of function ----
  223.    pop  si             ;restore register vars
  224.    pop  di             ;
  225.    mov  sp,[bp-SAVEBP] ;original frame
  226.    pop  bp             ;callers bp
  227.    retf                ;exit
  228.  
  229. Peter.
  230.  
  231. _____________________ Subj: Function Arguments on Stack _____________________
  232.  
  233. Fm: Hans Peter Rushworth 100031,473            # 261555 
  234. To: Jesse 76646,3302 (X)                       Date: 14-Dec-92  14:10:26
  235.  
  236. >> what IS pushed by a function automatically?
  237.  
  238. Normal function:
  239.  
  240.      High memory
  241.  
  242.        argn   <-- calling function pushes arguments in reverse order
  243.        arg2       eg f( arg1, arg2, ..., argn )
  244.        arg1
  245.  <return address> <--- the CALL instruction pushes the IP or CS:IP (model
  246.                        dependant) of the next instruction of the calling func
  247. _______________________ENTERS NEW FUNCTION_________________________________
  248.             BP     <--- The called function saves old the Base pointer
  249.                         and moves this stack address into the new BP
  250.   <local variables><--- The stack pointer is adjusted to make space
  251.                         for the functions local (automatic) variables
  252.             DI     <--- The called function pushes register variables
  253.      SP:    SI          (I may have the order wrong here)
  254.   <rest of stack>  <--- used for temporary pushes and pops, other function
  255.                         calls and interrupts.
  256.      Low memory
  257.  
  258. Cleanup on exit: first SI and DI are popped, then BP is copied  back into
  259. SP, SP now points at the calling functions BP on the stack. BP is popped
  260. and a RET is performed, returning to the calling function. The function
  261. will usually do an ADD SP,n to "remove" the arguments it placed on the stack.
  262. The function return value is placed in AX or DX:AX depending on the size.
  263. The called function accesses variables using BP, positive offsets are used
  264. for the function actual parameters, and negative ones for the locals.
  265.  
  266. When an interrupt occurs (hardware or software) the following is pushed on
  267. the stack by the CPU
  268.  
  269.        FLAGS register <-- after the push the interrupt mask is set.
  270.        CS
  271.        IP
  272.        AX
  273.        BX
  274.        CX
  275.        DX
  276.        ES
  277.        DS
  278.        SI           <--- Register varaibles are automatically saved
  279.        DI                neither function explicitly saves or restores them
  280.        BP           <--- The SP at this address is copied into the BP below
  281. ____________________________________ Enters interrupt handler_______
  282.  <local variables>  <--- The function does a SUB SP,n to allocate space
  283.                          for local variables, and sets up DS to point to
  284.                          the handlers data segment.
  285. SP:
  286.  <rest of stack>    <--- used for push pop etc
  287.  
  288. Cleanup: The BP is copied back into the SP, and a IRET instruction is
  289. executed, which reloads all the registers. (the function may modify the
  290. registers on the stack to return values if this is a software interrupt,
  291. but for hardware interrupts the registers on the stack must be READ ONLY).
  292.  
  293. I hope that is more or less a correct description.
  294.  
  295. Peter.
  296.  
  297. BTW, did you realise that the LOOP instruction on a 386/486 is actual SLOWER
  298. than the equivalent seperate decrement and branch instructions?
  299. ...........................................................................
  300.  
  301. Fm: Mark Betz/Ass't SysOp 76605,2346           # 266171 
  302. To: Jesse 76646,3302 (X)                       Date: 22-Dec-92  11:35:30
  303.  
  304. Hi, Jesse. If you're saving all of the registers, then there's probably no
  305. harm in using PUSHA/POPA, unless there are some hidden side effects that I'm
  306. not aware of. However, there are registers that you don't need to save, even
  307. if you're using them. AX is one, since the compiler expects it to be used for
  308. return values. Also, SP isn't really restored, since it's value is discarded
  309. by the POPA instruction, not copied back into the register. So there's 2 that
  310. the instruction isn't needed for. That leaves 6. A PUSHA takes 18 clocks on
  311. the 386, while PUSH only requires 2. POPA takes 24 clocks on the 386, and POP
  312. takes 4. So you're wasting 6 clocks on the PUSHA, but the POPA works out
  313. even. If the function is one that is called in a tight loop, say 10,000
  314. times, then you're blowing off 60,000 clocks <g>. 
  315.  
  316. _______________________ Subj: 386 Instruction Timing _______________________
  317.  
  318. Fm: KGliner 70363,3672                         # 318190 
  319. To: all                                        Date: 21-Mar-93  22:53:29
  320.  
  321.    A simple asm question for you all:
  322.  
  323.    On a 386, do these instructions take the same amount of time or is one
  324. faster than the other:
  325.  
  326.    mov [si],al
  327.    mov [si + 512],al
  328. ...........................................................................
  329.  
  330. Fm: Mike W. Smith 75300,3434                   # 318283 
  331. To: KGliner 70363,3672 (X)                     Date: 22-Mar-93  01:59:24
  332.  
  333. KG>On a 386, do these instructions take the same amount of time or is one
  334. KG>faster than the other:
  335.  
  336. KG>   mov [si],al KG>   mov [si + 512],al
  337.  
  338. On a 386, a "MOV mem,reg" is 2 clock cycles for any effective address.
  339. ...........................................................................
  340.  
  341. Fm: Randy @ Safari 71165,3600                  # 318977 
  342. To: Mike W. Smith 75300,3434 (X)               Date: 23-Mar-93  09:20:46
  343.  
  344. Except when an offset is used and that takes 1 cycle per byte of offset. If
  345. the offset is BYTE, one cycle. If the offset is WORD, two cycles.
  346.  
  347. At least that's what Turbo Profiler says when I run the test.
  348.  
  349. Randy 
  350. ...........................................................................
  351.  
  352. Fm: Mike W. Smith 75300,3434                   # 319385 
  353. To: Randy @ Safari 71165,3600                  Date: 23-Mar-93  23:50:43
  354.  
  355. RS>Except when an offset is used and that takes 1 cycle per byte of offset.
  356. RS>If the offset is BYTE, one cycle. If the offset is WORD, two cycles.
  357.  
  358. That's different from what my tech reference says.  A MOV reg,mem takes the
  359. same time whether it's a byte or word.   For 8086/88 processors the effective
  360. address adds anywhere from 5 to 14 clock cycles to an instruction. For
  361. 286/386 processors, the only case where an extra clock is added is when all
  362. three indexing elements are used (base, index, and displacement).
  363. ...........................................................................
  364.  
  365. Fm: Randy @ Safari 71165,3600                  # 320207 
  366. To: Mike W. Smith 75300,3434 (X)               Date: 25-Mar-93  09:22:21
  367.  
  368. ->That's different from what my tech reference says.  A MOV reg,mem ->takes
  369. the same time whether it's a byte or word
  370.  
  371. That's true, except when you use an offset like [si+512] which causes and ADD
  372. to be performed prior to the fetch. My timings are as such
  373.  
  374. 10,000 iterations (includes loop time)
  375. mov al,[si]         .0047
  376. mov al,[si+512]     .0051/.0052 (fluctuated)
  377.  
  378. That was the original question, right? 
  379.  
  380. _____________________________ Subj: 32 Bit Code _____________________________
  381.  
  382. Fm: Sarwan Narine 76675,164                    # 319332 
  383. To: All                                        Date: 23-Mar-93  22:17:49
  384.  
  385. Consider the following instructions:
  386.    #1.  MOV AL, DS:[SI]
  387.    #2.  MOV AL, DS:[ESI]
  388.  
  389. These instructions can be used to accomplish the same task.  However, under
  390. certain circumstances instruction #2 will fail.  If SMARTDRV is _not_ loaded
  391. then instruction #2 causes a hang-up, however, a CTRL-ALT-DEL will reset my
  392. system.  What does SMARTDRV do to enable instruction #2 to execute?  BTW, my
  393. program is written for 32-bit CPUs only.  Thanks for any insight.
  394. ...........................................................................
  395.  
  396. Fm: Jaimi McEntire 71700,1202                  # 319345 
  397. To: Sarwan Narine 76675,164                    Date: 23-Mar-93  22:38:05
  398.  
  399. Sarwan, if your code before that loaded si (because you wanted a word), the
  400. esi register could have trash in the upper 16 bits. in that case, you would
  401. definitely need to either clear out esi (mov esi,0 ) before loading it, or
  402. you would need to extend it as you moved it (cwde).  Just as a side note, you
  403. can of course use any 32 bit register as an index on the 386, if you did not
  404. know that. also, you can use FS and GS too. all you need to do (if you are
  405. using borland c) is compile by assembly. P.S. Smartdrv probably enables #2 to
  406. execute because it clears the registers, because it too has 32 bit code. 
  407.  
  408. Jaimi
  409. ...........................................................................
  410.  
  411. Fm: Bruce Nehlsen 76535,2466                   # 319363 
  412. To: Jaimi McEntire 71700,1202 (X)              Date: 23-Mar-93  23:00:26
  413.  
  414. Sarwan -
  415.  
  416. Another comment, since I had the same problem, except my code would CRASH if
  417. and only if EMM386 was loaded.
  418.  
  419. Anyway, in my case it turned out to be my assembly directives. In some
  420. modules I used <.code, .data> , and in some I used < DATA SEG ">.  In one of
  421. those 2 methods, the assembler was inserting ENTER and LEAVEs, which made a
  422. big mess, since I already had those in there.
  423.  
  424. Bottom line - check the .LST file, and ensure that what you WROTE is what the
  425. assembler generated.
  426.  
  427. Later...
  428. ...........................................................................
  429.  
  430. Fm: Dan Corritore 70243,1110                   # 319394 
  431. To: Sarwan Narine 76675,164                    Date: 24-Mar-93  00:05:40
  432.  
  433. Another thing I'd like to add to what the others have said is that you can't
  434. use a value greater than 65535 in ESI if you have not changed the segment
  435. limit stuff on the computer. The 386 (or higher) computer starts up with the
  436. segment limits set to be 65535. If you can, always debug 386-specific code
  437. with a 386-specific debugger.. it'll allow you to see things other debuggers
  438. won't (and also capture exceptions --one of which is activated by using
  439. invalid segment limits).
  440.         _Dan  
  441. ...........................................................................
  442.  
  443. Fm: rod lentz 71163,57                         # 319438 
  444. To: Dan Corritore 70243,1110 (X)               Date: 24-Mar-93  02:53:58
  445.  
  446.     re: segment limits, &c...
  447.     By my understanding, most machines running under DOS these days
  448. are actually running in a virtual 86 (managed by emm386 or similar)
  449. most of the time.  In v86 mode, as I understand it, the segment limit
  450. is always 0xffff.  Therefore, without switching to protected mode
  451. (via VCPI/DPMI/whatever), there shouldn't be any advantage to using
  452. a dword subscript (such as [esi]).
  453.     Anybody care to confirm/refute this ?
  454.  
  455.         - Rod
  456. ...........................................................................
  457.  
  458. Fm: Rob Nicholson (HMS Ltd) 100060,154         # 319468 
  459. To: rod lentz 71163,57 (X)                     Date: 24-Mar-93  05:40:20
  460.  
  461. There appears to be a 'fudge' that allows the segments to be >65535 in real
  462. mode. One of the memory managers or disk caches (can't remember which) left
  463. the segments unbounded.
  464.  
  465. Rob.
  466. ...........................................................................
  467.  
  468. Fm: Dan Corritore 70243,1110                   # 319725 
  469. To: rod lentz 71163,57 (X)                     Date: 24-Mar-93  15:57:14
  470.  
  471.         You are right. There is no advantage at all to using ESI over SI
  472. without going into protected mode and switching the segment limit stuff
  473. yourself (or having one of those DOS extenders, I believe). If you have to do
  474. it yourself, get a 386 or 486 specific book which deals with that kind of
  475. stuff(or both).. I'm planning on doing so one day when I feel the need for
  476. stuff like that. Well, anyway, that stuff doesn't stop you from using the
  477. 32-bit registers and 32-bit instructions, though, so play with them all you
  478. want!<g>
  479.         _Dan  
  480. ...........................................................................
  481.  
  482. Fm: rod lentz 71163,57                         # 319954 
  483. To: Dan Corritore 70243,1110                   Date: 24-Mar-93  21:22:54
  484.  
  485.     Rob - I've heard about the glitch/feature that allows segments
  486. > 64k in real mode, but like I said, most PC's are spending most of
  487. their time in v86 mode these days, where I don't believe it works.
  488. And unfortunately, the predominant protected mode spec in use is
  489. VCPI; has anybody else tried sifting through that one ?  Not the
  490. easiest spec I've seen...
  491.     Dan - I have been using the 32 bit reg's for math & stuf; I was
  492. just hoping somebody knew of a way to do 32-bit addressing from
  493. inside v86 mode.  Segmented far pointers are a big clock-killer in
  494. most of my apps.
  495.  
  496.         - Rod
  497. ...........................................................................
  498.  
  499. Fm: Jaimi McEntire 71700,1202                  # 321511 
  500. To: Dan Corritore 70243,1110                   Date: 27-Mar-93  10:42:03
  501.  
  502. Oh, one other thing - you need to ignore the segment registers in flat model.
  503. instead of using ES:DI, you would just use EDI. (or any other index or
  504. general register for that matter).
  505.  
  506. Jaimi
  507. ...........................................................................
  508.  
  509. Fm: rod lentz 71163,57                         # 320768 
  510. To: Rob Nicholson (HMS Ltd) 100060,154         Date: 26-Mar-93  04:42:26
  511.  
  512.     Nope, (real mode != v86) !  Very similar, but not the same.
  513. In v86 mode, a "supervising" program is needed to handle details of
  514. the virtualization (virtual to physical memory mapping, &c.).
  515.     Also, from v86 mode you can't take advantage of the glitch/feature
  516. of the 386/486's, where you can load the segment limits with large
  517. (4 gig !) values in protected mode, switch back to real mode, and
  518. then access huge segments from real mode.
  519.  
  520.         - Rod
  521. ...........................................................................
  522.  
  523. Fm: Randy @ Safari 71165,3600                  # 321275 
  524. To: Serge Mathieu 71035,2771 (X)               Date: 26-Mar-93  22:53:07
  525.  
  526. Well, for one...
  527.  
  528. Movs to and from memory in Protected mode can take as much as 18
  529. machine cycles as compared to 2 to 5 for a real mode 386 or 486 respectively.
  530. This is your MAJOR slowdown.
  531.  
  532. I can't quote other speeds cause I've left my docs at home. But I am sure
  533. some of the other memory intensive functions like AND/OR/XOR have the same
  534. problem. 
  535.  
  536. Randy
  537. Safari  
  538. ...........................................................................
  539.  
  540. Fm: Randy @ Safari 71165,3600                  # 321274 
  541. To: Serge Mathieu 71035,2771 (X)               Date: 26-Mar-93  22:52:45
  542.  
  543. Ok, here goes..
  544.  
  545. in REAL mode, you have this...
  546.  
  547. +---------------------------+  0K
  548. |                           |
  549. ~                           ~
  550. |                           |
  551. +---------------------------+ 640k
  552. |                           |
  553. |                           |
  554. |                           |
  555. |                           |
  556. +---------------------------+ Top of memory (max for machine)
  557.  
  558. the first part is what you can address directly from your program.  The
  559. second part MUST be addressed through a memory manager and is EXTREMELY slow.
  560.  
  561. In REAL FLAT MODE, you have the same thing, but (a) a FLAT MODEL HEAP MANAGER
  562. allocates far memory quickly in blocks much larger than the page frame
  563. (usually 64k) of EMS or XMS, and (b) you can access all of the allocated
  564. memory with one instruction.
  565.  
  566. for example, in real mode, to access memory WITHIN the 640k boundary you must
  567. do this (or the same thing some other way<g>)
  568.  
  569. asm  les di, dword ptr [some_ptr]  ; some_ptr is the FAR address
  570. asm  mov al, byte ptr es:[di]      ; this eats cycles cause of the
  571.                                    ; ES segment override.
  572.  
  573. in REAL FLAT MODE, you do this
  574.  
  575. asm  mov ebx, dword [some_ptr]     ; loads all 32 bits into EBX
  576.                                                         ; this is also faster
  577. than LES DI
  578. asm     mov al,byte [EBX]                       ; 5 cycles maximum
  579.  
  580. in proteced mode, you do the same as in REAL FLAT MODE but it takes longer
  581. because the processor is handling many tasks (internal and external), as well
  582. as watching for segment overruns, at one time.
  583.  
  584. I'll post more tomorrow.
  585.  
  586. Randy
  587. Safari  
  588. ...........................................................................
  589.  
  590. Fm: rod lentz 71163,57                         # 321380 
  591. To: Randy @ Safari 71165,3600                  Date: 27-Mar-93  04:58:29
  592.  
  593.     Randy -
  594.     Now, by "real flat mode", I assume you're using the trick of
  595. loading up large selectors in protected mode, then switching back
  596. to real mode (i.e., the "seg4g" trick) ?  Which, as I understand,
  597. doesn't work in v86 mode, i.e. anytime emm386 or similar managers
  598. are running ?
  599.     Also, about your statements re:speed in different modes -
  600. to the best of my understanding, all modes operate fairly equally.
  601. The big killers are calling through task gates, and switching to/from
  602. protected mode (which of course is needed for DOS calls, handling
  603. real-mode interrupts, &c.).  As far as the processor watching for
  604. segment overruns, I believe that's done in all modes; it's just
  605. a lot more likely to cause an exception in protected mode.  Am I
  606. mistaken ?
  607.  
  608.         - Rod
  609. ...........................................................................
  610.  
  611. Fm: Mark Betz/Ass't SysOp 76605,2346           # 320453 
  612. To: Serge Mathieu 71035,2771 (X)               Date: 25-Mar-93  18:53:58
  613.  
  614. I don't know that EMS is too slow. You can get 64k pages at a time, so it's
  615. effectively like having a number of segments on tap. You just have to switch
  616. them into the page frame. I'm not very expert on this topic, so I'd best
  617. leave specific performance details to others. If Eric Pinnel is lurking
  618. he'll tell you that the trend is towards 32-bit flat memory model, and I
  619. think he'd be right.
  620.  
  621.                                                         --Mark
  622. ...........................................................................
  623.  
  624. Fm: Rob Nicholson (HMS Ltd) 100060,154         # 320760 
  625. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 26-Mar-93  03:43:29
  626.  
  627. AFAIK, EMS (expanded) is faster than XMS (extended) when used from real mode.
  628. With EMS, 64k can be banked into memory almost instantly. With XMS, you keep
  629. having to copy chunks of memory backwards and forwards between extended and
  630. conventional memory.
  631.  
  632. Rob.
  633. ...........................................................................
  634.  
  635. Fm: Mark Betz/Ass't SysOp 76605,2346           # 321090 
  636. To: Rob Nicholson (HMS Ltd) 100060,154         Date: 26-Mar-93  18:23:02
  637.  
  638. Hi, Rob. Wouldn't you also have to back-shuttle the EMS page if it changed? I
  639. suppose you could use it for read-only stuff.
  640.  
  641.                                                         --Mark
  642. ...........................................................................
  643.  
  644. Fm: Dan Corritore 70243,1110                   # 320656 
  645. To: Serge Mathieu 71035,2771 (X)               Date: 25-Mar-93  22:31:56
  646.  
  647. Yeah, I'd opt for flat mode anyday, but EMS and XMS aren't all that bad to
  648. use. I used EMS very briefly a while ago, but it's speed wasn't that slow.
  649. Anyway, you always access it through a certain frame of memory (usually
  650. D000-DFFF). I used it to just add a spare 64K of memory to my program (to use
  651. just like anything else), but that's not really a good use for it at all..
  652. XMS and the others I really don't know much about, but I'll probably run into
  653. them soon or a later... actually, my PC INTERN book looks like it has a few
  654. good sections on the various ways of accessing extended memory . Oh well,
  655. that's all I could do..
  656.         _Dan  
  657. ...........................................................................
  658.  
  659. Fm: Randy @ Safari 71165,3600                  # 321652 
  660. To: rod lentz 71163,57 (X)                     Date: 27-Mar-93  14:51:54
  661.  
  662. No. The loading of the "large selectors" or the top 16 bits of the 32 bit
  663. registers is not a function of protected mode. Nor is it slower or equally as
  664. fast.
  665.  
  666. Real mode 32 bit moves take 2 to 5 cycles depending on the CPU, 2 for 486, up
  667. to 5 on a 386.
  668.  
  669. In protected mode, you have bounds checking that occurs inside the processor
  670. that takes extra cycles thus causing the incredible lag in MOV times. No
  671. state switching occurs except in the startup where the procesor is told to
  672. ignore segment boundary violations.
  673.  
  674. Randy 
  675. ...........................................................................
  676.  
  677. Fm: rod lentz 71163,57                         # 321737 
  678. To: Randy @ Safari 71165,3600 (X)              Date: 27-Mar-93  17:23:20
  679.  
  680.     So, does real flat mode work with emm386 (or similar) loaded ?
  681. And, if so, do you have any sample code you're willing to share
  682. of how to set it up ?
  683.     Also, what tools are you developing with then ?  I assume mostly
  684. assembler, to get the addressing modes you need.
  685.  
  686.     As far as the bounds checking & other penalties in protected
  687. mode - is this mentioned in the Intel doc's ?  I don't remember seeing
  688. that mentioned.
  689.     And state switching should be needed when running protected mode
  690. under DOS, to handle hardware interrupts, DOS i/o, and interfacing
  691. with all that other real mode code sitting underneath the protected
  692. app.
  693.  
  694.         - Rod
  695. ...........................................................................
  696.  
  697. Fm: Randy @ Safari 71165,3600                  # 321862 
  698. To: rod lentz 71163,57 (X)                     Date: 27-Mar-93  21:16:29
  699.  
  700. No. State switching is not needed.
  701.  
  702. No memory manager, except HIMEM can be loaded as they all put the system in
  703. V86 mode.
  704.  
  705. The tool is called BCCX32 and is put out by Network Systems Design.
  706. (414) 231-3333 out of Oshkosh (b'gosh<g>), Wisconsin.
  707. The guys' name is Jim Dempsey and after looking at his sample code,  it looks
  708. pretty good.
  709.  
  710. BCCX32 is a postprocessor that takes your BCC/TCC generated ASM output from
  711. the compiler and strokes it, optimizes it, and re-generates 32-bit flat model
  712. code that will run as it sits.
  713.  
  714. I know it sounds bizarre but it works.
  715.  
  716. Randy  Safari 
  717. ...........................................................................
  718.  
  719. Fm: rod lentz 71163,57                         # 322004 
  720. To: Randy @ Safari 71165,3600 (X)              Date: 28-Mar-93  00:59:40
  721.  
  722.     Sounds like an interesting tool.  I like the idea of the code
  723. post-processor, so you can still use your compiler; nifty !
  724.     However, the (expected) memory manager conflict bothers me.
  725. In my experience, having the user reconfigure/reboot/&c. is the
  726. type of thing that causes many gripes.  For some of the "turnkey"
  727. systems I work on, it's still a possibility, but for anything aimed
  728. at more general release, I shudder.  What's your experience in
  729. dealing with that ?
  730.  
  731.         - Rod
  732. ...........................................................................
  733.  
  734. Fm: Randy @ Safari 71165,3600                  # 322180 
  735. To: rod lentz 71163,57 (X)                     Date: 28-Mar-93  12:30:24
  736.  
  737. ->experience in dealing with that.
  738.  
  739. None yet. EPIC's doing it with ZONE 66 and I REALLY don't like the
  740. idea but as FLAT model packages become more and more the norm, people
  741. WILL get used to it.
  742.  
  743. Randy 
  744. ...........................................................................
  745.  
  746. Fm: Rob Nicholson (HMS Ltd) 100060,154         # 322060 
  747. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 28-Mar-93  06:19:29
  748.  
  749. As most of our use for EMS is for storing bit-maps, I suppose it's read-only
  750. and it works quite well. XMS copying is much slower for this purpose.
  751.  
  752. Rob.
  753.  
  754. _______________________ Subj: Boolean Sprite Masking _______________________
  755.  
  756. Fm: TIM 76247,1130                             # 343432 
  757. To: ALL                                        Date: 28-Apr-93  14:01:02
  758.  
  759.   Here's one for the blitheads out there... <grin> I want to merge two
  760. sprites, held in character arrays. (Let's call them A and B -- both "unsigned
  761. char".) An individual value of '0' is equivalent to transparency.
  762.   Here's the question: is there a set of strictly Boolean operators that will
  763. let me merge these two arrays? In other words, 
  764.     C = (A & mask) | B,
  765.   where 'mask' is 0xFF everywhere B[?] = 0x00, and 0x00 everywhere else.
  766.   It seems to me that there is no Boolean way to create 'mask' (which looks
  767. like the output of a stepping function), but maybe I'm just not thinking
  768. clearly enough today.
  769.   Loops are EVIL. <grin> Is there a better way?
  770. ...........................................................................
  771.  
  772. Fm: Dan Corritore 70243,1110                   # 343771 
  773. To: TIM 76247,1130 (X)                         Date: 28-Apr-93  22:15:39
  774.  
  775. I can't think of any logical operations, but this is what I'd do (in C, at
  776. least):
  777.  
  778.         C[n]= B[n] ? B[n] : A[n];
  779.  
  780. Sorry.. I can't think of any better way then to test for 0!
  781.  
  782. Now, in assembly, there is a neat trick which can be performed on 486+
  783. processors, which doesn't require a jump. Here it is:
  784.  
  785.         mov ah,B[n]     ; pseudo-code -ish (implement how you choose)
  786.  
  787.         mov al,0        ; the 'tester'
  788.  
  789.         mov bh,A[n]     ; again, pseudo-code -ish
  790.  
  791. ;Now, here's the tricky part:
  792.  
  793.         cmpxchg ah,bh   ; now, ah will equal the correct value
  794.  
  795.         mov C[n],ah     ; pseudo-code ish..
  796.  
  797. There you go! Don't understand? Well, here's how it goes.. the
  798.  'cmpxchg ah,bh' instruction boils down to this:
  799.  
  800.         if (AL==AH) AH=BH;      // remember, AL==0
  801.         else AL=BH;             // this part we don't care about..
  802.  
  803.         // (what we do care about is that it didn't change AH)
  804.  
  805. Which equals, using the above code,
  806.  
  807.         if (B[n]==0) C[n]=A[n];
  808.         else C[n]=B[n];
  809.  
  810. Do you understand?
  811.  
  812.         _Dan
  813.  
  814. P.S. Thanks.. I needed to use my brain today! <g>  
  815. ...........................................................................
  816.  
  817. Fm: Hans Peter Rushworth 100031,473            # 343849 
  818. To: TIM 76247,1130 (X)                         Date: 28-Apr-93  23:39:32
  819.  
  820. >>  where 'mask' is 0xFF everywhere B[?] = 0x00, and 0x00 everywhere else. It
  821. seems to me that there is no Boolean way to create 'mask'
  822.  
  823. Dan's way is correct IMO, but since you ask about how to make the mask:
  824.  
  825.    movzx  ax,byte ptr B[?] ;AL = pixel, AH = 0
  826.    dec    ax               ;AH = 0xFF if B[?] was zero, else 0x00
  827.    inc    al               ;restore AL=pixel
  828.  
  829. Peter.
  830. ...........................................................................
  831.  
  832. Fm: Dan Corritore 70243,1110                   # 344166 
  833. To: Hans Peter Rushworth 100031,473 (X)        Date: 29-Apr-93  13:14:17
  834.  
  835. That's a neat technique for creating the 'mask'. I guess I should've listened
  836. to what he was asking more closely. (instead of giving him a way to do it
  837. without the mask). There's so many tricks you can do in Assembly language,
  838. which is why we love to program in it, yes?<g>
  839.         _Dan  
  840. ...........................................................................
  841.  
  842. Fm: Hans Peter Rushworth 100031,473            # 344189 
  843. To: Dan Corritore 70243,1110 (X)               Date: 29-Apr-93  13:44:03
  844.  
  845. >> so many tricks you can do in Assembly language, which is why we love to
  846. program in it, yes?<g>
  847.  
  848. Absolutely!
  849.  
  850. I still think your C = B ? B : A; or  if(!(C=B)) C=A;
  851.  
  852. is the proper method. But I thought the dec trick was interesting.
  853.  
  854. Peter.
  855. ...........................................................................
  856.  
  857. Fm: John Dlugosz [ViewPoint] 70007,4657        # 343887 
  858. To: TIM 76247,1130 (X)                         Date: 29-Apr-93  00:17:57
  859.  
  860. re loops:  You need a loop to process the thing anyway.  Step through C, A,
  861. and B at the same time, processing one byte. (I assume you have 1 byte per
  862. pixel, packed pixel format)
  863.  
  864. So, create the mask from B just for that byte, when needed, as part of the
  865. main loop.
  866.  
  867. For a hint, look at the way the compiler generates code for the prefix !
  868. operator.  It involves no jumps.
  869.  
  870. However, since you need a jump _anyway_ to get back to the top of the loop,
  871. you can double the loop and have the test on B being zero branch to two
  872. different parts of code which OR's in B and advances or just advances, and
  873. put this _before_ the test, so you still only have exactly one jump per
  874. iteration. 
  875.  
  876. --John
  877. ...........................................................................
  878.  
  879. Fm: Mark 'SAM' Baker 100025,444                # 344146 
  880. To: John Dlugosz [ViewPoint] 70007,4657 (X)    Date: 29-Apr-93  12:48:49
  881.  
  882. All these complications.
  883.  
  884. Surely the fastest and most efficient (in terms of code size) method is :-
  885.  
  886. mov al,b[n]
  887. jnz passover
  888. mov al,a[n]
  889. :passover
  890. mov c[n],al
  891. < this gives you the resultant pixel in c[n], no need to mask or anything >
  892.  
  893.                                 Mark
  894. ...........................................................................
  895.  
  896. Fm: Hans Peter Rushworth 100031,473            # 344190 
  897. To: Mark 'SAM' Baker 100025,444 (X)            Date: 29-Apr-93  13:44:14
  898.  
  899. Mark,
  900.  
  901. >   mov al,b[n] >   jnz passover
  902.  
  903. One small point: unlike nice Motorola processors, the mov instruction does
  904. not effect any flags, so you would need a compare of some sort.
  905.  
  906. Tim's request included a "no branches" constraint, that's why we are being
  907. devious in our ways. <g>
  908.  
  909. Peter.
  910. ...........................................................................
  911.  
  912. Fm: John Dlugosz [ViewPoint] 70007,4657        # 344361 
  913. To: Mark 'SAM' Baker 100025,444 (X)            Date: 29-Apr-93  18:39*32
  914.  
  915. <<Surely the fastest and most efficient (in terms of code size) method is>>
  916.  
  917. Smallest code, but not the fastest!  jumps are _expensive_.  We go to great
  918. lengths to avoid them.  Figure 7 clocks plus pipeline delays for your "jnz
  919. passover".  That is half the time it takes to multiply, or longer than all
  920. the rest of the instructions in that loop combined.
  921. ...........................................................................
  922.  
  923. Fm: Dan Corritore 70243,1110                   # 344165 
  924. To: John Dlugosz [ViewPoint] 70007,4657 (X)    Date: 29-Apr-93  13:14:12
  925.  
  926. Yeah.. I forgot about the ! operator. It should be easy to create a mask
  927. doing that.. as such:
  928.  
  929.         mask= -!B[?];   // do a 'not' and then negate it
  930.  
  931. This way, it will be either -1 (0xff) for a zero value or 0 for a non-zero
  932. value.
  933.  
  934.         _Dan  
  935. ...........................................................................
  936.  
  937. Fm: Mark 'SAM' Baker 100025,444                # 344151 
  938. To: TIM 76247,1130 (X)                         Date: 29-Apr-93  12:54:07
  939.  
  940. Why do you need to bother with all this masking.
  941.  
  942. In pseudo-assembler, try this :-
  943.  
  944. mov al,b[n]
  945. jnz not_b
  946. mov al,a[n]
  947. not_b:
  948. mov c[n],al
  949.  
  950. This gives you the correct result, without any recourse to booleans.
  951. I think it is probably also the fastest, and the most efficient in code size
  952. that you will find.
  953.  
  954. OK, a purist wouldn't like the jump (it is a GOTO by any other name), but you
  955. can't avoid them in assembler.
  956.  
  957. procedure BIT_SET;
  958. begin
  959.   C[n]:=B[n];
  960.   if (C[n] = 0) then C[n]:=A[n];
  961. end;
  962.  
  963.                                 Mark
  964. ...........................................................................
  965.  
  966. Fm: Hans Peter Rushworth 100031,473            # 344191 
  967. To: Mark 'SAM' Baker 100025,444 (X)            Date: 29-Apr-93  13:44:20
  968.  
  969. Sorry for the repeat:
  970.  
  971. >> mov al,b[n] >> jnz not_b
  972.  
  973. You must insert a cmp al,0 or "or al,al" to correctly set the zero flag. The
  974. mov instruction does not effect it.
  975.  
  976. Peter.
  977. ...........................................................................
  978.  
  979.  
  980.