Умножение/деление со сдвигом - Assembler

Узнай цену своей работы

Формулировка задачи:

Помогите исправить код. Пожалуйста. Операции умножения и деления выполнять с помощью операций сдвига. F= y-(96*x)/16 (8-битные со знаком) Ввод значений переменных организовать с клавиатуры. Вывод результата организовать на экран. Если размер результата будет более 16 бит – результат преобразовывать в 16-битный
Листинг программы
  1. LOCALS
  2. .model small
  3. .stack 100h
  4. .data
  5. CrLf db 0Dh, 0Ah, '$'
  6. PromptGetX db 'Input X (-32768..+32767): ', '$'
  7. PromptGetY db 'Input Y (-32768..+32767): ', '$'
  8. KeyBuf db 7, 0, 8 dup(0) ;max,len,string,CR(0dh)
  9. msgError db 'Ошибка ввода числа', 0Dh, 0Ah, '$'
  10. X db ?
  11. Y db ?
  12. F db ?
  13. .code
  14. main proc
  15. mov ax, @data
  16. mov ds, ax
  17. @@GetX:
  18. ; ввод числа с клавиатуры (строки)
  19. lea dx, PromptGetX
  20. mov ah,09h
  21. int 21h
  22. mov ah, 0Ah
  23. mov dx, offset KeyBuf
  24. int 21h
  25. ; перевод строки (на новую строку)
  26. lea dx, CrLf
  27. mov ah,09h
  28. int 21h
  29. ; преобразование строки в число
  30. lea si, KeyBuf+1
  31. lea di, X
  32. call Str2Num
  33. ; проверка на ошибку
  34. jnc @@GetY
  35. ; если есть ошибка ввода - напечатать сообщение об ошибке
  36. lea dx, msgError
  37. mov ah,09h
  38. int 21h
  39. jmp @@GetX
  40. @@GetY:
  41. ; ввод числа с клавиатуры (строки)
  42. lea dx, PromptGetY
  43. mov ah,09h
  44. int 21h
  45. mov ah, 0Ah
  46. mov dx, offset KeyBuf
  47. int 21h
  48. ; перевод строки (на новую строку)
  49. lea dx, CrLf
  50. mov ah,09h
  51. int 21h
  52. ; преобразование строки в число
  53. lea si, KeyBuf+1
  54. lea di, Y
  55. call Str2Num
  56. ; проверка на ошибку
  57. jnc @@Calc
  58. ; если есть ошибка ввода - напечатать сообщение об ошибке
  59. lea dx, msgError
  60. mov ah,09h
  61. int 21h
  62. jmp @@GetY
  63. @@Calc:
  64. ;F= y-(96*x)/16 ???
  65. mov cl, X
  66. sal cl,1
  67. sal cl,1
  68. sal cl,1
  69. mov bh, Y
  70. sub bh,cl
  71. mov F, bh
  72. call Show_AX
  73. mov ax, 4C00h
  74. int 21h
  75. main endp
  76. ; выводит число из регистра AX на экран
  77. ; входные данные:
  78. ; ax - число для отображения
  79. Show_AX proc
  80. push ax
  81. push bx
  82. push cx
  83. push dx
  84. push di
  85. mov cx, 10
  86. xor di, di ; di - кол. цифр в числе
  87. ; если число в ax отрицательное, то
  88. ;1) напечатать '-'
  89. ;2) сделать ax положительным
  90. or ax, ax
  91. jns @@Conv
  92. push ax
  93. mov dx, '-'
  94. mov ah, 2 ; ah - функция вывода символа на экран
  95. int 21h
  96. pop ax
  97. neg ax
  98. @@Conv:
  99. xor dx, dx
  100. div cx ; dl = num mod 10
  101. add dl, '0' ; перевод в символьный формат
  102. inc di
  103. push dx ; складываем в стэк
  104. or ax, ax
  105. jnz @@Conv
  106. ; выводим из стэка на экран
  107. @@Show:
  108. pop dx ; dl = очередной символ
  109. mov ah, 2 ; ah - функция вывода символа на экран
  110. int 21h
  111. dec di ; повторяем пока di<>0
  112. jnz @@Show
  113. pop di
  114. pop dx
  115. pop cx
  116. pop bx
  117. pop ax
  118. ret
  119. Show_AX endp
  120. ; преобразования строки в число
  121. ; на входе:
  122. ; ds:[si] - строка с числом
  123. ; ds:[di] - адрес числа
  124. ; на выходе
  125. ; ds:[di] - число
  126. ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
  127. Str2Num proc
  128. push ax
  129. push bx
  130. push cx
  131. push dx
  132. push ds
  133. push es
  134. push si
  135. push ds
  136. pop es
  137. mov cl, ds:[si]
  138. xor ch, ch
  139. inc si
  140. mov bx, 10
  141. xor ax, ax
  142. ;если в строке первый символ '-'
  143. ; - перейти к следующему
  144. ; - уменьшить количество рассматриваемых символов
  145. cmp byte ptr [si], '-'
  146. jne @@Loop
  147. inc si
  148. dec cx
  149. @@Loop:
  150. mul bx ; умножаем ax на 10 ( dx:ax=ax*bx )
  151. mov [di], ax ; игнорируем старшее слово
  152. cmp dx, 0 ; проверяем, результат на переполнение
  153. jnz @@Error
  154. mov al, [si] ; Преобразуем следующий символ в число
  155. cmp al, '0'
  156. jb @@Error
  157. cmp al, '9'
  158. ja @@Error
  159. sub al, '0'
  160. xor ah, ah
  161. add ax, [di]
  162. jc @@Error ; Если сумма больше 65535
  163. cmp ax, 8000h
  164. ja @@Error
  165. inc si
  166. loop @@Loop
  167. pop si ;проверка на знак
  168. push si
  169. inc si
  170. cmp byte ptr [si], '-'
  171. jne @@Check ;если должно быть положительным
  172. neg ax ;если должно быть отрицательным
  173. jmp @@StoreRes
  174. @@Check: ;дополнительная проверка, когда при вводе положительного числа получили отрицательное
  175. or ax, ax ;
  176. js @@Error
  177. @@StoreRes: ;сохранить результат
  178. mov [di], ax
  179. clc
  180. pop si
  181. pop es
  182. pop ds
  183. pop dx
  184. pop cx
  185. pop bx
  186. pop ax
  187. ret
  188. @@Error:
  189. xor ax, ax
  190. mov [di], ax
  191. stc
  192. pop si
  193. pop es
  194. pop ds
  195. pop dx
  196. pop cx
  197. pop bx
  198. pop ax
  199. ret
  200. Str2Num endp
  201. end main

