Процедура отдельным файлом.

Тема в разделе "WASM.BEGINNERS", создана пользователем Balamut, 7 июл 2018.

  1. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Друзья, не могу взять в толк, хочу сделать процедуру отдельным файлом, но не собирается exe.
    Код (ASM):
    1. ;sort Процедура сортировки байтов
    2. ;Вход: invoke, addr param2, addr param1
    3. ;      param1 адресс массива размерность dw
    4. ;      param2 кол-во байт в массиве dw
    5. ;Меняет регистры esi edi ecx ebx eax
    6. ;Выход:
    7. ;#########################################################################
    8. .586
    9.       .model flat, stdcall
    10.       option casemap :none
    11.       public sort                                  
    12. ;#########################################################################
    13.       include \masm32\include\windows.inc
    14.       include \masm32\include\user32.inc
    15.       include \masm32\include\kernel32.inc
    16.       includelib \masm32\lib\user32.lib
    17.       includelib \masm32\lib\kernel32.lib
    18. ;#########################################################################
    19.     .data
    20. ;#########################################################################
    21.     .code
    22.             sort proc
    23.             push ebp                                           ;пролог: сохранение EBP
    24.             mov ebp, esp                                    ;пролог: инициализация EBP
    25.             mov edi,[ebp+8]                            
    26.             dec edi                                
    27.             mov edx,edi                                      ;в edx счетчик внешнего цикл-1
    28.             xor ebx,ebx                                       ;если ebx=len-1 то прерываем внешний цикл и выходим
    29. lbig:
    30.             xor ecx,ecx                                        ;обнуляем ecx, который будет счетчиком внутреннего цикла
    31.             mov ecx,[ebp+8]                              ;в ecx кол-во байт массива
    32.             mov esi,[ebp+12]                             ;в esi АДРЕС массива
    33. intloop:
    34.             dec ecx                              
    35.             jcxz extloop                                       ;переход на внешний цикл если eсх=0
    36.             mov word ptr ax,[esi]                
    37.             cmp al,ah                                           ;иначе сравниваем текущий эл массива со следующим
    38.             jc normsort                                        ;если сортировка не требуется (al<ah)то идем к следующему эл-ту
    39.             xchg al,ah                                          ;иначе меняем эл местами
    40.             mov [esi],ax        
    41.             inc esi                                                 ;переход к следующему эл
    42.             jmp intloop                                         ;продолжаем внутренний цикл
    43. normsort:                      
    44.             inc ebx                                                ;увеличиваем ebx и
    45.             cmp ebx,edi                                        ;сравниваем с количеством эл-ов массива
    46.             je exit                                                  ;если ebx=len-1 то прерываем внешний цикл и выходим
    47.             inc esi                                                  ;иначе переходим к следующему эл-ту
    48.             jmp intloop
    49. extloop:  ;внешний цикл если eсх=0
    50.             xor ebx,ebx                                         ;сбрасываем счетчик преждевременного выхода
    51.             dec edx                                                ;уменьшаем счетчик внешнего цикла
    52.             cmp edx,0                                           ;если конец то выход
    53.             jne lbig                                                ;иначе сортируем дальше
    54. exit:
    55.             pop ebp                                                ;эпилог: восстановление EBP
    56.             ret 8                                                      ;освобождаем 8 байт из стека      
    57.             sort endp
    58.             END

    Код (ASM):
    1. .586
    2.       .model flat, stdcall
    3.       option casemap :none                                      
    4. ;#########################################################################
    5.       include \masm32\include\windows.inc
    6.       include \masm32\include\user32.inc
    7.       include \masm32\include\kernel32.inc
    8.       includelib \masm32\lib\user32.lib
    9.       includelib \masm32\lib\kernel32.lib
    10. ;#########################################################################
    11.       extern sort@8:near
    12.     .data
    13. unsort  db "gygyu87559898432zxmnd"                                             ;несортированный массив
    14. len= $-unsort                                                                                       ;длина массива
    15. ;#########################################################################
    16.     .code
    17.  start:
    18.     mov edx,len
    19.     push offset unsort
    20.     push edx
    21.     call sort@8
    22.  
    23. exit:
    24.     invoke ExitProcess, 0  
    25.                
    26.  end start

    Причем obj файлы делаются, но дальше masm32 ругается:

    main.obj : error LNK2001: unresolved external symbol _sort@8
    main.exe : fatal error LNK1120: 1 unresolved externals
     
  2. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Balamut,
    за правильность работы не отвечаю, но ехе-файл создался
    01.asm
    Код (ASM):
    1. ;sort Процедура сортировки байтов
    2. ;Вход: invoke, addr param2, addr param1
    3. ;      param1 адресс массива размерность dw
    4. ;      param2 кол-во байт в массиве dw
    5. ;Меняет регистры esi edi ecx ebx eax
    6. ;Выход:
    7. ;#########################################################################
    8. .586
    9.       .model flat, stdcall
    10.       option casemap :none
    11. ;#########################################################################
    12.       include \masm32\include\windows.inc
    13.       include \masm32\include\user32.inc
    14.       include \masm32\include\kernel32.inc
    15.       includelib \masm32\lib\user32.lib
    16.       includelib \masm32\lib\kernel32.lib
    17. ;#########################################################################
    18.     .data
    19. ;#########################################################################
    20.     .code
    21.             sort proc public param2:DWORD, param1:DWORD
    22.           mov edi,param2                    
    23.             dec edi                        
    24.             mov edx,edi                                      ;в edx счетчик внешнего цикл-1
    25.             xor ebx,ebx                                       ;если ebx=len-1 то прерываем внешний цикл и выходим
    26. lbig:
    27.             xor ecx,ecx                                        ;обнуляем ecx, который будет счетчиком внутреннего цикла
    28.             mov ecx,param2                              ;в ecx кол-во байт массива
    29.             mov esi,param1                             ;в esi АДРЕС массива
    30. intloop:
    31.             dec ecx                      
    32.             jcxz extloop                                       ;переход на внешний цикл если eсх=0
    33.             mov word ptr ax,[esi]        
    34.             cmp al,ah                                           ;иначе сравниваем текущий эл массива со следующим
    35.             jc normsort                                        ;если сортировка не требуется (al<ah)то идем к следующему эл-ту
    36.             xchg al,ah                                          ;иначе меняем эл местами
    37.             mov [esi],ax
    38.             inc esi                                                 ;переход к следующему эл
    39.             jmp intloop                                         ;продолжаем внутренний цикл
    40. normsort:              
    41.             inc ebx                                                ;увеличиваем ebx и
    42.             cmp ebx,edi                                        ;сравниваем с количеством эл-ов массива
    43.             je exit                                                  ;если ebx=len-1 то прерываем внешний цикл и выходим
    44.             inc esi                                                  ;иначе переходим к следующему эл-ту
    45.             jmp intloop
    46. extloop:  ;внешний цикл если eсх=0
    47.             xor ebx,ebx                                         ;сбрасываем счетчик преждевременного выхода
    48.             dec edx                                                ;уменьшаем счетчик внешнего цикла
    49.             cmp edx,0                                           ;если конец то выход
    50.             jne lbig                                                ;иначе сортируем дальше
    51. exit:    ret                         ;эпилог и освобождаем 8 байт из стека
    52.             sort endp
    53.             END
    02.asm
    Код (ASM):
    1. .586
    2.       .model flat, stdcall
    3.       option casemap :none                              
    4. ;#########################################################################
    5.       include \masm32\include\windows.inc
    6.       include \masm32\include\user32.inc
    7.       include \masm32\include\kernel32.inc
    8.       includelib \masm32\lib\user32.lib
    9.       includelib \masm32\lib\kernel32.lib
    10. ;#########################################################################
    11.       extern sort@8:dword
    12.     .data
    13. unsort  db "gygyu87559898432zxmnd"                                             ;несортированный массив
    14. len= $-unsort                                                                                       ;длина массива
    15. ;#########################################################################
    16.     .code
    17.  start:
    18.     mov edx,len
    19.     push offset unsort
    20.     push edx
    21.     call sort@8
    22. exit:
    23.     invoke ExitProcess, 0            
    24.  end start
    bat-файл
    @echo off
    \masm32\bin\ml /c /coff 01.asm
    \masm32\bin\ml /c /coff 02.asm
    \masm32\bin\Link /SUBSYSTEM:WINDOWS 02.obj 01.obj
    del 01.obj
    del 02.obj

    чтобы работало корректно, необходимо погонять экзешник под отладчиком, найти ошибки, исправить и снова пересобрать :)
     
    Balamut нравится это.
  3. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Mikl___
    Большое спасибо, сейчас погоняю.
    Делал процедуру исполняемым файлом, без передачи параметров в стек, и все работало как надо.
    Извините за настырность, но есть еще вопрос.Есть ли разница между call@8:byte и call@2:dword ведь по количеству байт это одно и тоже, или masm конролирует тип данных?
     
  4. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    @8 -- это очистить стек после выхода из процедуры от 8 байтов, но пишут "extern sort@8:dword" так как аргументы передаются в виде двордов. По поводу "masm контролирует тип данных?" не знаю, на ассемблере контроль лежит на человеке, это же на ЯВУ, где всё под присмотром компилятора
     
  5. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    То есть данная запись extern sort@8:dword это не 8 двойных слов, а именно 8 байт?
     
  6. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Да, extern функции в Win32 оканчиваются на @0, @4, @8, ..., @32 и т.д.
     
  7. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Еще раз большое спасибо за помощь и за терпение к чайникам.
     
  8. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Balamut,
    открой \masm32\include\user32.inc посмотри любую функцию, например CreateWindowExA, видишь, у нее 12 аргументов типа двойное слово (:lol: WORD)
    CreateWindowExA PROTO STDCALL :lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD,:lol: WORD

    а теперь открой \masm32\lib\user32.lib и найди поиском CreateWindowExA
    _CreateWindowExA@48
    <-- она заканчивается на 4 х 12 = @48
     
  9. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    То есть, вызывая ф-цию вот так (call@кол-во впихнутых в стек байт), мне необязательно явно возвращать стек в первоначальное состояние, типа ret n, (где n- кол-во впихнутых в стек байт)?
    Мне надо погонять, исправленный вами код, в ollydbg, думаю часть вопросов отпадет.
     
  10. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Код (ASM):
    1.            jne lbig                                                ;иначе сортируем дальше
    2. exit:   ret                       ;эпилог и освобождаем 8 байт из стека  
    3.             sort endp
    компилятор подставит вместо ret --> leave/retn 8 автоматом
     
  11. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Вот теперь,наконец-то, ко мне пришло понимание func@n, но как исправленная вами процедура будет брать из стека параметры, ведь в моем варианте все было явно через смещение регистра bp, а у вас, будто глобальные переменные.
    Хотя, может, я напутал вас описанием к функции.
     
  12. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Balamut,
    Код (ASM):
    1. sort proc public param2:DWORD, param1:DWORD
    2.          mov edi,param2                      
    3.             . . . .
    4.            mov ecx,param2                              ;в ecx кол-во байт массива
    5.            mov esi,param1
    компилятор сам подставит пролог и эпилог, локальные переменные (если требуется) и вместо param2 = [ebp+8], param1 = [ebp+12] и т.д. то есть избавит тебя от рутинной работы и ошибок
     
  13. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Не устану говорить спасибо, после ваших объяснений Masm мне нравится все больше и больше.
     
  14. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Balamut,
    Правила форума
    Цитируйте только суть, не стоит цитировать всё сообщение целиком :)
     
    Коцит нравится это.
  15. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Эх, снова застрял в коде. Почему вызов процедуры лезет в содержимое [памяти], а не переходит по значению?
    вот участок кода:
    .....
    CALL DWORD PTR [02.401020] ; call sort@8
    .....
    02.401020 my proc ; вот адрес самой процедуры
    В итоге, вызов берет дворд, состоящий из первых четырех опкодов процедуры, и переходит в никуда :sad:
     
  16. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Беру hiew32
    00.png
    адрес 40100Bh, виден вызов процедуры sort. По адресу 401020h располагается сама процедура
     
  17. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    А квадратные скобки? [000401020] т.е. переход по адресу 8bec8b55
     
  18. Mikl___

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

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Balamut,
    квадратные скобки нужны чтобы отличать адрес от числовой константы, то есть call ds:[000401020h] ― это вызов процедуры, расположенной по адресу 401020h. Не путай использование квадратных скобок с наименованием регистра и регистр без квадратных скобок.
     
  19. Balamut

    Balamut New Member

    Публикаций:
    0
    Регистрация:
    7 июл 2018
    Сообщения:
    13
    Выполняя пошагово код, вызов процедуры происходит у меня, именно по четырем байтам, на которые указывает 000401020h. Не пойму, почему так.
    Разве в call d,[000401020] буква d не указывает на дворд.
     
  20. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.615
    Адрес:
    Russia
    есть две инструкции jmp ofs и jmp mem - первая прыгает на адрес - ofs, а вторая, загружает ofs из памяти и потом на него прыгает - прямой и косвенный переход

    jmp dword ptr var_contained_ofs
    и
    jmp near i32

    call - аналогично
     
    Последнее редактирование: 8 июл 2018