jnz L1 ; Если ECX не равно 0, продолжаем цикл
L2: pop esi ; Восстанавливаем значения использовавшихся регистров
pop ebx
mov esp, ebp ; Освобождаем стек
pop ebp ; Восстанавливаем значение регистра EBP
ret
InputNumber endp
Процедура вывода числа в 16-ричной системе счисления. Процедура получает один параметр – выводимое число. Для вывода всегда формируется строка из 8-ми шестнадцатеричных цифр с лидирующими нулями. Поскольку количество символов заранее известно, они будут сразу же записываться в строку с конца, и инвертировать строку не придётся. Процедура предназначена для использования в консольном приложении и предполагает, что идентификатор устройства ввода был получен основной программой и сохранён в переменной hStdOut.
digits db '0123456789abcdef' ; Массив шестнадцатеричных цифр
OutputNumber proc
push ebp ; Сохраняем в стеке значение регистра EBP
mov ebp, esp ; Заносим в регистр EBP текущее значение вершины стека
sub esp, 12 ; Выделяем в стеке место под формируемую строку
push esi
; Преобразуем число в строку
mov eax, [ebp + 8] ; Заносим в регистр EAX переданный параметр
mov ecx, 8 ; Заносим в регистр ECX количество символов строки
mov byte ptr [ebp - 1], 10 ; Добавляем в конец строки символы с кодами 13 и 10 для перевода курсора
mov byte ptr [ebp - 2], 13
lea esi, [ebp - 3] ; Начиная с адреса [EBP - 3] будут заносится цифры
L3: mov edx, eax ; Копируем значение регистра EAX в регистр EDX
and edx, 1111b ; Получаем остаток от деления на 16
shr eax, 4 ; Делим исходное число на 16
mov dl, digits[edx] ; По полученному остатку от деления берём цифру...
mov [esi], dl ; ... и записываем её в строку
dec esi ; Уменьшаем адрес, т. к. строка формируется с конца
dec ecx ; Уменьшаем ECX на 1
jnz L3 ; Если ECX не равно 0, продолжаем цикл
; Выводим строку
inc esi ; Регистр ESI указывает на начало строки
push 0
push 0
push 10
push esi
push hStdOut
call WriteConsole
pop esi
mov esp, ebp ; Освобождаем стек
pop ebp ; Восстанавливаем значение регистра EBP
ret 4 ; Удаляем из стека переданный параметр и возвращаемся
OutputNumber endp
Функция, находящая в одномерном массиве x сумму значений f(x[i]), где f – некоторая функция одного целочисленного аргумента, адрес которой передаётся через параметры. Функции используют соглашение о вызовах cdecl.
Sum proc
push ebp
mov ebp, esp
push esi
push edi
mov ecx, [ebp + 8] ; Заносим в ECX первый параметр – количество элементов массива
mov esi, [ebp + 12] ; Заносим в ESI второй параметр – адрес начала массива
mov edi, [ebp + 16] ; Заносим в EDI третий параметр – адрес функции
xor edx, edx ; Обнуляем регистр EDX
L: push [esi] ; Кладём в стек элемент массива
call edi ; Вызываем функцию, адрес которой находится в регистре EDI
add esp, 4 ; Освобождаем стек
add edx, eax ; Прибавляем результат функции к общей сумме
add esi, 4 ; Переходим к следующему элементу массива
dec ecx ; Уменьшаем значение регистра ECX на 1
jnz L ; Если ECX не равно 0, продолжаем цикл
mov eax, edx ; Записываем полученную сумму в регистр EAX,
; через который должен возвращаться результат функции
pop edi
pop esi
mov esp, ebp
pop ebp
ret
Sum endp
Sqr proc
mov eax, [esp + 4]
imul eax
ret
Sqr endp
Negation proc
mov eax, [esp + 4]
neg eax
ret
Negation endp
Для вызова функции Sum будет использовать следующая последовательность команд.
push Sqr
push offset a
push na
call Sum
add esp, 12
mov sa, eax
push Negation
push offset a
push na
call Sum
add esp, 12
mov sa, eax
Процедура, проверяющая сбалансированность круглых и квадратных скобок в строке. Строка должна заканчиваться нулём. Для проверки сбалансированности открывающие скобки будем класть в стек, а при нахождении в строке закрывающей скобки будем извлекать из стека последнюю положенную туда открывающую скобку и проверять, что она соответствует закрывающей скобке. Будем считать, что скобок в тексте меньше, чем других символов, поэтому после сравнения делаем переход «если равно», считая, что это событие менее вероятно. При любом выходе из процедуры нужно очистить стек. Поскольку мы не можем заранее знать, сколько скобок будет туда положено и сколько извлечено, восстановление значения регистра ESP можно сделать только с помощью регистра EBP. Процедура возвращает значение через регистр EAX: если скобки сбалансированы, регистр EAX будет содержать значение истина (-1), в противном случае регистр EAX будет содержать значение ложь (0).
Brackets proc
push ebx ; Сохраняем регистры
push ebp
mov ebp, esp ; Сохраняем начальное значение регистра ESP
mov ebx, [ebp + 12] ; Заносим в регистр EBX адрес начала строки
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |


