; Однако, в остальном прототип функции верен, вернее, не то что бы он верен
; (на самом деле порядок аргументов обратный), но для использования – пригоден
MyFunc proc near ; CODE XREF: _main+12p
s = dword ptr 8
arg_4 = dword ptr 0Ch
arg_8 = dword ptr 10h
push ebp
mov ebp, esp
; Открываем кадр стека
mov eax, [ebp+s]
; Заносим в EAX указатель на строку
push eax ; s
call _strlen
; Передаем его функции strlen
pop ecx
; Очищаем стек от одного аргумента, выталкивая его в неиспользуемый регистр
mov edx, [ebp+arg_8]
; Заносим в EDX аргумент arg_8 типа int
add edx, [ebp+arg_4]
; Складываем его с аргументом arg_4
add eax, edx
; Складываем сумму arg_8 и arg_4 с длиной строки
pop ebp
retn 0Ch
; Стек чистит вызываемая функция. Значит, ее тип PASCAL
или stdcall
MyFunc endp
Листинг 65
Как мы видим, идентификация базовых типов вызов и восстановление прототипов функции – занятие несложное. Единственное, что портит настроение – путаница с PASCAL и stdcall, но порядок занесения аргументов в стек не имеет никакого значения, разве что в особых случаях, один из которых перед вами:
#include <stdio.h>
#include <windows.h>
#include <winuser.h>
// CALLBACK процедура для приема сообщений от таймера
VOID CALLBACK TimerProc(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
)
{
// Бибикаем всеми пиками на все голоса
MessageBeep((dwTime % 5)*0x10);
// Выводим время в секундах, прошедшее с момента пуска системы
printf("\r:=%d",dwTime / 1000);
}
main()
// Да, это консольное приложение, но оно так же может иметь цикл выборки сообщений
// и устанавливать таймер!
{
int a;