Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.08.2010, 21:28   #1
ZahAlex
Пользователь
 
Регистрация: 08.04.2009
Сообщений: 45
По умолчанию Проблема с CALL на MASM32

При создании EXE-шника компоновщик MASM во всех вызовах как CALL так и INVOKE делает им стандартный выход:
leave
ret 04
Причём при вызове DLL входную часть прописывает:
push esp
mov ebp,esp
///////////// - код
leave
ret 04
А при вызове локального SUBа не прописывает. Идёт глюк по стёку.
Вопрос: Как заставить MASM линковать только то, что я написал, без вышеуказанных входов и выходов CALLов.
После изучения ассемблера стал мозг зависать...
ZahAlex вне форума Ответить с цитированием
Старый 23.08.2010, 21:42   #2
Goodwin98
equ asm
Участник клуба
 
Аватар для Goodwin98
 
Регистрация: 02.05.2009
Сообщений: 1,605
По умолчанию

Цитата:
Как заставить MASM линковать только то, что я написал, без вышеуказанных входов и выходов CALLов.
Просто не оформляйте кусок кода, как подпрограмму.
Цитата:
А при вызове локального SUBа не прописывает. Идёт глюк по стёку.
Что это означает ?
Какой вопрос - такой ответ. Не забываем пользоваться поиском, гуглом.
Помощь в выполнении работ по ассемблеру ICQ:2725322O4
Goodwin98 вне форума Ответить с цитированием
Старый 23.08.2010, 22:00   #3
ZahAlex
Пользователь
 
Регистрация: 08.04.2009
Сообщений: 45
По умолчанию

А как не оформлять, тогда как оформлять (это DLL!)

Там где написано invoke [function], начало и конец функции выглядят в дебаге так:
push esp
mov ebp,esp
///////////// - код
leave
ret 04
А там где CALL [соседняя метка]:
///////////// - код
leave
ret 04
EIP не восстанавливается куда нужно из-за leave
После изучения ассемблера стал мозг зависать...
ZahAlex вне форума Ответить с цитированием
Старый 23.08.2010, 23:29   #4
yuran666666
Форумчанин
 
Аватар для yuran666666
 
Регистрация: 23.04.2009
Сообщений: 346
По умолчанию

оформить функцию просто как метку, локальные переменные высчитывать придется нецензурно вспоминая матерей создателей стека и интела
также посмотрите хорошую инструкцию enter -> leave
ну и ret должен быть с циферкой в зависимости от количества аргументов с которыми вызывали функцию

>При создании EXE-шника компоновщик MASM во всех вызовах как CALL >так и INVOKE делает им стандартный выход:
>leave
>ret 04
это неверно!

; вот малюсенький пример, показывающий пример вызова своей функции, в ней
;можно убрать enter и leave, и параметр передавать не в стеке, а в регистре..
;вообщем посмотрите в отладчике-ничего сложного
Код:
Код:
	.386
	.model flat,stdcall
	option casemap:none
.data
string	db "Is my function!",0
.code
start:
push offset string
call strlen
ret

strlen:
enter 4,0 ; занимаем место под локальную переменную(4 байта), оно в прынцыпе не нужно
pushad
cld
mov edi,[ebp+8] ;в edi кладем адрес начала строки (аргумент функции)
xor eax,eax
xor ecx,ecx
dec ecx
repnz scasb ;находим конец строки
not ecx
dec ecx    ;высчитваем ее длину
mov [ebp],ecx ;сохраняем в локальной переменной
popad
mov eax,[ebp] ;перекидываем в еах
leave ;выравниваем стек от локальных переменных
ret 4 ;выходим с выравниваем от аргументов функци (он один всего, посему 4, было бы два аргумента - было бы 8 итд)
end start
а вот пожалуйста все то же, только без ненужных локальных переменных

Код:
	.386
	.model flat,stdcall
	option casemap:none
.data
string	db "Is my function!",0
.code
start:
push offset string
call strlen
ret

strlen:
push ecx
cld
mov edi,[esp+8]
xor eax,eax
xor ecx,ecx
dec ecx
repnz scasb
not ecx
dec ecx
xchg eax,ecx
pop ecx
ret 4
end start
Нет, ну правда..

Последний раз редактировалось Stilet; 25.08.2010 в 16:05.
yuran666666 вне форума Ответить с цитированием
Старый 25.08.2010, 15:31   #5
VerhoLom
Пользователь
 
Регистрация: 25.08.2010
Сообщений: 12
По умолчанию

Или где-то так:

Код:
       call @1
       db "My long string",0
@1: call _strLen
       ret

_strLen:
push ebp
mov ebp,esp
mov esi,dword [ebp+8]
xor eax,eax
xor ecx,ecx
@i:
lodsb
dec al
js @ret
inc dword ecx
jmp @i
@ret:
xchg eax,ecx
mov esp,ebp
pop ebp
ret 0x04
А вообще странно, что компилятор так себя ведет...

Последний раз редактировалось Stilet; 25.08.2010 в 16:05.
VerhoLom вне форума Ответить с цитированием
Старый 26.08.2010, 21:19   #6
ZahAlex
Пользователь
 
Регистрация: 08.04.2009
Сообщений: 45
По умолчанию

Всем спaсибo (голосовать за репутацию не могу - не активен значок), вроде допёр, что надо делать...
И кстати (из моих личных изысканий) регистры EDI, ESI надо сохранять в каждой функции DLL, нето они(API) не будут вызываться VisualBasic'oм.
После изучения ассемблера стал мозг зависать...
ZahAlex вне форума Ответить с цитированием
Старый 27.08.2010, 00:35   #7
|{ot
Форумчанин
 
Аватар для |{ot
 
Регистрация: 09.03.2008
Сообщений: 127
По умолчанию

Не понятно, зачем так заморачиватся:

Цитата:
оформить функцию просто как метку
Можно все делать как обычно по-старинке:
Код:
_Proc1 PROC

...............

ret
_Proc1 ENDP
Только нельзя объявлять параметры процедуры:
Код:
_Proc1 PROC p1:DWORD,p2:DWORD

...............

ret 
_Proc1 ENDP
А делать все ручками..
Код:
push 1
push 2
call _Proc1

;Параметры у процедуры есть, только их не объявляем в процедуре, а сами обрабатываем 
_Proc1 PROC
	push esi
	push edi
	mov esi,[esp+12]
	mov edi,[esp+16];вот и получили параметры..
...............

ret
_Proc1 ENDP
Минус - нельзя через invoke вызывать, и конечно же прототип ф-ции без параметров записывать если надо..

Цитата:
Сообщение от VerhoLom Посмотреть сообщение
А вообще странно, что компилятор так себя ведет...
Ничего ни странно. Он как и полагается вставляет в процедуру 5-ти(или 3-х) байтовый пролог для доступа к стековым параметрам процедуры.

Цитата:
Как заставить MASM линковать только то, что я написал, без вышеуказанных входов и выходов CALLов.
Не совсем понятно зачем так делать??

Цитата:
И кстати (из моих личных изысканий) регистры EDI, ESI надо сохранять в каждой функции DLL, нето они(API) не будут вызываться VisualBasic'oм.
Вообще по соглашению stdcall все ф-ции не должны "портить" регистры esi edi ebp esp ebx. Кстате почти все API имеют такой же 5-ти байтовый пролог.
|{ot вне форума Ответить с цитированием
Старый 02.09.2010, 16:54   #8
VerhoLom
Пользователь
 
Регистрация: 25.08.2010
Сообщений: 12
Сообщение

Цитата:
Сообщение от ZahAlex Посмотреть сообщение
Всем спaсибo (голосовать за репутацию не могу - не активен значок), вроде допёр, что надо делать...
И кстати (из моих личных изысканий) регистры EDI, ESI надо сохранять в каждой функции DLL, нето они(API) не будут вызываться VisualBasic'oм.
VB абсолютно пофигу, сохраняете Вы эти регистры или нет. Тут главное, чтобы Вы правильно вернули ему стек, а он поддерживает только STDCALL конвенцию, а остальные - только ассемблерными вставками. Главное - удалите из стека все параметры и не трогайте адрес возврата. Можно пролог и не делать...

Для |{ot:
Я тут в книжке про руткиты прочитал, что начиная с WindowsXP SP2 майкрософт сделала во всех АПИ 5-байтовый пролог:

mov edi,edi
push ebp
mov ebp,esp


Хотя объяснения я так и не догнал: это надо для того, чтобы после установки обновлений виндовса не надо было перезагружать комп. Может я чего не знаю? Хотя само объяснение выглядит прикольно: "Стремясь удовлетворить (???) пожелания пользователей, фирма майрософт сделала пролог 5-байтным". Насколько я знаю (и это подтверждает ход истории), под пользователями мелкомягкие понимают людей типа секретуток (как сказал Крис Касперски, "они не отличают IP-адрес от пениса"). Это ж куда цивилизация двинулась, чтобы секретарь была в курсе про прологи в АПИ и пр... Не, так мы без работы будем...

Последний раз редактировалось VerhoLom; 02.09.2010 в 17:04.
VerhoLom вне форума Ответить с цитированием
Старый 02.09.2010, 21:45   #9
|{ot
Форумчанин
 
Аватар для |{ot
 
Регистрация: 09.03.2008
Сообщений: 127
По умолчанию

Цитата:
Сообщение от VerhoLom Посмотреть сообщение
сделала во всех АПИ 5-байтовый пролог
Я же и писал сверху
Цитата:
в процедуру 5-ти(или 3-х) байтовый пролог
Не во все АПИ конечно! Некоторые и без него..

Ну а какая глава в книге про руткиты была? Плохо читал...))

Цитата:
это надо для того, чтобы после установки обновлений виндовса не надо было перезагружать комп
Все верно. Когда устанавливаеш обновления, то грубо говоря некоторые системные функции (API и не только) "подвергаются изменению своего кода". Но тогда что бы обновления вступили в силу нужно перегрузить систему, дабы в программах использовались уже обновленные ф-ции из обновленных ДЛЛ. Вот они и делают после обновления и до перезагрузки спайсинг функций, код которых обновится после перезагрузки. получается вот так (к примеру):

User32.dll ->MessageBox proc ....
mov edi,edi
push ebp
mov ebp,esp
.......
ret
MessageBox endp
Пусть эта функция и обновляется. Тогда, к примеру, обновлением создается Updatedll.dll и подгружается во все процессы где есть User32.dll, а код User32.dll ->MessageBox меняется вот так:

User32.dll ->MessageBox proc ....
jmp Updatedll.dll ->MessageBox proc
....
ret
MessageBox endp

Получается при вызове MessageBox управление передастся в Updatedll.dll ->MessageBox где и есть новая версия функции.
А уже после перезагрузки функция в User32.dll ->MessageBox изменится на новую (наверное заменой файла)

Вот и получается, что для jmp Updatedll.dll ->MessageBox нужно 5 байт (1байт = опкод jmp + 4 байта на адрес), а это как раз размер пролога.
|{ot вне форума Ответить с цитированием
Старый 23.08.2012, 19:23   #10
djonatan98
Форумчанин
 
Регистрация: 15.04.2012
Сообщений: 103
По умолчанию

У меня крмпиоятор выдавал 125 ошибок, тогда иначе организовал код

Код:
.386
.model flat, stdcall
option casemap:none


includelib \masm32\lib\kernel32.lib

 		
СloseHandle    PROTO :DWORD    	
FindFirstFileA PROTO :DWORD,:DWORD 	
FindNextFileA  PROTO :DWORD,:DWORD  	
CreateFileA    PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD		
ReadFile       PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD		
GlobalAlloc    PROTO :DWORD,:DWORD   	
GetFileSize    PROTO :DWORD,:DWORD   		
SetFilePointer PROTO :DWORD,:DWORD,:DWORD,:DWORD		
WriteFile      PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD  		               
GlobalFree     PROTO :DWORD    		
VirtualProtect PROTO :DWORD,:DWORD,:DWORD,:DWORD	
ExitProcess    PROTO :DWORD		
GetProcAddress PROTO :DWORD,:DWORD	
LoadLibrary    PROTO :DWORD 	
SetCurrentDirectory PROTO :DWORD 	
			

pushz macro szText:VARARG
    local nexti
    call  nexti
    db    szText, 0
nexti:
endm


.data
delta_off
 
.data
    db 0
.code
    invoke ExitProcess, 0
start:
теперь выдает 107 но уже прогресс
djonatan98 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Механизм CALL Stilet Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 30.07.2010 10:06
Infra call center emilregis Общие вопросы Delphi 16 29.04.2009 11:26
Call of duty 4 Соколов Дмитрий Gamedev - cоздание игр: Unity, OpenGL, DirectX 1 03.04.2009 12:40
Only assignment, call . . . RIO Общие вопросы .NET 2 03.05.2008 16:55