Source code of Windows XP (NT5)
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.

283 lines
5.4 KiB

  1. ;
  2. ; asm_decoder_translate_e8()
  3. ;
  4. ; Assembly implementation of this from decxlat.c
  5. ;
  6. ; 26-Jul-96 jforbes Initial version
  7. ;
  8. TITLE XLATASM.ASM
  9. .386P
  10. .model FLAT
  11. PUBLIC _asm_decoder_translate_e8
  12. OFFSET_INSTR_POS equ 28
  13. OFFSET_FILE_SIZE equ 32
  14. OFFSET_MEM equ 36
  15. OFFSET_BYTES equ 40
  16. ;
  17. ; ulong asm_decoder_translate_e8(instr_pos, file_size, mem *, bytes)
  18. ;
  19. ; returns new instr_pos in EAX
  20. ;
  21. _TEXT SEGMENT
  22. _asm_decoder_translate_e8 PROC NEAR
  23. push ebx
  24. push ecx
  25. push edx
  26. push esi
  27. push edi
  28. push ebp
  29. ; edx = bytes
  30. mov edx, DWORD PTR [esp + OFFSET_BYTES]
  31. ; if (bytes >= 6)
  32. cmp edx, 6
  33. jge greater_than_6_bytes
  34. ;
  35. ; less than 6 bytes to translate, so don't translate
  36. ;
  37. ; instr_pos += bytes
  38. add edx, [esp + OFFSET_INSTR_POS]
  39. ; return new instr_pos in eax
  40. mov eax, edx
  41. pop ebp
  42. pop edi
  43. pop esi
  44. pop edx
  45. pop ecx
  46. pop ebx
  47. ret 0
  48. greater_than_6_bytes:
  49. ; ebp = current_file_size
  50. mov ebp, DWORD PTR [esp + OFFSET_FILE_SIZE]
  51. ; ebx = 0xE8, our magic number
  52. mov ebx, 0E8h ; 232
  53. ; esi = instr_pos
  54. mov esi, DWORD PTR [esp + OFFSET_INSTR_POS]
  55. ; ecx = mem
  56. mov ecx, DWORD PTR [esp + OFFSET_MEM]
  57. ; edi = instr_pos + bytes - 6
  58. mov edi, esi
  59. add edi, edx
  60. sub edi, 6
  61. ; backup the last 6 bytes in the buffer
  62. sub esp, 6
  63. ; eax = &mem[bytes-6]
  64. mov eax, ecx
  65. add eax, edx
  66. sub eax, 6
  67. mov edx, [eax]
  68. mov [esp], edx
  69. mov dx, WORD PTR [eax+4]
  70. mov WORD PTR [esp+4], dx
  71. ; now store 0xE8's in there
  72. mov DWORD PTR [eax], 0E8E8E8E8h
  73. mov WORD PTR [eax+4], 0E8E8h
  74. ; save &mem[bytes-6]
  75. push eax
  76. ;
  77. ; main loop
  78. ;
  79. ; eax = temporary
  80. ; ebx = 0xE8
  81. ; ecx = source ptr
  82. ; edx = temporary
  83. ; esi = instr pos
  84. ; edi = end_instr_pos
  85. ; ebp = current_file_size
  86. ;
  87. loop_top:
  88. ;
  89. ; while (*mem++ != 0xE8)
  90. ; ;
  91. ; eax = mem before
  92. mov eax, ecx ; u1
  93. nop ; v1
  94. main_subloop:
  95. cmp bl, [ecx] ; u2
  96. je SHORT equals_e8 ; v1
  97. cmp bl, [ecx+1] ; u2
  98. je SHORT pre1 ; v1
  99. cmp bl, [ecx+2] ; u2
  100. je SHORT pre2 ; v1
  101. cmp bl, [ecx+3] ; u2
  102. je SHORT pre3 ; v1
  103. add ecx, 4 ; u1
  104. jmp SHORT main_subloop ; v1
  105. pre3:
  106. add ecx, 3 ; u1
  107. jmp SHORT equals_e8 ; v1
  108. pre2:
  109. add ecx, 2 ; u1
  110. jmp SHORT equals_e8 ; v1
  111. pre1:
  112. inc ecx
  113. equals_e8:
  114. ; instr_pos += bytes visited in above loop
  115. ; esi := esi + (ecx - eax)
  116. sub esi, eax ; u1
  117. add esi, ecx ; v1
  118. ;
  119. ; Here is the only place we check for the end.
  120. ;
  121. ; We can do this because we force an 0xE8 at the end
  122. ; of the buffer.
  123. ;
  124. ; We cannot overlap the MOV below in between the
  125. ; cmp/jge, because ecx+1 may point to invalid memory.
  126. ;
  127. cmp esi, edi ; u1
  128. jge SHORT bottom ; v1
  129. ; eax = absolute = *(long *) mem
  130. mov eax, [ecx+1] ; u1
  131. add ecx, 5 ; v1 memptr += 5
  132. ;
  133. ; if (absolute < current_file_size && absolute >= 0)
  134. ;
  135. ; use unsigned comparison here so that if absolute < 0
  136. ; then it seems like it's some huge number
  137. ;
  138. ; this way we only do one comparison, abs >= file_size
  139. ;
  140. cmp eax, ebp ; u1
  141. jae SHORT second_check ; v1
  142. ;
  143. ; instead of doing "offset = absolute - instr_pos" and
  144. ; then storing it, we just say *mem -= instr_pos
  145. ;
  146. ; instead of:
  147. ;
  148. ; sub eax, esi
  149. ; mov [ecx-4], eax
  150. ;
  151. ; we do:
  152. sub [ecx-4], esi ; u3
  153. add esi, 5 ; v1 instr_pos += 5
  154. mov eax, ecx ; u1 (copied from loop_top)
  155. jmp SHORT main_subloop ; v1
  156. ;
  157. ; we want (absolute < 0) && (absolute >= -instr_pos)
  158. ;
  159. ; which can be rewritten as:
  160. ;
  161. ; (-absolute > 0) && (-absolute - instr_pos <= 0)
  162. ;
  163. ; then:
  164. ;
  165. ; (-absolute > 0) && (-absolute <= instr_pos)
  166. ;
  167. ; we can do both of these checks by checking with
  168. ; unsigned arithmetic, since if absolute < 0 then it
  169. ; will seem like some huge number:
  170. ;
  171. ; if ((ulong) (-(long) absolute) <= instr_pos)
  172. ;
  173. ; note: absolute==0 is taken care of in the first case
  174. ;
  175. second_check:
  176. ; edx = instr_pos + absolute
  177. neg eax ; u
  178. cmp eax, esi ; u1
  179. ja SHORT no_conversion ; v1
  180. ;
  181. ; instead of storing "offset = absolute + current_file_size"
  182. ; we can do *mem += file_size.
  183. ;
  184. ; instead of doing:
  185. ;
  186. ; neg eax
  187. ; add eax, ebp
  188. ; mov DWORD PTR [ecx-4], eax
  189. ;
  190. ; we do:
  191. add [ecx-4], ebp ; u3
  192. no_conversion:
  193. ; instr_pos += 5
  194. add esi, 5 ; v1 u1
  195. jmp SHORT loop_top ; v1
  196. bottom:
  197. ; instr_pos = end_instr_pos + 6
  198. add edi, 6
  199. ; restore the 6 bytes
  200. ; get &mem[bytes-6]
  201. pop eax
  202. mov edx, DWORD PTR [esp]
  203. mov DWORD PTR [eax], edx
  204. mov dx, WORD PTR [esp+4]
  205. mov WORD PTR [eax+4], dx
  206. add esp, 6
  207. ; return new instr_pos in eax
  208. mov eax, edi
  209. pop ebp
  210. pop edi
  211. pop esi
  212. pop edx
  213. pop ecx
  214. pop ebx
  215. ret 0
  216. _asm_decoder_translate_e8 ENDP
  217. _TEXT ENDS
  218. END