Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

unnrv2b.S 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
  3. *
  4. * This file is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * Originally this code was part of ucl the data compression library
  10. * for upx the ``Ultimate Packer of eXecutables''.
  11. *
  12. * - Converted to gas assembly, and refitted to work with etherboot.
  13. * Eric Biederman 20 Aug 2002
  14. *
  15. * - Structure modified to be a subroutine call rather than an
  16. * executable prefix.
  17. * Michael Brown 30 Mar 2004
  18. *
  19. * - Modified to be compilable as either 16-bit or 32-bit code.
  20. * Michael Brown 9 Mar 2005
  21. */
  22. /****************************************************************************
  23. * This file provides the decompress_block() and decompress_block16()
  24. * functions which can be called in order to decompress an image
  25. * compressed with the nrv2b utility in src/util.
  26. *
  27. * These functions are designed to be called by the prefix. They are
  28. * position-independent code.
  29. *
  30. * The same basic assembly code is used to compile both
  31. * decompress_block() and decompress_block16().
  32. ****************************************************************************
  33. */
  34. .text
  35. .arch i386
  36. .section ".prefix", "ax", @progbits
  37. #ifdef CODE16
  38. /****************************************************************************
  39. * decompress_block16 (real-mode near call, position independent)
  40. *
  41. * Parameters (passed via registers):
  42. * %ds:%si - Pointer to compressed input data
  43. * %es:%di - Pointer to output buffer
  44. * Returns:
  45. * All registers are preserved
  46. *
  47. * NOTE: The compressed data size must be in the range [1,65533-%si]
  48. * and the uncompressed data size must be in the range [1,65536-%di]
  49. * (where %si and %di are the input values for those registers). Note
  50. * particularly that the lower limit is 1, not 0, and that the upper
  51. * limit on the input (compressed) data really is 65533, since the
  52. * algorithm may read up to three bytes beyond the end of the input
  53. * data, since it reads dwords.
  54. *
  55. * Although splitting up the data into (almost) 64kB chunks for
  56. * compression is awkward and worsens the compression ratio, it has
  57. * little to no practical effect since our image size is currently
  58. * <64kB for all single drivers. Having a decompression routine that
  59. * can run in real-mode avoids the need to duplicate RM-to-PM
  60. * transition code from librm (or have part of librm kept
  61. * uncompressed, which is itself awkward) and means that we don't need
  62. * to set up the PM stack until we hit the setup routine itself.
  63. ****************************************************************************
  64. */
  65. #define REG(x) x
  66. .code16
  67. .globl decompress_block16
  68. decompress_block16:
  69. #else /* CODE16 */
  70. /****************************************************************************
  71. * decompress_block (32-bit protected-mode near call, position independent)
  72. *
  73. * Parameters (passed via registers):
  74. * %ds:%esi - Pointer to compressed input data
  75. * %es:%edi - Pointer to output buffer
  76. * Returns:
  77. * All registers are preserved
  78. ****************************************************************************
  79. */
  80. #define REG(x) e ## x
  81. .code32
  82. .globl decompress_block
  83. decompress_block:
  84. #endif /* CODE16 */
  85. #define xAX REG(ax)
  86. #define xCX REG(cx)
  87. #define xBP REG(bp)
  88. #define xSI REG(si)
  89. #define xDI REG(di)
  90. /* Save registers */
  91. pushal
  92. /* Do the decompression */
  93. cld
  94. xor %xBP, %xBP
  95. dec %xBP /* last_m_off = -1 */
  96. jmp dcl1_n2b
  97. decompr_literals_n2b:
  98. movsb
  99. decompr_loop_n2b:
  100. addl %ebx, %ebx
  101. jnz dcl2_n2b
  102. dcl1_n2b:
  103. call getbit32
  104. dcl2_n2b:
  105. jc decompr_literals_n2b
  106. xor %xAX, %xAX
  107. inc %xAX /* m_off = 1 */
  108. loop1_n2b:
  109. call getbit1
  110. adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
  111. call getbit1
  112. jnc loop1_n2b /* while(!getbit()) */
  113. sub $3, %xAX
  114. jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
  115. shl $8, %xAX
  116. movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
  117. inc %xSI
  118. not %xAX
  119. jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
  120. mov %xAX, %xBP /* last_m_off = m_off ?*/
  121. decompr_ebpeax_n2b:
  122. xor %xCX, %xCX
  123. call getbit1
  124. adc %xCX, %xCX /* m_len = getbit() */
  125. call getbit1
  126. adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
  127. jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
  128. inc %xCX /* m_len++ */
  129. loop2_n2b:
  130. call getbit1
  131. adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
  132. call getbit1
  133. jnc loop2_n2b /* while(!getbit()) */
  134. inc %xCX
  135. inc %xCX /* m_len += 2 */
  136. decompr_got_mlen_n2b:
  137. cmp $-0xd00, %xBP
  138. adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
  139. push %xSI
  140. lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
  141. rep
  142. es movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
  143. pop %xSI
  144. jmp decompr_loop_n2b
  145. getbit1:
  146. addl %ebx, %ebx
  147. jnz 1f
  148. getbit32:
  149. movl (%xSI), %ebx
  150. sub $-4, %xSI /* sets carry flag */
  151. adcl %ebx, %ebx
  152. 1:
  153. ret
  154. decompr_end_n2b:
  155. /* Restore registers and return */
  156. popal
  157. ret