Решение задачи: «Умножение/деление со сдвигом»

textual
Листинг программы
  1. LOCALS
  2.  
  3. .model small
  4.  
  5. .stack 100h
  6.  
  7. .data
  8.         CrLf            db      0Dh, 0Ah, '$'
  9.         PromptGetX      db      'Input X
  10. : ', '$'
  11.         PromptGetY      db      'Input Y: ', '$'
  12.         KeyBuf          db      7, 0, 8 dup(0)      
  13.  
  14. ;max,len,string,CR(0dh)
  15.         msgError        db      'Ошибка ввода числа', 0Dh, 0Ah, '$'
  16.  
  17.         X               db      ?
  18.         Y               db      ?
  19.         F               db      ?
  20. .code
  21.  
  22. main    proc
  23.         mov     ax,     @data
  24.         mov     ds,     ax
  25.  
  26. @@GetX:
  27.         ; ввод числа с клавиатуры (строки)
  28.         lea     dx, PromptGetX
  29.         mov     ah,09h
  30.         int     21h
  31.  
  32.         mov     ah, 0Ah
  33.         mov     dx, offset KeyBuf
  34.         int     21h
  35.  
  36.         ; перевод строки (на новую строку)
  37.         lea     dx, CrLf
  38.         mov     ah,09h
  39.         int     21h
  40.  
  41.         ; преобразование строки в число
  42.         lea     si, KeyBuf+1
  43.         lea     di, X
  44.         call    Str2Num
  45.  
  46.         ; проверка на ошибку
  47.         jnc     @@GetY
  48.  
  49.         ; если есть ошибка ввода - напечатать сообщение об ошибке
  50.         lea     dx, msgError
  51.         mov     ah,09h
  52.         int     21h
  53.         jmp     @@GetX
  54.  
  55. @@GetY:
  56.         ; ввод числа с клавиатуры (строки)
  57.         lea     dx, PromptGetY
  58.         mov     ah,09h
  59.         int     21h
  60.  
  61.         mov     ah, 0Ah
  62.         mov     dx, offset KeyBuf
  63.         int     21h
  64.  
  65.         ; перевод строки (на новую строку)
  66.         lea     dx, CrLf
  67.         mov     ah,09h
  68.         int     21h
  69.  
  70.         ; преобразование строки в число
  71.         lea     si, KeyBuf+1
  72.         lea     di, Y
  73.         call    Str2Num
  74.  
  75.         ; проверка на ошибку
  76.         jnc     @@Calc
  77.  
  78.         ; если есть ошибка ввода - напечатать сообщение об ошибке
  79.         lea     dx, msgError
  80.         mov     ah,09h
  81.         int     21h
  82.         jmp     @@GetY
  83.  
  84. @@Calc:
  85.     mov ax, 0 ;bx:=96*X
  86.     mov al, X
  87.     mov cl, 5
  88.     sal ax, cl
  89.     mov bx, ax
  90.     sal ax, 1
  91.     add bx, ax
  92.  
  93.     mov cl, 4 ;bx:=(96*X)/16
  94.     sar bx, cl
  95.  
  96.     mov bx, 9 ;ax:=Y
  97.     mov al, Y
  98.  
  99.     sub ax, bx ;ax:=Y-(96*X)/16
  100.      
  101.        
  102.         call    Show_AX
  103.  
  104.         mov     ax,     4C00h
  105.         int     21h
  106. main    endp
  107.  
  108. ; выводит число из регистра AX на экран
  109. ; входные данные:
  110. ; ax - число для отображения
  111. Show_AX proc
  112.         push    ax
  113.         push    bx
  114.         push    cx
  115.         push    dx
  116.         push    di
  117.  
  118.         mov     cx, 10
  119.         xor     di, di          ; di - кол. цифр в числе
  120.  
  121.         ; если число в ax отрицательное, то
  122.         ;1) напечатать '-'
  123.         ;2) сделать ax положительным
  124.         or      ax, ax
  125.         jns     @@Conv
  126.         push    ax
  127.         mov     dx, '-'
  128.         mov     ah, 2           ; ah - функция вывода символа на
  129.  
  130. экран
  131.         int     21h
  132.         pop     ax
  133.  
  134.         neg     ax
  135.  
  136. @@Conv:
  137.         xor     dx, dx
  138.         div     cx              ; dl = num mod 10
  139.         add     dl, '0'         ; перевод в символьный формат
  140.         inc     di
  141.         push    dx              ; складываем в стэк
  142.         or      ax, ax
  143.         jnz     @@Conv
  144.         ; выводим из стэка на экран
  145. @@Show:
  146.         pop     dx              ; dl = очередной символ
  147.         mov     ah, 2           ; ah - функция вывода символа на
  148.  
  149. экран
  150.         int     21h
  151.         dec     di              ; повторяем пока di<>0
  152.         jnz     @@Show
  153.  
  154.         pop     di
  155.         pop     dx
  156.         pop     cx
  157.         pop     bx
  158.         pop     ax
  159.         ret
  160. Show_AX endp
  161.  
  162. ; преобразования строки в число
  163. ; на входе:
  164. ; ds:[si] - строка с числом
  165. ; ds:[di] - адрес числа
  166. ; на выходе
  167. ; ds:[di] - число
  168. ; CY - флаг переноса (при ошибке - установлен, иначе - сброшен)
  169. Str2Num proc
  170.         push    ax
  171.         push    bx
  172.         push    cx
  173.         push    dx
  174.         push    ds
  175.         push    es
  176.         push    si
  177.  
  178.         push    ds
  179.         pop     es
  180.  
  181.         mov     cl, ds:[si]
  182.         xor     ch, ch
  183.  
  184.         inc     si
  185.  
  186.         mov     bx, 10
  187.         xor     ax, ax
  188.  
  189.         ;если в строке первый символ '-'
  190.         ; - перейти к следующему
  191.         ; - уменьшить количество рассматриваемых символов
  192.         cmp     byte ptr [si], '-'
  193.         jne     @@Loop
  194.         inc     si
  195.         dec     cx
  196. @@Loop:
  197.         mul     bx         ; умножаем ax на 10 ( dx:ax=ax*bx )
  198.         mov     [di], ax   ; игнорируем старшее слово
  199.         cmp     dx, 0      ; проверяем, результат на переполнение
  200.         jnz     @@Error
  201.  
  202.         mov     al, [si]   ; Преобразуем следующий символ в число
  203.         cmp     al, '0'
  204.         jb      @@Error
  205.         cmp     al, '9'
  206.         ja      @@Error
  207.         sub     al, '0'
  208.         xor     ah, ah
  209.         add     ax, [di]
  210.         jc      @@Error    ; Если сумма больше 65535
  211.         cmp     ax, 8000h
  212.         ja      @@Error
  213.         inc     si
  214.  
  215.         loop    @@Loop
  216.  
  217.         pop     si         ;проверка на знак
  218.         push    si
  219.         inc     si
  220.         cmp     byte ptr [si], '-'
  221.         jne     @@Check    ;если должно быть положительным
  222.         neg     ax         ;если должно быть отрицательным
  223.         jmp     @@StoreRes
  224. @@Check:                   ;дополнительная проверка, когда при вводе
  225.  
  226. положительного числа получили отрицательное
  227.        or       ax, ax     ;
  228.        js       @@Error
  229. @@StoreRes:                ;сохранить результат
  230.         mov     [di], ax
  231.         clc
  232.         pop     si
  233.         pop     es
  234.         pop     ds
  235.         pop     dx
  236.         pop     cx
  237.         pop     bx
  238.         pop     ax
  239.         ret
  240. @@Error:
  241.         xor     ax, ax
  242.         mov     [di], ax
  243.         stc
  244.         pop     si
  245.         pop     es
  246.         pop     ds
  247.         pop     dx
  248.         pop     cx
  249.         pop     bx
  250.         pop     ax
  251.         ret
  252. Str2Num endp
  253.  
  254. end     main

Объяснение кода листинга программы

  1. Устанавливаются локальные переменные и параметры модели компоновки.
  2. Инициализируются переменные для вывода сообщений на экран и ввода/вывода данных.
  3. Определяется сообщение об ошибке.
  4. Инициализируются переменные для хранения вводимых значений X, Y и результата F.
  5. В процедуре main инициализируются стек и сегмент данных, инициализируются регистры.
  6. Происходит ввод значений X и Y с клавиатуры путем вызова соответствующих сообщений и обработки пользовательского ввода.
  7. Переводятся введенные строки в числа.
  8. Если произошла ошибка ввода, выводится сообщение об ошибке, и процесс ввода повторяется.
  9. Рассчитывается значение переменной F с использованием операций умножения, деления и арифметических операций.
  10. Результат выводится на экран с помощью процедуры Show_AX.
  11. Программа завершается системным вызовом.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут