Gistrec

ASM 1 v1

Sep 24th, 2018
851
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. .386
  2. .MODEL FLAT, STDCALL
  3. ; прототипы внешних функций (процедур) описываются директивой EXTERN,
  4. ; после знака @ указывается общая длина передаваемых параметров,
  5. ; после двоеточия указывается тип внешнего объекта – процедура
  6. EXTERN  GetStdHandle@4: PROC
  7. EXTERN  WriteConsoleA@20: PROC
  8. EXTERN  CharToOemA@8: PROC
  9. EXTERN  ReadConsoleA@20: PROC
  10. EXTERN  ExitProcess@4: PROC; функция выхода из программы
  11. EXTERN  lstrlenA@4: PROC; функция определения длины строки
  12. EXTERN  wsprintfA: PROC; т.к. число параметров функции не фиксировано,
  13.             ; используется соглашение, согласно которому очищает стек
  14.             ; вызывающая процедура
  15.  
  16.  
  17. .DATA; сегмент данных
  18.  
  19. ; выводимая строка, в конце добавлены
  20. ; управляющие символы: 13 – возврат каретки, 10 – переход на новую
  21. ; строку, 0 – конец строки; с использованием директивы DB
  22. ; резервируется массив байтов
  23. WRITE_VALUE_STRING DB "Введите число в 16-ти ричной системе: ",13,10,0
  24.  
  25.  
  26. ;;;;; FMT DB "Число %d", 0; строка со списком форматов для функции wsprintfA
  27.  
  28. DIN DD ?; дескриптор ввода; директива DD резервирует память объемом
  29. ; 32 бита (4 байта), знак «?» используется для неинициализированных данных
  30. DOUT DD ?; дескриптор вывода
  31.  
  32. FIRST_VALUE  DB 50 dup (?); Первое число в строковм виде
  33. FIRST_LENGTH DD ? ; Длина первого числа
  34.  
  35. SECOND_VALUE DB 50 dup (?); Второе число
  36. SECOND_LENGTH DD ? ; Длина второго числа
  37.  
  38. RESULT_VALUE DB 200 dup (?); Строка с результатом
  39. RESULT_LENGTH DD ? ; Длина строки с результатом
  40.  
  41. LENS DD ? ; Буффер для длины строки (для ввода/вывода)
  42. D_IN DD ? ; Дескриптор ввода
  43. D_OUT DD ?; Дескриптор вывода
  44.  
  45. .CODE; сегмент кода
  46.  
  47.  
  48. MAIN PROC; описание процедуры
  49.  
  50.  
  51.  
  52. ; 1. Сначала перекодируем строку STRN для DOS (т.к. она содержит русские буквы)
  53. ; Перемещаем в регистр EAX адрес строки STRN (OFFSET возвращает адрес)
  54. MOV  EAX, OFFSET WRITE_VALUE_STRING;
  55.  
  56. ; У функции CharToOemA@8 два параметра - откуда берем строку и куда кладем
  57. ; Адрес строки
  58. PUSH EAX; параметры функции помещаются в стек командой PUSH
  59. PUSH EAX
  60. CALL CharToOemA@8; вызов функции
  61.  
  62.  
  63. ; 2. Получаем дескриптов ввода и вывода функцией GetStdHandle
  64. ; Аргумент функции: -10 для ввода, -11 для вывода, -12 для сообщения об ошибки
  65. ; Функция возвращает дескриптор в регистр EAX
  66. PUSH -10
  67. CALL GetStdHandle@4
  68. ; Перемещаем регистр вывода в новую переменную D_IN
  69. MOV D_IN, EAX
  70.  
  71. PUSH -11
  72. CALL GetStdHandle@4
  73. ; Перемещаем регистр вывода в новую переменную D_OUT
  74. MOV D_OUT, EAX
  75.  
  76. ; 3. Определяем длину строки WRITE_VALUE_STRING
  77. ; Аргумент функции: адрес строки. Возвращаемое значение: длина строки в регистре EAX
  78. PUSH OFFSET WRITE_VALUE_STRING
  79. CALL lstrlenA@4;
  80.  
  81. ; Выводим строку WRITE_VALUE_STRING функцией WriteConsoleA
  82. PUSH 0; 5-ый параметр всегда 0
  83. PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
  84. PUSH EAX; Длина строки, сколько хотим вывести
  85. PUSH OFFSET WRITE_VALUE_STRING; Адрес строки
  86. PUSH D_OUT; Регистр вывода
  87. CALL WriteConsoleA@20
  88.  
  89.  
  90. ; 4. Вводим строку FIRST_VALUE
  91. ; FIRST_LENGTH больше на два, дополнительно введены
  92. ; 13 - возврат каретки и 10 - переход на новую строку
  93. PUSH 0; 5-ый параметр всегда 0
  94. PUSH OFFSET FIRST_LENGTH; Длина считанной строки строки
  95. PUSH 50; Сколько символов хотим считать
  96. PUSH OFFSET FIRST_VALUE; Куда читаем
  97. PUSH D_IN; Регистр ввода
  98. CALL ReadConsoleA@20
  99.  
  100. ; TODO:
  101. ; Проверка на то, чтобы длина строки была больше 3
  102. ; И чтобы строка была меньше какого-то числа (избежать переполнение)
  103.  
  104. ; 5. Еще раз выводим сообщение о необходимости ввести второе число
  105. PUSH 0; 5-ый параметр всегда 0
  106. PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
  107. PUSH EAX; Длина строки, сколько хотим вывести
  108. PUSH OFFSET WRITE_VALUE_STRING; Адрес строки
  109. PUSH D_OUT; Регистр вывода
  110. CALL WriteConsoleA@20
  111.  
  112. ; 6. Вводим строку SECOND_VALUE
  113. PUSH 0; 5-ый параметр всегда 0
  114. PUSH OFFSET SECOND_LENGTH; Длина считанной строки строки
  115. PUSH 50; Сколько символов хотим считать
  116. PUSH OFFSET SECOND_VALUE; Куда читаем
  117. PUSH D_IN; Регистр ввода
  118. CALL ReadConsoleA@20
  119.  
  120.  
  121. ; TODO:
  122. ; Проверка на то, чтобы длина строки была больше 3
  123. ; И чтобы строка была меньше какого-то числа (избежать переполнение)
  124.  
  125. ; TODO:
  126. ; Посимвольно переводим две строки в десятиричную систему счислению
  127.  
  128. ; TODO:
  129. ; Перемножить два десятиричных числа MUL
  130. ; NOTE: Посмотреть что будет при большом числе (делит на два)
  131.  
  132. ; TODO:
  133. ; Вывести полученное число
  134.  
  135.  
  136. CALL ReadConsoleA@20 ; обратите внимание: LENS больше числа введенных
  137. ; символов на два, дополнительно введенные символы: 13 – возврат каретки и
  138. ; 10 – переход на новую строку
  139. ; вывод полученной строки
  140. PUSH 0
  141. PUSH OFFSET LENS
  142. PUSH LENS; длина вводимой строки
  143. PUSH OFFSET BUF
  144. PUSH DOUT
  145. CALL WriteConsoleA@20
  146. ; вывод числа 123 в буфер BUF
  147. PUSH 123
  148. PUSH OFFSET FMT
  149. PUSH OFFSET BUF
  150. CALL wsprintfA
  151. ADD ESP, 12; очистка стека от параметров (изменение регистра ESP
  152. ; на 3*4 = 12 байтов)
  153. ; вывод строки с числом 123
  154. PUSH 0
  155. PUSH OFFSET LENS
  156. PUSH EAX
  157. PUSH OFFSET BUF
  158. PUSH DOUT
  159. CALL WriteConsoleA@20
  160. ; небольшая задержка
  161. MOV ECX,03FFFFFFFH; помещение в регистр ECX – счетчик цикла –
  162. ; большого значения
  163. L1: LOOP L1; цикл без тела
  164. ; выход из программы
  165.  
  166.  
  167.  
  168. PUSH 0; параметр: код выхода
  169. CALL ExitProcess@4
  170. MAIN ENDP
  171. END MAIN
Advertisement