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.

347 lines
6.1 KiB

6 years ago
  1. %define BUILD_64
  2. %ifdef BUILD_64
  3. BITS 64
  4. %define SZOF_PTR 8
  5. %define eax rax
  6. %define ebx rbx
  7. %define ecx rcx
  8. %define edx rdx
  9. %define edi rdi
  10. %define esi rsi
  11. %define esp rsp
  12. %define ebp rbp
  13. %else
  14. BITS 32
  15. %define SZOF_PTR 4
  16. %endif
  17. O_RDONLY: equ 0
  18. SIGINT: equ 2
  19. %define SYS_EXIT 60
  20. %define SYS_READ 0
  21. %define SYS_WRITE 1
  22. %define SYS_OPEN 2
  23. %define SYS_CLOSE 3
  24. %define SYS_SIGACTION 13
  25. %define BUFFER_SZ 1572864
  26. %macro print 1
  27. ; Ensure we write the string to the data section.
  28. ; This syntax does not unset the special macro __SECT__, which is used to restore
  29. ; the previous section below.
  30. [section .data]
  31. %%msg: db %1, 0
  32. %%msglen: equ $ - %%msg
  33. ; Restore to the section we're in (probably .text)
  34. __SECT__
  35. push eax
  36. push ebx
  37. mov eax, %%msg
  38. mov ebx, %%msglen
  39. call _write
  40. pop ebx
  41. pop eax
  42. %endmacro
  43. %macro write 2
  44. push eax
  45. push ebx
  46. mov eax, %1
  47. mov ebx, %2
  48. call _write
  49. pop ebx
  50. pop eax
  51. %endmacro
  52. %macro _linsys_pusha 0
  53. mov [_old_esp], esp
  54. mov esp, _syscall_save_stack
  55. push rdi
  56. push rsi
  57. push rdx
  58. push rcx
  59. push r8
  60. push r9
  61. push r10
  62. push r11
  63. mov esp, [_old_esp]
  64. %endmacro
  65. %macro _linsys_popa 0
  66. mov [_old_esp], esp
  67. mov esp, _syscall_save_stack
  68. sub esp, 8*SZOF_PTR
  69. pop r11
  70. pop r10
  71. pop r9
  72. pop r8
  73. pop rcx
  74. pop rdx
  75. pop rsi
  76. pop rdi
  77. mov esp, [_old_esp]
  78. %endmacro
  79. %macro linsys 1
  80. _linsys_pusha
  81. mov eax, %1
  82. syscall
  83. _linsys_popa
  84. %endmacro
  85. %macro linsys 2
  86. _linsys_pusha
  87. mov eax, %1
  88. mov rdi, %2
  89. syscall
  90. _linsys_popa
  91. %endmacro
  92. %macro linsys 3
  93. _linsys_pusha
  94. mov eax, %1
  95. mov rdi, %2
  96. mov rsi, %3
  97. syscall
  98. _linsys_popa
  99. %endmacro
  100. %macro linsys 4
  101. _linsys_pusha
  102. mov eax, %1
  103. mov rdi, %2
  104. mov rsi, %3
  105. mov rdx, %4
  106. syscall
  107. _linsys_popa
  108. %endmacro
  109. %macro linsys 5
  110. _linsys_pusha
  111. mov eax, %1
  112. mov rdi, %2
  113. mov rsi, %3
  114. mov rdx, %4
  115. mov rcx, %5
  116. syscall
  117. _linsys_popa
  118. %endmacro
  119. %macro linsys 6
  120. _linsys_pusha
  121. mov eax, %1
  122. mov rdi, %2
  123. mov rsi, %3
  124. mov rdx, %4
  125. mov rcx, %5
  126. mov r8, %6
  127. syscall
  128. _linsys_popa
  129. %endmacro
  130. %macro linsys 7
  131. _linsys_pusha
  132. mov eax, %1
  133. mov rdi, %2
  134. mov rsi, %3
  135. mov rdx, %4
  136. mov rcx, %5
  137. mov r8, %6
  138. mov r9, %7
  139. syscall
  140. _linsys_popa
  141. %endmacro
  142. %macro exit 1
  143. ; This is a divergent path, so we don't need to worry about clobbers.
  144. linsys SYS_EXIT, %1
  145. ; Halt.
  146. %endmacro
  147. %macro push_char 1
  148. mov r8, r9
  149. mov r9, r10
  150. mov r10, r11
  151. mov r11, %1
  152. cmp r12, 3
  153. jl %%not_ready
  154. mov esi, r8
  155. inc dword [counts_b0 + esi * 4]
  156. shl esi, 6
  157. or esi, r9
  158. inc dword [counts_b1 + esi * 4]
  159. shl esi, 6
  160. or esi, r10
  161. inc dword [counts_b2 + esi * 4]
  162. shl esi, 6
  163. or esi, r11
  164. inc dword [counts + esi * 4]
  165. jmp %%done
  166. %%not_ready:
  167. inc r12
  168. %%done:
  169. %endmacro
  170. section .bss
  171. counts:
  172. resd (64 * 64 * 64 * 64)
  173. counts_b2:
  174. resd (64 * 64 * 64)
  175. counts_b1:
  176. resd (64 * 64)
  177. counts_b0:
  178. resd 64
  179. counts.len: equ $ - counts
  180. %define COUNT_BASE_0 ((64 * 64 * 64 * 64) + (64 * 64 * 64) + (64 * 64))
  181. %define COUNT_BASE_1 ((64 * 64 * 64 * 64) + (64 * 64 * 64))
  182. %define COUNT_BASE_2 (64 * 64 * 64 * 64)
  183. buffer:
  184. resb BUFFER_SZ
  185. .len: equ $ - buffer
  186. _old_esp: resq 1
  187. resq 8
  188. _syscall_save_stack:
  189. section .data
  190. mapping:
  191. db 63,63,63,63,63,63,63,63,63,63,37,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,36,42,43,57,58,59,61,44,50,51,62,63,39,45,38,63,26,27,28,29,30,31,32,33,34,35,40,41,54,46,55,63,56,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,48,63,49,60,47,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,52,63,53,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63
  192. .len: equ $ - mapping
  193. section .text
  194. global _write
  195. _write:
  196. ; This is the Linux write syscall, using its own weird parameter passing.
  197. ; Store the registers we're about to clobber...
  198. push ecx
  199. push edx
  200. ; And push these, because we'll need them later
  201. push eax
  202. push ebx
  203. ; Do up the syscall
  204. linsys SYS_WRITE, 2, [esp+SZOF_PTR], [esp]
  205. ; Check the return
  206. .after:
  207. cmp eax, 0
  208. jl .err ; Oops.
  209. cmp eax, [esp]
  210. jge .done
  211. ; We didn't write the whole buffer; let's try that again.
  212. add [esp+SZOF_PTR], eax
  213. sub [esp], eax
  214. linsys SYS_WRITE, 1, [esp+SZOF_PTR], [esp]
  215. jmp .after
  216. .err:
  217. .done:
  218. ; Good or not, we're cleaning up
  219. pop ebx
  220. pop eax
  221. pop edx
  222. pop ecx
  223. ret
  224. global _start
  225. _start:
  226. pop esi
  227. pop edi
  228. cmp esi, 3
  229. jge .has_extra_arg
  230. cmp esi, 2
  231. jge .has_arg
  232. print {"usage: <executable> [<update file>] <file> > <output file>",10}
  233. exit 1
  234. .has_extra_arg:
  235. print {'Reading in previous table...',10}
  236. pop ebx
  237. linsys SYS_OPEN, ebx, O_RDONLY, 0
  238. cmp eax, 0
  239. jge .table_open
  240. print {"Can't open table file",10}
  241. exit 7
  242. .table_open:
  243. push eax
  244. mov esi, counts
  245. .table_read_loop:
  246. cmp esi, counts+counts.len
  247. jge .table_read_done
  248. mov edx, counts+counts.len
  249. sub edx, esi
  250. linsys SYS_READ, [esp], esi, edx
  251. cmp eax, 0
  252. jl .table_read_error
  253. cmp eax, 0
  254. je .table_read_trunc
  255. add esi, eax
  256. jmp .table_read_loop
  257. .table_read_error:
  258. print {"Error reading in table",10}
  259. exit 7
  260. .table_read_trunc:
  261. print {"Table file too small",10}
  262. exit 7
  263. .table_read_done:
  264. pop eax
  265. .has_arg:
  266. print {'Updating tables...',10}
  267. pop ebx
  268. linsys SYS_OPEN, ebx, O_RDONLY, 0
  269. cmp eax, 0
  270. jge .file_open
  271. print {"Can't open file",10}
  272. exit 2
  273. .file_open:
  274. push eax
  275. xor r8, r8
  276. xor r9, r9
  277. xor r10, r10
  278. xor r11, r11
  279. xor r12, r12
  280. xor ebx, ebx
  281. .read_loop:
  282. linsys SYS_READ, [esp], buffer, buffer.len
  283. cmp eax, 0
  284. jl .read_error
  285. je .read_done
  286. mov ecx, 0
  287. .count_loop:
  288. cmp ecx, eax
  289. jge .count_done
  290. mov bl, [buffer + ecx]
  291. mov bl, [mapping + ebx]
  292. push_char ebx
  293. inc ecx
  294. jmp .count_loop
  295. .count_done:
  296. jmp .read_loop
  297. .read_error:
  298. print {'Error occured while reading',10}
  299. .read_done:
  300. linsys SYS_CLOSE, [esp]
  301. mov esi, counts
  302. .write_loop:
  303. cmp esi, counts+counts.len
  304. jge .write_done
  305. mov edx, counts+counts.len
  306. sub edx, esi
  307. linsys SYS_WRITE, 1, esi, edx
  308. cmp eax, 0
  309. jl .write_error
  310. add esi, eax
  311. jmp .write_loop
  312. .write_error:
  313. print {'Error occured while writing',10}
  314. .write_done:
  315. print {'Finished.',10}
  316. exit 0