PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/interp.asm

http://github.com/jpalmer/BrainF_ck-intepreter
Assembly | 279 lines | 234 code | 14 blank | 31 comment | 0 complexity | 4dd0a23b6791203f5d7798b6d10683f8 MD5 | raw file
  1. ;The aim of this is to create a brainfuck intepreter
  2. ;status - trying for speed increases
  3. extern printf
  4. extern malloc
  5. extern putchar
  6. ;due to different calling convention, the registers that we use depend on the OS
  7. %ifdef WIN64
  8. %define vd rcx
  9. %define main WinMain ;on windows main is not called main
  10. %endif
  11. %ifdef LIN64
  12. %define vd rdi
  13. %endif
  14. global main
  15. ;x64 calling convention
  16. ;ints / pointers - RCX RDX R8 R9
  17. ; - rdi is first on linux
  18. ; initialized data is put in the .data segment - it may be true that these are not modifiable
  19. segment .data
  20. ;loopless hello world
  21. ;program db "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++++++++++++++++.+++++++..+++.-------------------------------------------------------------------.------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++++++.+++.------.--------.-------------------------------------------------------------------.",0
  22. ;hello world w/ loops
  23. ;program db "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.",0
  24. ;factorial
  25. program db ">++++++++++>>>+>+[>>>+[-[<<<<<[+<<<<<]>>[[-]>[<<+>+>-]<[>+<-]<[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>+<-[>[-]>>>>+>+<<<<<<-[>+<-]]]]]]]]]]]>[<+>-]+>>>>>]<<<<<[<<<<<]>>>>>>>[>>>>>]++[-<<<<<]>>>>>>-]+>>>>>]<[>++<-]<<<<[<[>+<-]<<<<]>>[->[-]++++++[<++++++++>-]>>>>]<<<<<[<[>+>+<<-]>.<<<<<]>.>>>>]", 0
  26. debug db "dd",0
  27. intf db "%i" ,10,0
  28. charf db "%c",0
  29. hellostr db "loop", 10 ,0
  30. incdp db ">"
  31. decdp db "<"
  32. incbyte db "+"
  33. decbyte db "-"
  34. output db "."
  35. input db ","
  36. whilestart db "["
  37. whileend db "]"
  38. array dq 0
  39. jtab dq 0 ;stored in r9
  40. plength dq 0
  41. segment .text
  42. main:
  43. push rbp
  44. mov rbp,rsp
  45. %ifdef WIN64 ;not sure precisely what this does, got it by doing an objdump of a c exe - consider it magic
  46. sub rsp,0x20
  47. %elifdef LIN64
  48. sub rsp,0x10
  49. %endif
  50. ;allocate memory for memory
  51. mov vd, 0x5000000
  52. call malloc
  53. mov [array], rax
  54. jmp maparr
  55. maparr:
  56. mov rax, program
  57. dec rax
  58. .ib:
  59. mov byte [rax], 0
  60. jmp .loop
  61. .db:
  62. mov byte [rax], 1
  63. jmp .loop
  64. .out:
  65. mov byte [rax], 6
  66. jmp .loop
  67. .ddp:
  68. mov byte [rax], 3
  69. jmp .loop
  70. .idp:
  71. mov byte [rax], 2
  72. jmp .loop
  73. .inp:
  74. mov byte [rax], 7
  75. jmp .loop
  76. .ws:
  77. mov byte [rax], 4
  78. jmp .loop
  79. .we:
  80. mov byte [rax], 5
  81. jmp .loop
  82. .loop:
  83. inc rax
  84. mov bl, [rax]
  85. cmp bl, [incbyte]
  86. je .ib
  87. cmp bl, [decbyte]
  88. je .db
  89. cmp bl, [output]
  90. je .out
  91. cmp bl, [decdp]
  92. je .ddp
  93. cmp bl, [incdp]
  94. je .idp
  95. cmp bl, [input]
  96. je .inp
  97. cmp bl, [whilestart]
  98. je .ws
  99. cmp bl, [whileend]
  100. je .we
  101. cmp bl, 0
  102. jne .loop
  103. mov byte [rax], 8
  104. jmp Zeromem
  105. Zeromem:
  106. mov rcx, 0 ;0 value to store in memory
  107. mov rax,40008 ;currently 5k memory cells
  108. add rax, [array] ;rax is 'end' of memory
  109. mov rbx, 0
  110. add rbx, [array];rbx is 'start' of memory
  111. .loop_start:
  112. sub rax,8
  113. mov [rax], rcx
  114. cmp rax, rbx
  115. je Allocjmptab
  116. jmp .loop_start
  117. Allocjmptab:
  118. ;first calculate prog length
  119. mov rax, program
  120. dec rax
  121. xor rcx,rcx ;use rcx to hold prog length
  122. .loop_start:
  123. inc rax
  124. inc rcx
  125. cmp byte [rax],8
  126. je .loop_done
  127. .loop_done:
  128. mov rcx, [plength]
  129. ;now allocate memory
  130. mov vd, rcx
  131. sal vd,3 ;jtab has to store ints, so is 8 times bigger than the program, which is bytes
  132. call malloc
  133. mov[jtab], rax
  134. jmp Buildjmptab
  135. Buildjmptab:
  136. ;Variables I need to store
  137. ;I use the actual stack as the stack here - why not + frees up registers
  138. ;rcx - position through program
  139. mov rcx, program
  140. dec rcx ;for loop to be easier
  141. jmp .loop_start
  142. .whilestart:
  143. push rcx
  144. jmp .loop_start
  145. .whileend:
  146. pop rax ;rax is v
  147. push rax ; use this again later
  148. sub rax, program ;rax is now count through program of original start tax
  149. ;now I need to calculate the position to put the address
  150. mov r9, [jtab]
  151. mov [r9 + rax*8], rcx
  152. ;explaination -
  153. ;rax = position through program
  154. ;*8 - jump table is ints, program is bytes
  155. ;jtab - need to add in base address
  156. ;now do program.[curpointer] <- end(v)
  157. mov rax, rcx ;rax is now cur loc
  158. sub rax, program; rax now dist to current instruction
  159. pop rdx
  160. mov [r9 + rax*8],rdx
  161. jmp .loop_start
  162. .loop_start:
  163. inc rcx
  164. mov al, [rcx]
  165. mov dl, 4 ;whilestart
  166. cmp dl,al
  167. je .whilestart
  168. mov dl, 5 ;whileend
  169. cmp dl,al
  170. je .whileend
  171. mov dl, 8 ;move 8 - EOF
  172. cmp dl,al
  173. jne .loop_start ;if not end, keep going
  174. jmp initptrs ;now go to main loop
  175. initptrs:
  176. mov rdx, program
  177. mov al, [rdx]
  178. mov rbx, [array]
  179. mov vd, [rbx]
  180. jmp decode
  181. ;routines for different opcodes
  182. incdpC:
  183. ;decode at start should be faster - more time to get next opcode - but didn't actually make a difference
  184. inc rdx
  185. mov al, [rdx]
  186. mov [rbx], vd
  187. add rbx, 8
  188. mov vd, [rbx]
  189. jmp decode
  190. decdpC:
  191. inc rdx
  192. mov al, [rdx]
  193. mov [rbx], vd
  194. sub rbx, 8
  195. mov vd, [rbx]
  196. jmp decode
  197. decbyteC:
  198. inc rdx
  199. mov al, [rdx]
  200. dec vd
  201. jmp decode
  202. incbyteC:
  203. inc rdx
  204. mov al, [rdx]
  205. inc vd
  206. jmp decode
  207. outputC:
  208. ;works correctly in both oses - not sure if extra stack space necersarry, but keep it anyway
  209. push rbx
  210. push vd
  211. push r8
  212. push r9
  213. push rdx
  214. call putchar
  215. pop rdx
  216. pop r9
  217. pop r8
  218. pop vd
  219. pop rbx
  220. inc rdx
  221. mov al, [rdx]
  222. jmp decode
  223. whilestartC:
  224. ;check if memory.[pointer] = 0
  225. cmp vd, 0
  226. jne .nojmp
  227. ;now we need to get the new value for instrpointer
  228. sub rdx, program
  229. mov rdx, [rdx*8+r9]
  230. .nojmp: ;fall through
  231. inc rdx
  232. mov al, [rdx]
  233. jmp decode
  234. whileendC:
  235. cmp vd, 0 ;essentially same as above, but jump test reversed
  236. je .nojmp
  237. sub rdx, program
  238. mov rdx, [rdx*8+r9]
  239. .nojmp:
  240. inc rdx
  241. mov al, [rdx]
  242. jmp decode
  243. ;Instruction decode loop
  244. decode:
  245. and al,al
  246. je incbyteC
  247. dec al
  248. je decbyteC
  249. dec al
  250. je incdpC
  251. dec al
  252. je decdpC
  253. dec al
  254. je whilestartC
  255. dec al
  256. je whileendC
  257. dec al
  258. je outputC
  259. sub al, 2
  260. je exit
  261. ;EXIT HERE
  262. exit:
  263. xor rax,rax ;return 0
  264. leave
  265. ret