.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
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