Guest User

Untitled

a guest
Jun 25th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.63 KB | None | 0 0
  1.  
  2. ; factorial.asm
  3.  
  4.  
  5. ; this example gets the number from the user,
  6. ; and calculates factorial for it.
  7. ; supported input from 0 to 8 inclusive!
  8.  
  9.  
  10. ; this macro prints a char in AL and advances
  11. ; the current cursor position:
  12.  
  13.  
  14.  
  15. .model small
  16. .stack 100h
  17.  
  18. .data
  19. result dw ?
  20. ten dw 10
  21. msg1 db 0Dh,0Ah, 'enter the number: $'
  22. msg2 db 0Dh,0Ah, 'factorial: $'
  23. msg3 db 0Dh,0Ah, 'the result is too big!', 0Dh,0Ah, 'use values from 0 to 8.$'
  24.  
  25.  
  26. .code
  27.  
  28. start:
  29. putc macro char
  30. push ax
  31. mov al, char
  32. mov ah, 0eh
  33. int 10h
  34. pop ax
  35. endm
  36.  
  37. mov ax,@data
  38. mov ds,ax
  39.  
  40. lea dx, msg1
  41. mov ah, 9
  42. int 21h
  43. jmp n1
  44.  
  45. n1:
  46.  
  47. call scan_num
  48.  
  49.  
  50. ; factorial of 0 = 1:
  51. mov ax, 1
  52. cmp cx, 0
  53. je print_result
  54.  
  55. ; move the number to bx:
  56. ; cx will be a counter:
  57.  
  58. mov bx, cx
  59.  
  60. mov ax, 1
  61. mov bx, 1
  62.  
  63. calc_it:
  64. mul bx
  65. cmp dx, 0
  66. jne overflow
  67. inc bx
  68. loop calc_it
  69.  
  70. mov result, ax
  71.  
  72.  
  73. print_result:
  74.  
  75. ; print result in ax:
  76. lea dx, msg2
  77. mov ah, 9
  78. int 21h
  79.  
  80.  
  81. jmp n2
  82. n2:
  83.  
  84.  
  85. mov ax, result
  86. call print_num_uns
  87. jmp exit
  88.  
  89.  
  90. overflow:
  91. lea dx, msg3
  92. mov ah, 9
  93. int 21h
  94. jmp n3
  95. n3:
  96. jmp start
  97.  
  98. exit:
  99.  
  100. ; wait for any key press:
  101.  
  102. mov ah, 0
  103. int 16h
  104. mov ah,4ch
  105. int 21h
  106.  
  107. ret
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117. ;;; these functions are copied from emu8086.inc ;;;
  118. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  119.  
  120.  
  121. ; gets the multi-digit SIGNED number from the keyboard,
  122. ; and stores the result in CX register:
  123. SCAN_NUM PROC NEAR
  124. PUSH DX
  125. PUSH AX
  126. PUSH SI
  127.  
  128. MOV CX, 0
  129.  
  130. ; reset flag:
  131. MOV CS:make_minus, 0
  132.  
  133. next_digit:
  134.  
  135. ; get char from keyboard
  136. ; into AL:
  137. MOV AH, 00h
  138. INT 16h
  139. ; and print it:
  140. MOV AH, 0Eh
  141. INT 10h
  142.  
  143. ; check for MINUS:
  144. CMP AL, '-'
  145. JE set_minus
  146.  
  147. ; check for ENTER key:
  148. CMP AL, 0Dh ; carriage return?
  149. JNE not_cr
  150. JMP stop_input
  151. not_cr:
  152.  
  153.  
  154. CMP AL, 8 ; 'BACKSPACE' pressed?
  155. JNE backspace_checked
  156. MOV DX, 0 ; remove last digit by
  157. MOV AX, CX ; division:
  158. DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
  159. MOV CX, AX
  160. PUTC ' ' ; clear position.
  161. PUTC 8 ; backspace again.
  162. JMP next_digit
  163. backspace_checked:
  164.  
  165.  
  166. ; allow only digits:
  167. CMP AL, '0'
  168. JAE ok_AE_0
  169. JMP remove_not_digit
  170. ok_AE_0:
  171. CMP AL, '9'
  172. JBE ok_digit
  173. remove_not_digit:
  174. PUTC 8 ; backspace.
  175. PUTC ' ' ; clear last entered not digit.
  176. PUTC 8 ; backspace again.
  177. JMP next_digit ; wait for next input.
  178. ok_digit:
  179.  
  180.  
  181. ; multiply CX by 10 (first time the result is zero)
  182. PUSH AX
  183. MOV AX, CX
  184. MUL CS:ten ; DX:AX = AX*10
  185. MOV CX, AX
  186. POP AX
  187.  
  188. ; check if the number is too big
  189. ; (result should be 16 bits)
  190. CMP DX, 0
  191. JNE too_big
  192.  
  193. ; convert from ASCII code:
  194. SUB AL, 30h
  195.  
  196. ; add AL to CX:
  197. MOV AH, 0
  198. MOV DX, CX ; backup, in case the result will be too big.
  199. ADD CX, AX
  200. JC too_big2 ; jump if the number is too big.
  201.  
  202. JMP next_digit
  203.  
  204. set_minus:
  205. MOV CS:make_minus, 1
  206. JMP next_digit
  207.  
  208. too_big2:
  209. MOV CX, DX ; restore the backuped value before add.
  210. MOV DX, 0 ; DX was zero before backup!
  211. too_big:
  212. MOV AX, CX
  213. DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
  214. MOV CX, AX
  215. PUTC 8 ; backspace.
  216. PUTC ' ' ; clear last entered digit.
  217. PUTC 8 ; backspace again.
  218. JMP next_digit ; wait for Enter/Backspace.
  219.  
  220.  
  221. stop_input:
  222. ; check flag:
  223. CMP CS:make_minus, 0
  224. JE not_minus
  225. NEG CX
  226. not_minus:
  227.  
  228. POP SI
  229. POP AX
  230. POP DX
  231. RET
  232. make_minus DB ? ; used as a flag.
  233. SCAN_NUM ENDP
  234.  
  235.  
  236.  
  237.  
  238.  
  239. ; this procedure prints number in AX,
  240. ; used with PRINT_NUM_UNS to print signed numbers:
  241. PRINT_NUM PROC NEAR
  242. PUSH DX
  243. PUSH AX
  244.  
  245. CMP AX, 0
  246. JNZ not_zero
  247.  
  248. PUTC '0'
  249. JMP printed
  250.  
  251. not_zero:
  252. ; the check SIGN of AX,
  253. ; make absolute if it's negative:
  254. CMP AX, 0
  255. JNS positive
  256. NEG AX
  257.  
  258. PUTC '-'
  259.  
  260. positive:
  261. CALL PRINT_NUM_UNS
  262. printed:
  263. POP AX
  264. POP DX
  265. RET
  266. PRINT_NUM ENDP
  267.  
  268.  
  269.  
  270. ; this procedure prints out an unsigned
  271. ; number in AX (not just a single digit)
  272. ; allowed values are from 0 to 65535 (FFFF)
  273. PRINT_NUM_UNS PROC NEAR
  274. PUSH AX
  275. PUSH BX
  276. PUSH CX
  277. PUSH DX
  278.  
  279. ; flag to prevent printing zeros before number:
  280. MOV CX, 1
  281.  
  282. ; (result of "/ 10000" is always less or equal to 9).
  283. MOV BX, 10000 ; 2710h - divider.
  284.  
  285. ; AX is zero?
  286. CMP AX, 0
  287. JZ print_zero
  288.  
  289. begin_print:
  290.  
  291. ; check divider (if zero go to end_print):
  292. CMP BX,0
  293. JZ end_print
  294.  
  295. ; avoid printing zeros before number:
  296. CMP CX, 0
  297. JE calc
  298. ; if AX<BX then result of DIV will be zero:
  299. CMP AX, BX
  300. JB skip
  301. calc:
  302. MOV CX, 0 ; set flag.
  303.  
  304. MOV DX, 0
  305. DIV BX ; AX = DX:AX / BX (DX=remainder).
  306.  
  307. ; print last digit
  308. ; AH is always ZERO, so it's ignored
  309. ADD AL, 30h ; convert to ASCII code.
  310. PUTC AL
  311.  
  312.  
  313. MOV AX, DX ; get remainder from last div.
  314.  
  315. skip:
  316. ; calculate BX=BX/10
  317. PUSH AX
  318. MOV DX, 0
  319. MOV AX, BX
  320. DIV CS:ten ; AX = DX:AX / 10 (DX=remainder).
  321. MOV BX, AX
  322. POP AX
  323.  
  324. JMP begin_print
  325.  
  326. print_zero:
  327. PUTC '0'
  328.  
  329. end_print:
  330.  
  331. POP DX
  332. POP CX
  333. POP BX
  334. POP AX
  335. RET
  336. PRINT_NUM_UNS ENDP
  337. end
Add Comment
Please, Sign In to add comment