Обязательное выравнивание между функцией WSARecv и адреса структуры WSABUF

Тема в разделе "WASM.WIN32", создана пользователем NANO_VIRUS, 24 июл 2017.

  1. NANO_VIRUS

    NANO_VIRUS New Member

    Публикаций:
    0
    Регистрация:
    24 июл 2017
    Сообщения:
    15
    Приветствую.
    Начал программировать свой собственный web сервер для windows, и столкнулся с проблемой, которую позже решил, но так и не понял почему она возникает.

    Началось с того, что я начал выполнение функции (WSARecv) с правильными параметрами, но она всю равно выдавала ошибку (WSAEFAULT). В итоге методом тыка начал пошагово искать проблему. Остановился на том, что функция стала работать с условием, что от начала секции кода и до конца метки "WSABUF", должна присутствовать четность на 4 в байтах (если я правильно это назвал). Если это соблюдать, то все работает, но меня мучает вопрос, почему так происходит, и есть ли подобное в других функциях.

    Код для теста:
    Код (ASM):
    1. format PE GUI 4.0
    2. entry start
    3. include 'win32a.inc'
    4. section '.code' code import writeable readable executable
    5. library kernel32, 'KERNEL32.DLL',\
    6.    wsock32, 'Ws2_32.dll'
    7. include 'api\kernel32.inc'
    8. include 'api\wsock32.inc'
    9. start:
    10. ; Инициализация Winsock:
    11. push wsa ; _Out_ Адрес структуры "WSADATA"
    12. push 0x0101 ; _In_ Версия "1.1"
    13. call [WSAStartup] ; _Ret_ [0 / error]
    14. ; Создаем сокет:
    15. push 1 ; _In_ Флаг "WSA_FLAG_OVERLAPPED"
    16. push 0 ; _In_ Групповая операция не выполняется
    17. push 0 ; _In_ Характеристики сокета по умолчанию
    18. push 6 ; _In_ Протокол соединения "IPPROTO_TCP"
    19. push SOCK_STREAM ; _In_ Спецификация типа сокета
    20. push AF_INET ; _In_ Семейство адресов интернет-протокола версии 4 (IPv4)
    21. call [WSASocketW] ; _Ret_ [SOCKET / error]
    22. mov [sock], eax
    23. ; Cвязываем локальный адрес с гнездом:
    24. push sizeof.sockaddr_in ; _In_ Размер структуры "sockaddr_in"
    25. push saddr ; _In_ Адрес структуры "sockaddr_in"
    26. push [sock] ; _In_ Дескриптор сокета полученый функцией "WSASocketW"
    27. call [bind] ; _Ret_ [0 / error]
    28. ; Переводим режим сокета для входящих соединений:
    29. push 0x7fffffff ; _In_ Максимальная длина очереди ожидающих соединений
    30. push [sock] ; _In_ Дескриптор сокета полученый функцией "WSASocketW"
    31. call [listen] ; _Ret_ [0 / error]
    32. next:
    33. ; Ждем соединения:
    34. push 0 ; _In_ Данные обратного вызова не получаем, по причиние отсудствия фильтрациии соеденений
    35. push 0 ; _In_ Фильтрация соединений отключаем
    36. push 0 ; _Out_ Адрес размера структуры "sockaddr_in" не указываем
    37. push 0 ; _Out_ Адрес структуры "sockaddr_in" не указываем
    38. push [sock] ; _In_ Дескриптор сокета полученый функцией "WSASocketW"
    39. call [WSAAccept] ; _Ret_ [SOCKET / error]
    40. mov [socketconnect], eax
    41. ; Принимает данные из подключенного соединения:
    42. push 0 ; _In_ Адрес процедуры завершения не указываем
    43. push 0 ; _In_ Адрес структуры "WSAOVERLAPPED" не указываем
    44. push Flags ; _Out_ Адрес получения флагов
    45. push RecvBytes ; _Out_ Адрес получения размера сообщения в байтах
    46. push 1 ; _In_ Количество "WSABUF" структур
    47. push WSABUF ; _In_ Адрес структуры "WSABUF"
    48. push [socketconnect] ; _In_ Дескриптор сокета полученый функцией "WSAAccept"
    49. call [WSARecv] ; _Ret_ [0 / error]
    50. ; Закрываем соединение:
    51. push [socketconnect] ; _In_ Дескриптор сокета полученый функцией "WSAAccept"
    52. call [CloseHandle] ; _Ret_ [nonzero / error]
    53. jmp next
    54.     wsa WSADATA ; Структура для получения информации от функции "WSAStartup"
    55.     port     dd 80 ; Порт подключения HTTP
    56.     sock dd 0 ; Дескриптор основного сокета
    57.     socketconnect     dd 0 ; Дескриптор подключенного сокета
    58. RecvBytes dd 0 ; Размер сообщения в байтах полученной функцией "WSARecv"
    59. Flags dd 0 ; Флаги сообщения полученной функцией "WSARecv"
    60. ; Структура sockaddr_in:
    61. saddr:
    62. dw AF_INET ; Семейство адресов (должно быть AF_INET)
    63. dw 20480 ; Sin ip-port конвертация из 80 порта функцией "htons" (не стал вписывать)
    64. dd 0 ; Sin ip-adress
    65. rd 8 ; Дополнение, чтобы сделать структуру с полным размером "SOCKADDR"
    66. ;-----------------------------------------------------------:
    67. ; Растояние от метки "start" до метки "WSABUF", равна 608, что делится на 4 " 608 / 4 = 152 "
    68. rb 1 ; Тут меняю количество байтов, пока не получу четность на 4.
    69. ;-----------------------------------------------------------:
    70. ; Структура WSABUF для принятия данных функцией "WSARecv":
    71. WSABUF:
    72. .len dd 2048 ; Размер в байтах
    73. .buf dd buffer ; Адрес буфера
    74. ; Выделяем память в самом файле
    75. buffer:
    76. rb 2048
     
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Да, это называется кратность адреса. Например. при создании ресурсов в секции данных, адрес ресурсов должен быть кратен 4 байтам, многие структуры для Win x64 должны быть расположены (выровнены) по адресу кратному 8, для masm это выполняется командой align 4
     
    NANO_VIRUS нравится это.
  3. NANO_VIRUS

    NANO_VIRUS New Member

    Публикаций:
    0
    Регистрация:
    24 июл 2017
    Сообщения:
    15
    Спасибо