Advertisement
VladimirKostovsky

ASM Multiply Octal Decimal (RU)

Nov 27th, 2023 (edited)
3,127
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. .386 ; Ассемблерная директива, предписывающая использовать набор операций для; процессора 80386
  2. .MODEL FLAT, STDCALL ; Ассемблерная директива, определяющая модель памяти программы (модель управления стеком)
  3.  
  4.  
  5. ; Прототипы внешних процедур (После @ — общая длина передаваемых параметров,
  6. ; после : — тип внешнего объекта "Процедура")
  7. EXTERN  GetStdHandle@4: PROC   ; Функция определения дескриптора
  8. EXTERN  WriteConsoleA@20: PROC ; Функция вывода текста
  9. EXTERN  CharToOemA@8: PROC     ; Функция перекодировки
  10. EXTERN  ReadConsoleA@20: PROC  ; Функция ввода
  11. EXTERN  ExitProcess@4: PROC    ; Функция выхода из программы
  12. EXTERN  lstrlenA@4: PROC       ; Функция определения длины строки
  13. .DATA
  14. DIN DD ?                   ; Объявление переменной DIN для хранения ввода
  15. DOUT DD ?                  ; Объявление переменной DOUT для хранения вывода
  16. STRN1 DB "Введите первое восьмеричное число: ", 13, 10, 0  ; Строка приглашения для ввода первого числа
  17. STRN2 DB "Введите второе восьмеричное число: ", 13, 10, 0  ; Строка приглашения для ввода второго числа
  18. STRN3 DB "Результат умножения в десятичной системе: ", 13, 10, 0  ; Строка для вывода результата
  19. BUF DB 200 DUP (?)         ; Буфер для хранения введенных данных
  20. LENS DD ?                  ; Переменная для хранения длины ввода
  21. FlagA DD 0                 ; Флаг для первого числа
  22. FlagB DD 0                 ; Флаг для второго числа
  23. Two DD 2                   ; Константа для преобразования из восьмеричной в десятичную систему (степ. двойки)
  24. Ten DD 10                  ; Константа для десятичной системы
  25. NumA DD ?                  ; Переменная для хранения первого числа
  26. NumB DD ?                  ; Переменная для хранения второго числа
  27.  
  28. .CODE
  29. MAIN PROC                  ; Начало описания процедуры с именем MAIN
  30.                           ; Перекодируем строку STRN1
  31. PUSH OFFSET STRN1          ; Параметры функции помещаются в стек командой PUSH, OFFSET — операция,
  32.                           ;возвращающая адрес (смещения)
  33. CALL CharToOemA@8          ; Преобразование строки приглашения в ANSI
  34. PUSH -10                   ; STD_INPUT_HANDLE (константа вывода)
  35. CALL GetStdHandle@4        ; Получение дескриптора стандартного ввода
  36. MOV DIN, EAX              ; Сохранение дескриптора в переменной DIN
  37.  
  38. PUSH OFFSET STRN1
  39. CALL lstrlenA@4           ; Получение длины строки приглашения
  40. PUSH 0
  41. PUSH OFFSET LENS
  42. PUSH EAX
  43. PUSH OFFSET STRN1
  44. PUSH DIN
  45. CALL WriteConsoleA@20     ; Вывод приглашения для ввода первого числа в консоль
  46.  
  47. PUSH 0
  48. PUSH OFFSET LENS
  49. PUSH 200
  50. PUSH OFFSET BUF
  51. PUSH OFFSET LENS
  52. PUSH OFFSET DIN
  53. CALL ReadConsoleA@20      ; Чтение ввода пользователя в буфер
  54.  
  55. XOR EAX, EAX              ; Обнуление регистра EAX
  56. XOR EBX, EBX              ; Обнуление регистра EBX
  57. XOR ECX, ECX              ; Обнуление регистра ECX
  58. MOV ECX, 200              ; Установка счетчика на 200 (максимальная длина ввода)
  59. LEA ESI, [BUF]            ; Загрузка адреса буфера в регистр ESI
  60.  
  61. Convert1Loop:
  62. MOV AL, [ESI]             ; Загрузка байта из буфера в AL
  63. CMP AL, 0                 ; Сравнение с нулем (конец строки)
  64. JE Convert1Done           ; Если конец строки, завершить цикл
  65. SUB AL, '0'               ; Преобразование символа в число
  66. MUL Two                   ; Умножение текущего результата на 2
  67. ADD BX, AX                ; Прибавление нового значения к результату
  68. INC ESI                   ; Переход к следующему символу в буфере
  69. JMP Convert1Loop         ; Переход в начало цикла
  70.  
  71. Convert1Done:
  72. MOVZX EAX, BX             ; Загрузка результата в EAX
  73. MOV NumA, EAX             ; Сохранение результата в переменной NumA
  74.  
  75. PUSH OFFSET STRN2
  76. CALL CharToOemA@8         ; Преобразование строки приглашения в ANSI
  77.  
  78. PUSH -10                  ; STD_INPUT_HANDLE
  79. CALL GetStdHandle@4        ; Получение дескриптора стандартного ввода
  80. MOV DIN, EAX              ; Сохранение дескриптора в переменной DIN
  81.  
  82. PUSH OFFSET STRN2
  83. CALL lstrlenA@4           ; Получение длины строки приглашения
  84. PUSH 0
  85. PUSH OFFSET LENS
  86. PUSH EAX
  87. PUSH OFFSET STRN2
  88. PUSH DIN
  89. CALL WriteConsoleA@20     ; Вывод приглашения для ввода второго числа в консоль
  90.  
  91. PUSH 0
  92. PUSH OFFSET LENS
  93. PUSH 200
  94. PUSH OFFSET BUF
  95. PUSH OFFSET LENS
  96. PUSH OFFSET DIN
  97. CALL ReadFile@20          ; Чтение ввода пользователя в буфер
  98.  
  99. XOR EAX, EAX              ; Обнуление регистра EAX
  100. XOR EBX, EBX              ; Обнуление регистра EBX
  101. XOR ECX, ECX              ; Обнуление регистра ECX
  102. MOV ECX, 200              ; Установка счетчика на 200 (максимальная длина ввода)
  103. LEA ESI, [BUF]            ; Загрузка адреса буфера в регистр ESI
  104.  
  105. Convert2Loop:
  106. MOV AL, [ESI]             ; Загрузка байта из буфера в AL
  107. CMP AL, 0                 ; Сравнение с нулем (конец строки)
  108. JE Convert2Done           ; Если конец строки, завершить цикл
  109. SUB AL, '0'               ; Преобразование символа в число
  110. MUL Two                   ; Умножение текущего результата на 2
  111. ADD BX, AX                ; Прибавление нового значения к результату
  112. INC ESI                   ; Переход к следующему символу в буфере
  113. JMP Convert2Loop         ; Переход в начало цикла
  114.  
  115. Convert2Done:
  116. MOVZX EAX, BX             ; Загрузка результата в EAX
  117. MOV NumB, EAX             ; Сохранение результата в переменной NumB
  118. MOV EAX, NumA             ; Загрузка первого числа в EAX
  119. MOV EBX, NumB             ; Загрузка второго числа в EBX
  120. MUL EBX                   ; Умножение чисел, результат в EDX:EAX
  121. XOR EDI, EDI              ; Обнуление регистра EDI (для подсчета длины результата)
  122. MOV ESI, OFFSET BUF       ; Загрузка адреса буфера в ESI
  123. .WHILE EAX >= Ten         ; Цикл, пока результат больше или равен 10
  124.     DIV Ten               ; Деление на 10, остаток в EDX
  125.     ADD EDX, '0'          ; Преобразование остатка в символ и добавление к результату
  126.     PUSH EDX              ; Запись символа в стек
  127.     ADD EDI, 1            ; Увеличение счетчика длины
  128.     XOR EDX, EDX          ; Обнуление регистра EDX
  129. .ENDW
  130. ADD EAX, '0'              ; Преобразование оставшегося значения в символ
  131. PUSH EAX                  ; Запись символа в стек
  132. ADD EDI, 1                ; Увеличение счетчика длины
  133. CMP FlagA, 0              ; Проверка флага для первого числа
  134. JE Continue2              ; Если флаг сброшен, переход к метке Continue2
  135. CMP FlagB, 1              ; Проверка флага для второго числа
  136. JE Continue4              ; Если флаг установлен, переход к метке Continue4
  137. JNE Continue3             ; Если флаг сброшен, переход к метке Continue3
  138.  
  139. Continue2:
  140. CMP FlagB, 0              ; Проверка флага для второго числа
  141. JE Continue4              ; Если флаг сброшен, переход к метке Continue4
  142. JNE Continue3             ; Если флаг установлен, переход к метке Continue3
  143.  
  144. Continue3:
  145. PUSH '-'                  ; Помещение знака минус в стек
  146. ADD EDI, 1                ; Увеличение счетчика длины
  147.  
  148. Continue4:
  149. MOV ECX, EDI              ; Загрузка длины результата в ECX
  150. Convertc_c:
  151. POP [ESI]                 ; Извлечение символа из стека и запись в буфер
  152. INC ESI                   ; Переход к следующему символу в буфере
  153. LOOP Convertc_c           ; Повторение, пока ECX не достигнет 0
  154. PUSH OFFSET STRN3
  155. CALL CharToOemA@8         ; Преобразование строки результата в ANSI
  156. PUSH OFFSET STRN3
  157. CALL lstrlenA@4           ; Получение длины строки результата
  158. PUSH 0
  159. PUSH OFFSET LENS
  160. PUSH ECX
  161. PUSH OFFSET STRN3
  162. PUSH DOUT
  163. CALL WriteConsoleA@20     ; Вывод строки результата в консоль
  164. MOV ECX, 06FFFFFFFH       ; Инициализация счетчика для задержки (просто ожидание)
  165. L1:
  166. LOOP L1                   ; Петля ожидания
  167. PUSH 0
  168. CALL ExitProcess@4        ; Завершение программы
  169. MAIN ENDP
  170. END MAIN
  171.  
  172.  
Advertisement
Comments
Add Comment
Please, Sign In to add comment
Advertisement