Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .386
- .MODEL FLAT, STDCALL
- ; прототипы внешних функций (процедур) описываются директивой EXTERN,
- ; после знака @ указывается общая длина передаваемых параметров,
- ; после двоеточия указывается тип внешнего объекта – процедура
- EXTERN GetStdHandle@4: PROC
- EXTERN WriteConsoleA@20: PROC
- EXTERN CharToOemA@8: PROC
- EXTERN ReadConsoleA@20: PROC
- EXTERN ExitProcess@4: PROC; функция выхода из программы
- EXTERN lstrlenA@4: PROC; функция определения длины строки
- EXTERN wsprintfA: PROC; т.к. число параметров функции не фиксировано,
- ; используется соглашение, согласно которому очищает стек
- ; вызывающая процедура
- .DATA; сегмент данных
- ; выводимая строка, в конце добавлены
- ; управляющие символы: 13 – возврат каретки, 10 – переход на новую
- ; строку, 0 – конец строки; с использованием директивы DB
- ; резервируется массив байтов
- WRITE_VALUE_STRING DB "Введите число в 16-ти ричной системе: ",13,10,0
- ;;;;; FMT DB "Число %d", 0; строка со списком форматов для функции wsprintfA
- DIN DD ?; дескриптор ввода; директива DD резервирует память объемом
- ; 32 бита (4 байта), знак «?» используется для неинициализированных данных
- DOUT DD ?; дескриптор вывода
- FIRST_VALUE DB 50 dup (?); Первое число в строковм виде
- FIRST_LENGTH DD ? ; Длина первого числа
- SECOND_VALUE DB 50 dup (?); Второе число
- SECOND_LENGTH DD ? ; Длина второго числа
- RESULT_VALUE DB 200 dup (?); Строка с результатом
- RESULT_LENGTH DD ? ; Длина строки с результатом
- LENS DD ? ; Буффер для длины строки (для ввода/вывода)
- D_IN DD ? ; Дескриптор ввода
- D_OUT DD ?; Дескриптор вывода
- .CODE; сегмент кода
- MAIN PROC; описание процедуры
- ; 1. Сначала перекодируем строку STRN для DOS (т.к. она содержит русские буквы)
- ; Перемещаем в регистр EAX адрес строки STRN (OFFSET возвращает адрес)
- MOV EAX, OFFSET WRITE_VALUE_STRING;
- ; У функции CharToOemA@8 два параметра - откуда берем строку и куда кладем
- ; Адрес строки
- PUSH EAX; параметры функции помещаются в стек командой PUSH
- PUSH EAX
- CALL CharToOemA@8; вызов функции
- ; 2. Получаем дескриптов ввода и вывода функцией GetStdHandle
- ; Аргумент функции: -10 для ввода, -11 для вывода, -12 для сообщения об ошибки
- ; Функция возвращает дескриптор в регистр EAX
- PUSH -10
- CALL GetStdHandle@4
- ; Перемещаем регистр вывода в новую переменную D_IN
- MOV D_IN, EAX
- PUSH -11
- CALL GetStdHandle@4
- ; Перемещаем регистр вывода в новую переменную D_OUT
- MOV D_OUT, EAX
- ; 3. Определяем длину строки WRITE_VALUE_STRING
- ; Аргумент функции: адрес строки. Возвращаемое значение: длина строки в регистре EAX
- PUSH OFFSET WRITE_VALUE_STRING
- CALL lstrlenA@4;
- ; Выводим строку WRITE_VALUE_STRING функцией WriteConsoleA
- PUSH 0; 5-ый параметр всегда 0
- PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
- PUSH EAX; Длина строки, сколько хотим вывести
- PUSH OFFSET WRITE_VALUE_STRING; Адрес строки
- PUSH D_OUT; Регистр вывода
- CALL WriteConsoleA@20
- ; 4. Вводим строку FIRST_VALUE
- ; FIRST_LENGTH больше на два, дополнительно введены
- ; 13 - возврат каретки и 10 - переход на новую строку
- PUSH 0; 5-ый параметр всегда 0
- PUSH OFFSET FIRST_LENGTH; Длина считанной строки строки
- PUSH 50; Сколько символов хотим считать
- PUSH OFFSET FIRST_VALUE; Куда читаем
- PUSH D_IN; Регистр ввода
- CALL ReadConsoleA@20
- ; TODO:
- ; Проверка на то, чтобы длина строки была больше 3
- ; И чтобы строка была меньше какого-то числа (избежать переполнение)
- ; 5. Еще раз выводим сообщение о необходимости ввести второе число
- PUSH 0; 5-ый параметр всегда 0
- PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
- PUSH EAX; Длина строки, сколько хотим вывести
- PUSH OFFSET WRITE_VALUE_STRING; Адрес строки
- PUSH D_OUT; Регистр вывода
- CALL WriteConsoleA@20
- ; 6. Вводим строку SECOND_VALUE
- PUSH 0; 5-ый параметр всегда 0
- PUSH OFFSET SECOND_LENGTH; Длина считанной строки строки
- PUSH 50; Сколько символов хотим считать
- PUSH OFFSET SECOND_VALUE; Куда читаем
- PUSH D_IN; Регистр ввода
- CALL ReadConsoleA@20
- ; TODO:
- ; Проверка на то, чтобы длина строки была больше 3
- ; И чтобы строка была меньше какого-то числа (избежать переполнение)
- ; TODO:
- ; Посимвольно переводим две строки в десятиричную систему счислению
- ; TODO:
- ; Перемножить два десятиричных числа MUL
- ; NOTE: Посмотреть что будет при большом числе (делит на два)
- ; TODO:
- ; Вывести полученное число
- CALL ReadConsoleA@20 ; обратите внимание: LENS больше числа введенных
- ; символов на два, дополнительно введенные символы: 13 – возврат каретки и
- ; 10 – переход на новую строку
- ; вывод полученной строки
- PUSH 0
- PUSH OFFSET LENS
- PUSH LENS; длина вводимой строки
- PUSH OFFSET BUF
- PUSH DOUT
- CALL WriteConsoleA@20
- ; вывод числа 123 в буфер BUF
- PUSH 123
- PUSH OFFSET FMT
- PUSH OFFSET BUF
- CALL wsprintfA
- ADD ESP, 12; очистка стека от параметров (изменение регистра ESP
- ; на 3*4 = 12 байтов)
- ; вывод строки с числом 123
- PUSH 0
- PUSH OFFSET LENS
- PUSH EAX
- PUSH OFFSET BUF
- PUSH DOUT
- CALL WriteConsoleA@20
- ; небольшая задержка
- MOV ECX,03FFFFFFFH; помещение в регистр ECX – счетчик цикла –
- ; большого значения
- L1: LOOP L1; цикл без тела
- ; выход из программы
- PUSH 0; параметр: код выхода
- CALL ExitProcess@4
- MAIN ENDP
- END MAIN
Advertisement