home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH25 / IMGPRCS4.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-08-05  |  7.6 KB  |  353 lines

  1. ; IMGPRCS.ASM
  2. ;
  3. ; An image processing program (Second optimization pass).
  4. ;
  5. ; This program blurs an eight-bit grayscale image by averaging a pixel
  6. ; in the image with the eight pixels around it.  The average is computed
  7. ; by (CurCell*8 + other 8 cells)/16, weighting the current cell by 50%.
  8. ;
  9. ; Because of the size of the image (almost 64K), the input and output
  10. ; matrices are in different segments.
  11. ;
  12. ; Version #1: Straight-forward translation from Pascal to Assembly.
  13. ;
  14. ; Version #2: Three major optimizations. (1) used movsd instruction rather
  15. ;          than a loop to copy data from DataOut back to DataIn.
  16. ;          (2) Used repeat..until forms for all loops.  (3) unrolled
  17. ;          the innermost two loops (which is responsible for most of
  18. ;          the performance improvement).
  19. ;
  20. ; Version #3: Used registers for all variables. Set up segment registers
  21. ;          once and for all through the execution of the main loop so
  22. ;          the code didn't have to reload ds each time through.  Computed
  23. ;          index into each row only once (outside the j loop).
  24. ;
  25. ; Version #4: Eliminated copying data from DataOut to DataIn on each pass.
  26. ;          Removed hazards.  Maintained common subexpressions. Did some
  27. ;          more loop unrolling.
  28. ;
  29. ;
  30. ;    Performance comparisons (66 MHz 80486 DX/2 system).
  31. ;
  32. ;    This code-           2.5 seconds.
  33. ;    2nd optimization pass-     4 seconds.
  34. ;    1st optimization pass-     6 seconds.
  35. ;    Original ASM code-    36 seconds.
  36. ;    Borland Pascal v7.0-    45 seconds.
  37. ;    Borland C++ v4.02-    29 seconds.
  38. ;    Microsoft C++ v8.00-    21 seconds.
  39.  
  40.         .xlist
  41.         include     stdlib.a
  42.         includelib    stdlib.lib
  43.         .list
  44.         .386
  45.         option        segment:use16
  46.  
  47.  
  48.  
  49. dseg        segment    para public 'data'
  50. InName        byte    "roller1.raw",0
  51. OutName        byte    "roller2.raw",0
  52. dseg        ends
  53.  
  54.  
  55. ; Here is the input data that we operate on.
  56.  
  57. InSeg        segment    para public 'indata'
  58.  
  59. DataIn        byte    251 dup (256 dup (?))
  60.  
  61. InSeg        ends
  62.  
  63.  
  64. ; Here is the output array that holds the result.
  65.  
  66. OutSeg        segment    para public 'outdata'
  67.  
  68. DataOut        byte    251 dup (256 dup (?))
  69.  
  70. OutSeg        ends
  71.  
  72.  
  73.  
  74.  
  75. cseg        segment    para public 'code'
  76.         assume    cs:cseg, ds:dseg
  77.  
  78. Main        proc
  79.         mov    ax, dseg
  80.         mov    ds, ax
  81.         meminit
  82.  
  83.         mov    ax, 3d00h    ;Open input file for reading.
  84.         lea    dx, InName
  85.         int    21h
  86.         jnc    GoodOpen
  87.         print
  88.         byte    "Could not open input file.",cr,lf,0
  89.         jmp    Quit
  90.  
  91. ; Optimization modification- read the data into DataOut rather than
  92. ; DataIn because we'll move it into DataIn at the beginning of the
  93. ; h loop.
  94.  
  95. GoodOpen:    mov    bx, ax        ;File handle.
  96.         mov    dx, InSeg    ;Where to put the data.
  97.         mov    ds, dx
  98.         lea    dx, DataIn
  99.         mov    cx, 256*251    ;Size of data file to read.
  100.         mov    ah, 3Fh
  101.         int    21h
  102.         cmp    ax, 256*251    ;See if we read the data.
  103.         je    GoodRead
  104.         print
  105.         byte    "Did not read the file properly",cr,lf,0
  106.         jmp    Quit
  107.  
  108. GoodRead:       print
  109.         byte    "Enter number of iterations: ",0
  110.         getsm
  111.         atoi
  112.         free
  113.         mov    bp, ax
  114.         cmp    ax, 0
  115.         jle    Quit
  116.  
  117.         print
  118.         byte    "Computing Result",cr,lf,0
  119.  
  120.  
  121.         assume    ds:InSeg, es:OutSeg
  122.  
  123.         mov    ax, InSeg
  124.         mov    ds, ax
  125.         mov    ax, OutSeg
  126.         mov    es, ax
  127.  
  128. ; Copy the data once so we get the edges in both arrays.
  129.  
  130.         mov    cx, (251*256)/4
  131.         lea    si, DataIn
  132.         lea    di, DataOut
  133.     rep    movsd
  134.  
  135.  
  136. ; "hloop" repeats once for each iteration.
  137.  
  138. hloop:
  139.         mov    ax, InSeg
  140.         mov    ds, ax
  141.         mov    ax, OutSeg
  142.         mov    es, ax
  143.  
  144. ; "iloop" processes the rows in the matrices.
  145.  
  146.         mov    cl, 249
  147. iloop:        mov    bh, cl            ;i*256
  148.         mov    bl, 1            ;Start at j=1.
  149.         mov    ch, 254/2        ;# of times through loop.
  150.         mov    si, bx
  151.         mov    dh, 0            ;Compute sum here.
  152.         mov    bh, 0
  153.         mov    ah, 0
  154.  
  155. ; "jloop" processes the individual elements of the array.
  156. ; This loop has been unrolled once to allow the two portions to share
  157. ; some common computations.
  158.  
  159. jloop:
  160.  
  161. ; The sum of DataIn [i-1][j] + DataIn[i-1][j+1] + DataIn[i+1][j] +
  162. ; DataIn [i+1][j+1] will be used in the second half of this computation.
  163. ; So save its value in a register (di) until we need it again.
  164.  
  165.         mov    dl, DataIn[si-256]    ;[i-1,j]
  166.         mov    al, DataIn[si-255]    ;[i-1,j+1]
  167.         mov    bl, DataIn[si+257]    ;[i+1,j+1]
  168.         add    dx, ax
  169.         mov    al, DataIn[si+256]    ;[I+1,j]
  170.         add    dx, bx
  171.         mov    bl, DataIn[si+1]    ;[i,j+1]
  172.         add    dx, ax
  173.         mov    al, DataIn[si+255]    ;[i+1,j-1]
  174.  
  175.         mov    di, dx            ;Save partial result.
  176.  
  177.         add    dx, bx
  178.         mov    bl, DataIn[si-1]    ;[i,j-1]
  179.         add    dx, ax
  180.         mov    al, DataIn[si]        ;[i,j]
  181.         add    dx, bx
  182.         mov    bl, DataIn[si-257]    ;[i-1,j-1]
  183.         shl    ax, 3            ;DataIn[i,j] * 8.
  184.         add    dx, bx
  185.         add    dx, ax
  186.         shr    ax, 3            ;Restore DataIn[i,j] value.
  187.         shr    dx, 4            ;Divide by 16.
  188.         add    di, ax
  189.         mov    DataOut[si], dl
  190.  
  191. ; Okay, process the next cell over.  Note that we've got a partial sum
  192. ; sitting in DI already.  Don't forget, we haven't bumped SI at this point,
  193. ; so the offsets are off by one.  (This is the second half of the unrolled
  194. ; loop.)
  195.  
  196.         mov    dx, di            ;Contains partial sum.
  197.         mov    bl, DataIn[si-254]    ;[i-1,j+1]
  198.         mov    al, DataIn[si+2]    ;[i,j+1]
  199.         add    dx, bx
  200.         mov    bl, DataIn[si+258]    ;[i+1,j+1];
  201.         add    dx, ax
  202.         mov    al, DataIn[si+1]    ;[i,j]
  203.         add    dx, bx
  204.         shl    ax, 3            ;DataIn[i][j]*8
  205.         add    si, 2            ;Bump array index.
  206.         add    dx, ax
  207.         mov    ah, 0            ;Clear for next loop iter.
  208.         shr    dx, 4            ;Divide by 16
  209.         dec    ch
  210.         mov    DataOut[si-1], dl
  211.         jne    jloop
  212.  
  213.         dec    cl
  214.         jne    iloop
  215.  
  216.         dec    bp
  217.         je    Done
  218.  
  219.  
  220. ; Special case so we don't have to move the data between the two arrays.
  221. ; This is an unrolled version of the hloop that swaps the input and output
  222. ; arrays so we don't have to move data around in memory.
  223.  
  224.         mov    ax, OutSeg
  225.         mov    ds, ax
  226.         mov    ax, InSeg
  227.         mov    es, ax
  228.         assume    es:InSeg, ds:OutSeg
  229.  
  230. hloop2:
  231.  
  232.         mov    cl, 249
  233. iloop2:        mov    bh, cl
  234.         mov    bl, 1
  235.         mov    ch, 254/2
  236.         mov    si, bx
  237.         mov    dh, 0
  238.         mov    bh, 0
  239.         mov    ah, 0
  240. jloop2:
  241.         mov    dl, DataOut[si-256]
  242.         mov    al, DataOut[si-255]
  243.         mov    bl, DataOut[si+257]
  244.         add    dx, ax
  245.         mov    al, DataOut[si+256]
  246.         add    dx, bx
  247.         mov    bl, DataOut[si+1]
  248.         add    dx, ax
  249.         mov    al, DataOut[si+255]
  250.  
  251.         mov    di, dx
  252.  
  253.         add    dx, bx
  254.         mov    bl, DataOut[si-1]
  255.         add    dx, ax
  256.         mov    al, DataOut[si]
  257.         add    dx, bx
  258.         mov    bl, DataOut[si-257]
  259.         shl    ax, 3
  260.         add    dx, bx
  261.         add    dx, ax
  262.         shr    ax, 3
  263.         shr    dx, 4
  264.         mov    DataIn[si], dl
  265.  
  266.         mov    dx, di
  267.         mov    bl, DataOut[si-254]
  268.         add    dx, ax
  269.         mov    al, DataOut[si+2]
  270.         add    dx, bx
  271.         mov    bl, DataOut[si+258]
  272.         add    dx, ax
  273.         mov    al, DataOut[si+1]
  274.         add    dx, bx
  275.         shl    ax, 3
  276.         add    si, 2
  277.         add    dx, ax
  278.         mov    ah, 0
  279.         shr    dx, 4
  280.         dec    ch
  281.         mov    DataIn[si-1], dl
  282.         jne    jloop2
  283.  
  284.         dec    cl
  285.         jne    iloop2
  286.  
  287.         dec    bp
  288.         je    Done2
  289.         jmp    hloop
  290.  
  291.  
  292. ; Kludge to guarantee that the data always resides in the output segment.
  293.  
  294. Done2:
  295.         mov    ax, InSeg
  296.         mov    ds, ax
  297.         mov    ax, OutSeg
  298.         mov    es, ax
  299.         mov    cx, (251*256)/4
  300.         lea    si, DataIn
  301.         lea    di, DataOut
  302.     rep    movsd
  303.  
  304. Done:        print
  305.         byte    "Writing result",cr,lf,0
  306.  
  307.  
  308. ; Okay, write the data to the output file:
  309.  
  310.         mov    ah, 3ch        ;Create output file.
  311.         mov    cx, 0        ;Normal file attributes.
  312.         mov    dx, dseg
  313.         mov    ds, dx
  314.         lea    dx, OutName
  315.         int    21h
  316.         jnc    GoodCreate
  317.         print
  318.         byte    "Could not create output file.",cr,lf,0
  319.         jmp    Quit
  320.  
  321. GoodCreate:    mov    bx, ax        ;File handle.
  322.         push    bx
  323.         mov    dx, OutSeg    ;Where the data can be found.
  324.         mov    ds, dx
  325.         lea    dx, DataOut
  326.         mov    cx, 256*251    ;Size of data file to write.
  327.         mov    ah, 40h        ;Write operation.
  328.         int    21h
  329.         pop    bx        ;Retrieve handle for close.
  330.         cmp    ax, 256*251    ;See if we wrote the data.
  331.         je    GoodWrite
  332.         print
  333.         byte    "Did not write the file properly",cr,lf,0
  334.         jmp    Quit
  335.  
  336. GoodWrite:    mov    ah, 3eh        ;Close operation.
  337.         int    21h
  338.  
  339.  
  340. Quit:        ExitPgm            ;DOS macro to quit program.
  341. Main        endp
  342.  
  343. cseg        ends
  344.  
  345. sseg        segment    para stack 'stack'
  346. stk        byte    1024 dup ("stack   ")
  347. sseg        ends
  348.  
  349. zzzzzzseg    segment    para public 'zzzzzz'
  350. LastBytes    byte    16 dup (?)
  351. zzzzzzseg    ends
  352.         end    Main
  353.