/MedianaElka/main.asm

http://github.com/fiedukow/MedianaElka · Assembly · 546 lines · 499 code · 47 blank · 0 comment · 16 complexity · eb2e69466da668a6b5e766368019f1d3 MD5 · raw file

  1. .data
  2. #filename: .asciiz "qt.bmp"
  3. #new_filename: .asciiz "output.bmp"
  4. #.align 2
  5. filename: .space 64
  6. new_filename: .space 64
  7. #.align 2
  8. thanks: .asciiz "\nProgram zakonczyl dzialanie, wynik dzialania zapisano w pliku "
  9. question_s: .asciiz "Nazwa pliku do przerobienia (max. 64 znaki) > "
  10. question_t: .asciiz "Nazwa pliku do zapisania wyniku (max. 64 znaki; UPRAWNIENIA ZAPISU!) > "
  11. newline: .asciiz "\n"
  12. processing: .asciiz "Processing.."
  13. dot: .asciiz "."
  14. .align 2
  15. fl: .space 4 # current 1st line pointer
  16. sl: .space 4 # current 2nd line pointer
  17. tl: .space 4 # current 3rd line pointer
  18. pl: .space 4 # current proccesed line result
  19. .text
  20. main:
  21. # Register once set keep their value till the end:
  22. # s1 - file descriptor of source
  23. # s2 - width (same for both files)
  24. # s3 - height (same for both files)
  25. # s5 - file descriptor of result
  26. # s6 - bytes in one line with complement
  27. ##################################################################################
  28. ## ASKING USER FOR FILENAMES AND PROGRESSING IT
  29. ##################################################################################
  30. ## SYSCALL (print first question)
  31. li $v0,4 # print_string service
  32. la $a0,question_s # show place where the string is
  33. syscall # printf(question_s)
  34. ## SYSCALL (take filename of file to process)
  35. li $v0, 8 # read_string service
  36. la $a0, filename #show place for source filename (global variable)
  37. li $a1, 64 # max. filename size is 64
  38. syscall # scanf(source_filename, 64)
  39. ## SYSCALL (print second question)
  40. li $v0,4 # print_string service
  41. la $a0,question_t # show place where the string is
  42. syscall # printf(question_t)
  43. ## SYSCALL (take filename of file for output)
  44. li $v0, 8 # read-string service
  45. la $a0, new_filename #show place for target filename (global variable)
  46. li $a1, 64 # max. filename size is 64
  47. syscall # scanf(target_filename, 64)
  48. #for(i=0;l[i]!='\n';++i);
  49. #l[i]='\0';
  50. # Change first \n to \0 in loaded filenames
  51. # changing in source_file
  52. li $t0, 0
  53. la $t1, filename
  54. no_nl:
  55. addu $t2,$t1,$t0
  56. lb $t3,0($t2)
  57. bne $t3,10,skip_nl
  58. sb $0, 0($t2)
  59. j no_nl_end
  60. skip_nl:
  61. addiu $t0,$t0,1
  62. j no_nl
  63. no_nl_end:
  64. # changing in target_file
  65. li $t0, 0
  66. la $t1, new_filename
  67. no_nln:
  68. addu $t2,$t1,$t0
  69. lb $t3,0($t2)
  70. bne $t3,10,skip_nln
  71. sb $0, 0($t2)
  72. j no_nl_endn
  73. skip_nln:
  74. addiu $t0,$t0,1
  75. j no_nln
  76. no_nl_endn:
  77. # Filenames are now valid (without \n in the end).
  78. # All register FREE
  79. ##################################################################################
  80. ## OPENING FILES WITH AND FOR DATA
  81. ##################################################################################
  82. ## SYSCALL (open file for reading, $s1 is file descriptor)
  83. li $v0, 13 # open-file service
  84. la $a0, filename # 0($s0) # set filename to read
  85. li $a1, 0 # read-only flag
  86. li $a2, 0 # ignore mode
  87. syscall # open file, $v0 gets file-descriptior
  88. move $s1, $v0 # let s1 be file descriptor for old file
  89. ## SYSCALL (open file for writing (for save the result of program))
  90. li $v0, 13 # open-file service
  91. la $a0, new_filename # show file to write to
  92. li $a1, 1 # write flag
  93. li $a2, 0 # ignore mode
  94. syscall # open result file for writing, $v0 gets descriptor
  95. move $s5, $v0 # let s5 be file descriptor for new file
  96. # Now needed files are opened
  97. # For now:
  98. # $s1 is source file descriptor
  99. # $s5 is target file descriptor
  100. ##################################################################################
  101. ## LOADING PROCESSING AND SAVING HEADER OF BITMAP
  102. ##################################################################################
  103. addiu $sp,$sp,-54 # make place for header (from old bmp)
  104. ## SYSCALL (read 54B of file to $t0 (place on stack))
  105. li $v0, 14 # read-from-file service
  106. move $a0,$s1 # give system file descriptor
  107. la $a1,0($sp) # show place to write ($t0)
  108. li $a2,54 # set 54B limit to read (header size)
  109. syscall # read header of bmp
  110. # Read bmp dimensions from header just read
  111. lhu $s2,0x12($sp) # read width (stored on 2B)
  112. lhu $s3,0x16($sp) # read height (stored on 2B)
  113. ## SYSCALL (write 54B from stack to result file (header without any changes))
  114. li $v0, 15 # write-to-file service
  115. move $a0, $s5 # give system file dscriptor
  116. la $a1, 0($sp) # show place to write from ($t0)
  117. li $a2, 54 #set 54B as number of bytes to write to file
  118. syscall # write header to reslut file
  119. addiu $sp,$sp,54 # free stack of header information
  120. # Now header is written to target file
  121. # For now:
  122. # $s2 is width of image
  123. # $s3 is height of image
  124. ##################################################################################
  125. ## JUST END UP PROGRAM IF FILE IS TO SMALL FOR THIS FILTER
  126. ##################################################################################
  127. blt $s2,3,exit # if file is to small
  128. blt $s3,3,exit # just do nothing about it
  129. #@todo: probably it should rewrite image without any changes
  130. # Now program ends if file is smaller then 3x3 in at least one dimension
  131. ##################################################################################
  132. ## CALCULATING LINE SIZE IN BYTES
  133. ##################################################################################
  134. ## $t1 - 3 constans
  135. li $t1,3
  136. mult $s2,$t1 # 3 bytes describing one pixel in BMP (R,G,B)
  137. mflo $s6 # assuming 32 bits is enough for line size in bytes
  138. ## $t1 - FREE
  139. ## $t1 - width mod 4, with is number of bytes in complement
  140. andi $t1,$s2,0x00000003 # $t4 = width % 4
  141. addu $s6,$t1,$s6 # $s6 - is actual number of bytes in line now
  142. ## $t1 - FREE
  143. # For now:
  144. # $s6 is number of bytes in line with complement
  145. ##################################################################################
  146. ## READING FIRST LINES (SAVING ONE OF THEM), PREPARING STACK FOR 4 LINES (3 readed, 1 for progress)
  147. ##################################################################################
  148. subu $sp,$sp,$s6 # prepare stack to store the line 1
  149. sw $sp,tl #save 3rd line pointer
  150. subu $sp,$sp,$s6 # prepare stack to store the line 2
  151. sw $sp,sl #save 2nd line pointer
  152. subu $sp,$sp,$s6 # prepare stack to store the line 3
  153. sw $sp,fl #save 1st line pointer
  154. subu $sp,$sp,$s6 # prepare stack to store the result line
  155. sw $sp,pl #save result (processing) line pointer
  156. ## SYSCALL (read first line from source file)
  157. li $v0, 14 # read-from-file service
  158. move $a0, $s1 # show system file descriptor
  159. lw $t0, fl
  160. la $a1, 0($t0) # show system place for writing
  161. move $a2, $s6 # limit is the line size
  162. syscall # read whole line
  163. ## SYSCALL (read second line from source file)
  164. ## $t0 - place to write to next line
  165. li $v0, 14 # read-from-file service
  166. lw $t0, sl
  167. la $a1, 0($t0)
  168. syscall # read whole line
  169. ## SYSCALL (read third line from source file)
  170. li $v0, 14 # read-from-file service
  171. lw $t0, tl
  172. la $a1, 0($t0)
  173. syscall # read whole line
  174. ## $t0 - FREE
  175. ## SYSCALL (write first line to file (it dosn't change anyway)
  176. li $v0, 15 # write-to-file service
  177. move $a0, $s5 # show system file descriptor
  178. lw $t0, fl
  179. la $a1, 0($t0) # show system place to read from
  180. move $a2, $s6 # write a line size from showed pointer
  181. syscall # write whole line
  182. # Now there is place on stack for 4 lines
  183. # 3 lines are loaded
  184. # first line is already in target file
  185. # There are adresses of begining of first, second, third & processing line in memory under fl,sl,th,pl
  186. ##################################################################################
  187. ## LOOPING THROUGH THE LINES
  188. ##################################################################################
  189. ## $s7 - loop marker for a while
  190. move $s7, $s3
  191. addu $s7, $s7, -3 #3 lines already loaded
  192. # SYSCALL (printf info about begining of progressing)
  193. li $v0,4 # print_string service
  194. la $a0,processing # show adres to read from
  195. syscall # printf(Processing..)
  196. p3l_loop: #process 3 lines loops
  197. # SYSCALL (printf dot for every line you progress)
  198. li $v0,4 # print_string service
  199. la $a0,dot # show adress to read from
  200. syscall # printf(.)
  201. ##################################################################################
  202. ## NOW 3 LINES ARE ON STACK (showed by fl,sl,tl) ACCTUAL PROCESSING HERE, LOOPING THROUGH BLOCKS IN LINE
  203. ##################################################################################
  204. li $t7, 1 # t7 is acctual pixel (from 1 to width-1)
  205. addu $sp,$sp,-36 # make place on stack for brightness & pixel id
  206. prl:
  207. # WRITE TO RESULT LINE FIRST AND LAST PIXEL (UGLY BUT PROBABLY BETTER THEN LOOP)
  208. lw $t1, sl
  209. lw $t2, pl
  210. lb $t3, 0($t1)
  211. sb $t3, 0($t2)
  212. lb $t3, 1($t1)
  213. sb $t3, 1($t2)
  214. lb $t3, 2($t1)
  215. sb $t3, 2($t2)
  216. mul $t4,$s2,3
  217. addu $t1, $t1, $t4
  218. addu $t2, $t2, $t4
  219. lb $t3, -3($t1)
  220. sb $t3, -3($t2)
  221. lb $t3, -2($t1)
  222. sb $t3, -2($t2)
  223. lb $t3, -1($t1)
  224. sb $t3, -1($t2)
  225. # WRITE TO RESULT LINE FIRST AND LAST PIXEL - END
  226. # Loading brightness with ids of acctual block
  227. beq $t7,$s2,prl_end
  228. li $t9,0
  229. lbl:
  230. bge $t9,9,lbl_end # only ids 0-8 will be loaded
  231. move $a0,$t9 # show the procedure id of pixel to load
  232. jal take_pixel_b #call procedure, there is result in $a0
  233. mul $t8,$t9,4 # calculete place on stack for becomed value
  234. addu $t8,$t8,$sp
  235. sw $a0, 0($t8) # store becomed pair id, brightness
  236. addiu $t9,$t9,1 # progress next pixel in block
  237. j lbl
  238. lbl_end:
  239. # Brightness with ids on stack now! sort and change center now.
  240. # Sorting brightnesses with ids (quick buble)
  241. li $t0,0
  242. li $t9,1
  243. sort:
  244. beq $t0, 5, sort_end
  245. beqz $t9, sort_end
  246. li $t1,0
  247. li $t9, 0
  248. sort_in:
  249. li $t8,8
  250. subu $t8, $t8, $t0
  251. beq $t1, $t8, sort_in_end
  252. mul $t2,$t1,4
  253. addu $t2, $sp, $t2
  254. lh $t3, 0($t2)
  255. lh $t4, 4($t2)
  256. bge $t4,$t3,skip_swap
  257. li $t9,1
  258. lw $t3, 0($t2)
  259. lw $t4, 4($t2)
  260. sw $t4, 0($t2)
  261. sw $t3, 4($t2)
  262. skip_swap:
  263. addiu $t1,$t1,1
  264. j sort_in
  265. sort_in_end:
  266. addiu $t0,$t0,1
  267. j sort
  268. sort_end:
  269. #brightness sorted here, just change pixel to valid value now
  270. lw $a0, 16($sp) # show procedure id to take for writing (pair id, brightness in $a0 now)
  271. srl $a0,$a0,16 #show procedure id to take for writing (only id in $a0 now)
  272. jal write_pixel # call procedure - it will do rest of things needed
  273. # now $t0 is valid pixel id
  274. addiu $t7,$t7,1 # progress next block
  275. j prl
  276. prl_end:
  277. addu $sp,$sp,36 # free place on stack needed for brightnesses with ids
  278. # Now whole line is processed and the result is on place showed by pl
  279. ##################################################################################
  280. ## Saving acctual line if it isnt end
  281. ##################################################################################
  282. beqz $s7, end_p3l_loop #when no more lines, end loop
  283. ## SYSCALL (write line to file)
  284. li $v0, 15 # write-to-file service
  285. move $a0, $s5 # show system file descriptor
  286. lw $t0, pl
  287. la $a1, 0($t0) # show system place to read from
  288. move $a2, $s6 # write a line size from showed pointer
  289. syscall # write whole line (processed, with is next in order)
  290. ## SYSCALL (read next line from source file)
  291. li $v0, 14 # read-from-file service
  292. move $a0, $s1 # show system file descriptor
  293. lw $t0, fl
  294. la $a1, 0($t0) # show system place for writing
  295. move $a2, $s6 # limit is the line size
  296. syscall # read whole line (next in order)
  297. # swap fl,sl,tl (new order)
  298. ## t0,$t1,$t2 - tmp value for swap
  299. lw $t0,fl
  300. lw $t1,sl
  301. lw $t2,tl
  302. sw $t1,fl
  303. sw $t2,sl
  304. sw $t0,tl
  305. ## t0,$t1,$t2 - free
  306. addiu $s7,$s7,-1 # process next line
  307. j p3l_loop # }
  308. end_p3l_loop:
  309. # Now all lines are processed and all without last 2 are saved in target file
  310. ##################################################################################
  311. ## Saving last two lines, free stack
  312. ##################################################################################
  313. ## SYSCALL (write line to file)
  314. li $v0, 15 # write-to-file service
  315. move $a0, $s5 # show system file descriptor
  316. lw $t0, pl
  317. la $a1, 0($t0) # show system place to read from
  318. move $a2, $s6 # write a line size from showed pointer
  319. syscall # write whole line
  320. ## SYSCALL (write next line to result file)
  321. li $v0, 15 # write-to-file service
  322. lw $t0, tl
  323. la $a1, 0($t0)
  324. syscall # write whole line
  325. ## $s7 - FREE
  326. # free stack of line information
  327. addu $sp,$sp,$s6
  328. addu $sp,$sp,$s6
  329. addu $sp,$sp,$s6
  330. addu $sp,$sp,$s6
  331. # Now all lines are saved and stack is free, its about the end
  332. exit:
  333. ## SYSCALL (close source file)
  334. li $v0, 16 # file-close service
  335. la $a0, 0($s1) # show system source file descirptor
  336. syscall # close fd1 (source file)
  337. ## SYSCALL (close result file)
  338. li $v0, 16 # file-close service
  339. la $a0, 0($s5) # show system result file descriptor
  340. syscall # close fd2 (result file)
  341. ## SYSCALL (print exit msg)
  342. li $v0, 4 # print_string
  343. la $a0, thanks # show adress of end msg
  344. syscall # print(thanks)
  345. la $a0, new_filename # show adress of end msg param
  346. syscall # print(thanks_param)
  347. la $a0, newline # show adress of new line symbol
  348. syscall # print(nl)
  349. ## SYSCALL (end program)
  350. li $v0, 10
  351. syscall # exit program
  352. take_pixel_b: # calculate $a0 pixel in block brightness and save in $a0 with id on more imporant 4 bits, need $t7 (acctual block offset) & fl,sl,tl to be set
  353. # now sl+t1*pixel_size is acctual block center
  354. # where pixel_size is 3bytes (R,G,B)
  355. ble $a0,2,rfl
  356. ble $a0,5,rsl
  357. #read from 3rd line
  358. lw $t2, tl
  359. addiu $t6,$a0,-6
  360. j end_read
  361. rsl:
  362. #read from 2nd line
  363. lw $t2, sl
  364. addiu $t6,$a0,-3
  365. j end_read
  366. rfl:
  367. #read from 1st line
  368. lw $t2, fl
  369. move $t6,$a0
  370. end_read:
  371. # now $t2 is begin of needed line counter
  372. # and $t6 is pixel number in this line (with offset in $t0)
  373. mul $t3, $t7, 3
  374. mul $t6, $t6, 3
  375. addiu $t3, $t3, -3
  376. addu $t3, $t3, $t6
  377. addu $t3, $t3, $t2
  378. # now $t3 shows needed pixel adress
  379. lb $t4,0($t3)
  380. andi $t4,$t4,0x000000ff
  381. lb $t5,1($t3)
  382. andi $t5,$t5,0x000000ff
  383. addu $t4,$t4,$t5
  384. lb $t5,2($t3)
  385. andi $t5,$t5,0x000000ff
  386. addu $t4,$t4,$t5
  387. # t4 is calculated brightness now
  388. sll $a0,$a0,16 #make pair id brightness
  389. addu $a0,$a0,$t4 #..
  390. jr $ra
  391. write_pixel: # write $a0 pixel to 4pixel in block, need $t7 (acctual block offset) & fl,sl,tl to be set
  392. # now sl+t1*pixel_size is acctual block center
  393. # where pixel_size is 3bytes (R,G,B)
  394. ble $a0,2,rflw
  395. ble $a0,5,rslw
  396. #read from 3rd line
  397. lw $t2, tl
  398. addiu $t6,$a0,-6
  399. j end_readw
  400. rslw:
  401. #read from 2nd line
  402. lw $t2, sl
  403. addiu $t6,$a0,-3
  404. j end_readw
  405. rflw:
  406. #read from 1st line
  407. lw $t2, fl
  408. move $t6,$a0
  409. end_readw:
  410. # now $t2 is begin of needed line counter
  411. # and $t6 is pixel number in this line (with offset in $t0)
  412. mul $t3, $t7, 3
  413. lw $t5,pl
  414. addu $t5,$t5,$t3
  415. mul $t6, $t6, 3
  416. addiu $t3, $t3, -3
  417. addu $t3, $t3, $t6
  418. addu $t3, $t3, $t2
  419. # now $t3 shows needed pixel adress
  420. lb $t4,0($t3)
  421. andi $t4,$t4,0x000000ff
  422. sb $t4,0($t5)
  423. #write new R
  424. lb $t4,1($t3)
  425. andi $t4,$t4,0x000000ff
  426. sb $t4,1($t5)
  427. #write new G
  428. lb $t4,2($t3)
  429. andi $t4,$t4,0x000000ff
  430. sb $t4,2($t5)
  431. #write new B
  432. jr $ra