Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

515 lines
17 KiB

  1. ;** Decoding macros
  2. ;
  3. ; These walk a state machine based on where a command (i.e., char or string)
  4. ; begins.
  5. ;** BitsAt - Extract from bit position n some bits
  6. ;
  7. ; Macro parameter:
  8. ; n bit position to begin extract
  9. ; cbits number of bits to extract
  10. ; Entry: eax working data
  11. ; esi input stream
  12. ; edi output stream
  13. ; Exit: eax updated so that next data begins in al
  14. ; esi/edi updated
  15. ; ecx contains data
  16. ; Uses: none
  17. BitsAt macro n,cbits
  18. .errnz n eq 0
  19. if (n+cbits) lt 8 ; entire operation occurs in low byte
  20. CopyBits cx,ax,n,cbits ; (cx) = desired bits rightmost
  21. elseif (n+cbits) lt 16 ; operation consumes byte
  22. CopyBits cx,ax,n,cbits ; (cx) = desired bits rightmost
  23. lodsb ; (ah/al) = next input
  24. xchg al,ah ; (al/ah) = next input
  25. elseif (n+cbits) eq 16 ; operation consumes remainder of buffered data
  26. CopyBits cx,ax,n,cbits ; (cx) = desired bits rightmost
  27. lodsw ; (al/ah) = next input
  28. else ; operation consumes into unbuffered data
  29. mov ecx,eax
  30. lodsw
  31. shrd cx,ax,n
  32. and ecx,(1 shl cbits)-1
  33. endif
  34. endm
  35. ;** CmdAt - macro that processes a command at a bit position
  36. ;
  37. ; Macro parameter:
  38. ; n bit position where command is expected
  39. ; Entry: eax working data, command begins in al
  40. ; esi points to input stream
  41. ; edi points to output stream
  42. ; Exit: eax updated so that next command begins in al
  43. ; esi/edi updated
  44. ; EXPECTS FALL-THROUGH TO NEXT CmdAT
  45. ; Uses: ecx, edx (not directly, but by virtue of OffsetAt, which
  46. ; in turn calls LengthAt....)
  47. CmdAt macro n
  48. local ca1
  49. align4
  50. public CmdAt&n
  51. CmdAt&n:
  52. if n eq 7
  53. ror eax,1
  54. test al,11b shl 6
  55. rol eax,1
  56. else
  57. test al,11b shl n
  58. endif
  59. jpo ca1
  60. OffsetAt %(n+1)
  61. align4 ; note that OffsetAt jumps away
  62. ca1: ; so there is no fall-through penalty
  63. CharAt %(n+1)
  64. endm
  65. ;** CharAt - macro that processes a character at a bit position
  66. ;
  67. ; Macro parameter:
  68. ; n bit position where char is expected
  69. ; Entry: eax working data, char may be in ah
  70. ; esi input stream
  71. ; edi output stream
  72. ; Exit: eax updated so that next command begins in al
  73. ; esi/edi updated
  74. ; Uses: ch
  75. CharAt macro n
  76. if n eq 8
  77. mov al,ah ; (al) = char for output
  78. XlatChr
  79. CheckOffset
  80. stosb ; store it
  81. lodsw ; (al/ah) = next input
  82. else
  83. if n eq 1
  84. shr eax,1 ; (al) = byte for output
  85. XlatChr
  86. CheckOffset
  87. stosb ; store it
  88. add eax,eax ; (ah) = next byte
  89. lodsb ; (ah/al) = next input
  90. else
  91. mov ch,ah ; (ch) = saved next input
  92. shr eax,n ; (al) = byte for output
  93. XlatChr
  94. CheckOffset
  95. stosb ; store it
  96. lodsb ; (al) = byte-after-next
  97. mov ah,ch ; (ah/al) = next input
  98. endif
  99. xchg al,ah ; (al/ah) = next input
  100. endif
  101. endm
  102. ;** OffsetAt - Parse an offset at a bit position
  103. ;
  104. ; Macro parameter:
  105. ; n bit position where offset is expected
  106. ; Entry: cbits number of bits in offset
  107. ; eax working data, offset may begin in ah
  108. ; esi input stream
  109. ; edi output stream
  110. ; Exit: eax updated so that length begins in al
  111. ; ecx offset
  112. ; esi/edi updated
  113. ; Uses: ecx
  114. OffsetAt macro n
  115. local try8,try12
  116. public OffsetAt&n
  117. OffsetAt&n:
  118. CheckBit a,n ; does a 6-bit offset follow?
  119. jnz try8 ; no, try an 8-bit offset
  120. BitsAt %(n+1),6 ; yes, load it into (ecx) and go
  121. Jump LengthAt,%((n+7) mod 8)
  122. align4
  123. try8:
  124. CheckBit a,%(n+1) ; does an 8-bit offset follow?
  125. jnz try12 ; no, must be a 12-bit offset
  126. BitsAt %(n+2),8 ; yes, load it into (ecx)
  127. add ecx,MAX_6BIT_OFFSET+1 ;
  128. Jump LengthAt,%((n+10) mod 8); go process the following length
  129. align4
  130. try12:
  131. BitsAt %(n+2),12 ; load 12-bit offset into (ecx)
  132. add ecx,MAX_8BIT_OFFSET+1 ;
  133. Jump LengthAt,%((n+14) mod 8); go process the following length
  134. endm
  135. ;** LengthAt - parse off a length at a position and move the bytes
  136. ;
  137. ; LengthAt parses off a length (gamma-prime encoded), moves the
  138. ; relevant string, and dispatches to the next command.
  139. ;
  140. ; Macro parameter:
  141. ; n bit position to begin extract
  142. ; Entry: eax working data
  143. ; ecx offset for string
  144. ; esi input stream
  145. ; edi output stream
  146. ; Exit: eax updated so that next data begins in al
  147. ; esi/edi updated
  148. ; Uses: ecx, edx
  149. LengthAt macro n
  150. local try3,try5,try7,try9,tryGeneral,done,error
  151. % ifidni <LastErrBJump>,<DecodeError>
  152. LastErrBJump equ <error>
  153. endif
  154. align4
  155. public LengthAt&n
  156. LengthAt&n:
  157. jecxz error ; check for 0 offset (illegal)
  158. cmp ecx,SPECIAL_EOS ; check end-of-segment offset
  159. je done ; that's our EOS, so get out
  160. CheckBit a,n ; is this a degenerate encoding?
  161. jz try3 ; no, go for a wider encoding
  162. DoMovs short,2
  163. if n eq 7 ; are we finished with this byte?
  164. lodsb ; (ah/al) is next input
  165. xchg al,ah ; (al/ah) is next input
  166. endif
  167. Jump CmdAt,%((n + 1) mod 8) ; go process next command
  168. done:
  169. mov dl,n ; DL == current state
  170. jmp DecodeDone ; exit
  171. error:
  172. ;; Debug_Out "MRCI32 Decompress32: bad offset in LengthAt&n"
  173. jmp DecodeError
  174. align4
  175. try3:
  176. mov edx,ecx ; save delta
  177. CheckBit a,%(n + 1) ; is this a 3-bit encoding?
  178. jz try5 ; no, go for wider still
  179. BitsAt %(n+2),1
  180. DoMovs short,ecx,3
  181. Jump CmdAt,%((n + 3) mod 8) ; go process next command
  182. align4
  183. try5:
  184. CheckBit a,%(n + 2) ; is this a 5-bit encoding?
  185. jz try7 ; no, go test for wider STILL
  186. BitsAt %(n+3),2
  187. DoMovs short,ecx,5
  188. Jump CmdAt,%((n + 5) mod 8) ; go process next command
  189. align4
  190. try7:
  191. CheckBit a,%(n + 3) ; is this a 7 bit encoding?
  192. jz try9 ; no, go test for wider STILL
  193. BitsAt %(n+4),3
  194. DoMovs long,ecx,9
  195. Jump CmdAt,%((n + 7) mod 8) ; go process next command
  196. align4
  197. try9:
  198. CheckBit a,%(n + 4) ; is this a 9 bit encoding?
  199. jz tryGeneral ; no, go handle generically
  200. BitsAt %(n+5),4
  201. DoMovs long,ecx,17
  202. Jump CmdAt,%((n + 9) mod 8) ; go process next command
  203. ;
  204. ; Length exception handling code goes here
  205. ;
  206. align4
  207. tryGeneral:
  208. mov cl,n+5 ; CL == # of bits to eat to yield
  209. if n NE 7
  210. jmp LengthAbove32 ; gamma length with 5 leading zeros stripped
  211. else
  212. ;; .errnz $-GeneralLength ; assert that we'll fall through
  213. endif
  214. endm
  215. DoGeneralLength macro
  216. local try11,try13,try15,try17
  217. public LengthAbove32,CopyString
  218. GeneralLength:
  219. align4
  220. LengthAbove32:
  221. shl eax,16 ;
  222. mov ax,[esi] ; get 16 more bits
  223. add cl,16 ;
  224. ror eax,cl ; (eax) is filled, time to party
  225. ;
  226. ; Figure out the length and do a string op
  227. ;
  228. try11:
  229. shr eax,1 ; is it an 11-bit encoding?
  230. jnc try13 ; no
  231. and eax,1Fh ; mask off the numeric value
  232. add eax,33 ;
  233. xchg ecx,eax ; (ecx) now has string length
  234. sub al,10 ; record # extra bits in this length
  235. ;
  236. ; At this point, (ecx) is the # of bytes to copy and (al) is the number of
  237. ; additional bits to eat for the particular gamma length.
  238. ;
  239. ; Good coding practices suggest that CopyString be at the end so that the
  240. ; other gamma decoders need not jump backwards to it, but if we assume
  241. ; that the longer strings are marginally less common, then it is marginally
  242. ; better to fall through on this, the smallest of the general cases.
  243. ;
  244. align4
  245. CopyString:
  246. DoMovs long,ecx
  247. mov dl,al ; (dl) == bit position in old ax
  248. cmp dl,24 ; is it the max?
  249. jb @F ; no
  250. inc esi ; yes, need to skip 1 more whole byte
  251. lodsw ; get new (ax) to restart state machine
  252. sub dl,24 ; (dl) == new state
  253. DecodeRestart
  254. align4
  255. @@:
  256. cmp dl,16 ; did we exhaust the old ax?
  257. jae @F ; yes
  258. dec esi ; no,
  259. add dl,8 ; but we know we exhausted the low byte
  260. @@:
  261. lodsw ; get new (ax) to restart state machine
  262. sub dl,16 ; (dl) == new state
  263. DecodeRestart
  264. align4
  265. try13:
  266. shr eax,1 ; is it an 13-bit encoding?
  267. jnc try15 ; no
  268. and eax,3Fh ; mask off the numeric value
  269. add eax,65 ;
  270. xchg ecx,eax ; (cx) now has string length
  271. sub al,8 ; record # extra bits in this length
  272. jmp CopyString ;
  273. align4
  274. try15:
  275. shr eax,1 ; is it an 15-bit encoding?
  276. jnc try17 ; no
  277. and eax,7Fh ; mask off the numeric value
  278. add eax,129 ;
  279. xchg ecx,eax ; (ecx) now has string length
  280. sub al,6 ; record # extra bits in this length
  281. jmp CopyString ;
  282. align4
  283. try17:
  284. shr eax,1 ; is it an 17-bit encoding?
  285. ;; Debug_OutNC "MRCI32 Decompress32: invalid length"
  286. jnc DecodeError ; no, ERROR
  287. and eax,0FFh ; mask off the numeric value
  288. add eax,257 ;
  289. xchg ecx,eax ; (ecx) now has string length
  290. sub al,4 ; record # extra bits in this length
  291. jmp CopyString ;
  292. endm
  293. ;** DoMovs - worker macro for LengthAt and DoGeneralLength
  294. ;
  295. ; <size> is either "short" or "long"; if short, then we don't
  296. ; bother trying to do a movsw/movsb combo (overhead swamps benefit);
  297. ; if long, we do.
  298. ;
  299. ; If <len> == 2, the offset to use is in (ecx). (edx) is trashed.
  300. ;
  301. ; Otherwise, the offset has been saved in (edx), and <len>
  302. ; is the size of the string to move (normally ecx). (ecx) and (edx)
  303. ; are trashed.
  304. ;
  305. ; <errjmp> is where to go if the expansion is going to overflow the
  306. ; destination buffer. DoMovs just passes this parameter along to the
  307. ; CheckOffset macro.
  308. ;
  309. DoMovs macro size,len,extra,errjmp
  310. local slower
  311. ifidni <len>,<2>
  312. mov edx,esi ; save (esi) in (edx)
  313. mov esi,edi
  314. sub esi,ecx
  315. CheckOffset 2,errjmp ; check target offset
  316. movsb ; don't do movsw,
  317. movsb ; that doesn't handle overlap!
  318. mov esi,edx ; restore (esi) from (edx)
  319. else
  320. ifnb <len>
  321. ifdifi <len>,<ecx>
  322. ifb <extra>
  323. mov ecx,len
  324. else
  325. lea ecx,[len+extra]
  326. endif
  327. else
  328. ifnb <extra>
  329. add ecx,extra
  330. endif
  331. endif
  332. endif
  333. mov ebx,esi ; save (esi) in (ebx)
  334. mov esi,edi ;
  335. sub esi,edx ; (esi) points to string to move
  336. CheckOffset ecx,errjmp ; check target offset
  337. ifidni <size>,<short>
  338. rep movsb
  339. elseifidni <size>,<long>
  340. cmp edx,1 ; if the offset is 1,
  341. je short slower ; then overlap forces us to do movsb
  342. shr ecx,1
  343. rep movsw
  344. adc ecx,ecx
  345. slower: rep movsb
  346. else
  347. .err <Bad DoMovs parameter: size>
  348. endif
  349. mov esi,ebx ; restore (esi) from (ebx)
  350. endif
  351. endm
  352. ;** CheckOffset - Verify offsets in ESI and EDI are ok for len bytes
  353. ;
  354. ; If "len" is blank, then CheckOffset simply does a 1-byte check.
  355. ; In the event of an error in any case, it branches to DecodeError.
  356. ;
  357. LastErrSJump equ <DecodeError>
  358. LastErrBJump equ <DecodeError>
  359. CheckOffset macro len,errjmp
  360. local tmp,jsjmp,jbjmp
  361. IFDEF MAXDEBUG
  362. cmp edi,[maxOffset]
  363. jb short tmp
  364. int 3
  365. tmp:
  366. ENDIF
  367. ifnb <errjmp>
  368. ErrSJump equ <errjmp>
  369. else
  370. ErrSJump catstr LastErrSJump
  371. LastErrSJump equ <jsjmp>
  372. endif
  373. ifb <len>
  374. dec ebp ; space remaining in destination buffer?
  375. else
  376. sub ebp,len ; space remaining in destination buffer?
  377. endif
  378. ;; Debug_OutS "MRCI32 Decompress32: target buffer overflow"
  379. jsjmp: js ErrSJump
  380. IFDEF INLINE_LOWER_BOUND_CHECKING
  381. ;
  382. ; In-line bounds checking is disabled in favor of an invalid page fault
  383. ; handler. To use this code, be aware that EBX cannot be used by the
  384. ; decoding macros above (and it currently is!)
  385. ;
  386. ifnb <len>
  387. ifnb <errjmp>
  388. ErrBJump equ <errjmp>
  389. else
  390. ErrBJump catstr LastErrBJump
  391. LastErrBJump equ <jbjmp>
  392. endif
  393. cmp esi,ebx ; have we ventured before start of dest. buffer?
  394. ;; Debug_OutB "MRCI32 Decompress32: target buffer underflow"
  395. jbjmp: jb ErrBJump
  396. endif
  397. ENDIF ;INLINE_LOWER_BOUND_CHECKING
  398. endm
  399. ;* Misc. macros
  400. Jump macro lab,tag
  401. jmp lab&tag
  402. endm
  403. XlatChr macro ch
  404. ror al,1
  405. xor al,80h
  406. endm
  407. align4 macro
  408. ;
  409. ; This actually slowed down the real-mode decompressor, so some
  410. ; time will need to be spent verifying this is a real win... -JP
  411. ;
  412. align 4
  413. endm
  414. CheckBit macro reg,bit
  415. if bit lt 8
  416. test reg&l,(1 shl bit)
  417. else
  418. test reg&h,(1 shl (bit-8))
  419. endif
  420. endm
  421. CopyBits macro dst,src,n,cbits
  422. shld dst,src,16-n
  423. and e&dst,(1 shl cbits)-1
  424. endm
  425. ;
  426. ; AX has the remaining bits, DL has the next state
  427. ;
  428. DecodeRestart macro
  429. IFDEF DEBUG
  430. cmp dl,8
  431. ;; Debug_OutAE "MRCI32 Decompress32: bad decode state in DL"
  432. ENDIF
  433. movzx edx,dl
  434. jmp aCmdAt[edx*4] ; go to correct state handler
  435. endm
  436. IFDEF MAXDEBUG
  437. public maxOffset
  438. maxOffset dd -1 ; handy for getting control at a specific point
  439. ENDIF