Страница: 1 | 2 |
Вопрос: Почему обнуляется?
Добавлено: 22.09.04 03:33
Автор вопроса: CyRax | Web-сайт:
Пишу я значит код вызова MessageBox на своём ассемблере.
Адрес MessageBoxA хранится в EBP-16.
Если так:
PUSH 0& 'MB_OK
PUSH [ebp-20] 'Title
PUSH [ebp-24] 'Caption
PUSH 0& 'hWnd
CALL [EBP-16] 'Addressof MessageBoxA
,то выбивает. Проверил и оказалось что после PUSH значение в EBP-16 обнуляется.
А так работает:
MOV EAX,[EBP-16]
PUSH 0&
PUSH [ebp-20]
PUSH [ebp-24]
PUSH 0&
CALL EAX
Может так не должно быть и мой ассемблер сглючил? Я блин 2 часа не мог причину найти.
Ответы
Всего ответов: 29
Номер ответа: 1
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #1
Добавлено: 22.09.04 04:07
Вот опкоды с WDasm
Это для CALL [EBP-16]
:0000004E 6800000000 push 00000000
:00000053 FF75EC push [ebp-14]
:00000056 FF75E8 push [ebp-18]
:00000059 6800000000 push 00000000
:0000005E FF55F0 call [ebp-10]
Это для MOV EAX,[EBP-16]
:0000004B 8B45F0 mov eax, dword ptr [ebp-10]
:0000004E 6800000000 push 00000000
:00000053 FF75EC push [ebp-14]
:00000056 FF75E8 push [ebp-18]
:00000059 6800000000 push 00000000
:0000005E FFD0 call eax
Номер ответа: 2
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #2
Добавлено: 22.09.04 04:32
Call dword ptr [EBP-16]
хотя я не понял, почему у тебя в минус идёт?
у меня [ebp+8]
Номер ответа: 3
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #3
Добавлено: 22.09.04 04:41
Полный код процедуры такой:
Message proc ProcAddr:DWORD, hWin:dword,lpTitle:DWORD,lpMess:DWORD
push 0
push dword ptr [ebp+14h]
push dword ptr [ebp+10h]
push dword ptr [ebp+0Ch]
Call dword ptr [ebp+8]
ret
Message endp
Номер ответа: 4
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #4
Добавлено: 22.09.04 04:47
Вот так тоже работает:
mov eax,ProcAddr
push 0
push dword ptr [ebp+14h]
push dword ptr [ebp+10h]
push dword ptr [ebp+0Ch]
Call eax
Номер ответа: 5
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #5
Добавлено: 22.09.04 04:53
В минус, потому что это локальная переменная.
[EBP+imm] - это параметры.
[EBP-imm] - это уже локальные переменные.
Отрицательных чисел конечно же в АСМ не существует. Но ассемблеры (и компиляторы кстати тоже) условно принимают большую половину числа за отрицательный диапазон.
К примеру [EBP-1] - это [EBP+FF], [EBP-4] - это [EBP+FC] и т.д.
PS: Я просто поддержку макросов сделал у себя. Вот тестирую тперь. Хочу потом какой нибудь аналог Invoke приделать.
Номер ответа: 6
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #6
Добавлено: 22.09.04 05:04
Invoke наверное всё же прийдётся сделать. Я думал макросы упростят вызов API, но у меня они его только усложнили. Можешь не разбираться в коде. Просто глянь сколько его только на вызов окна сообщения:
#API
CONST EntryPoint EQU [EBP+8]
CONST LoadLibrary EQU [EBP+&HC]
CONST GetProcAddress EQU [EBP+&H10]
CONST Parameters EQU [EBP+&H14]
#MACRO ASCZ Src,reg32
MOV reg32,[EBP+8]
ADD reg32,Src
#END MACRO
#MACRO LIB ASCZ,reg32
PUSH ASCZ
CALL [EBP+&HC]
#END MACRO
#MACRO PROC LIB,ASCZ,reg32
PUSH ASCZ
PUSH LIB
CALL [EBP+&H10]
#END MACRO
CONST str_User32 EQU EBP-4
CONST hUser32 EQU EBP-8
CONST str_MessageBox EQU EBP-12
CONST hMessageBox EQU EBP-16
' USER32.DLL hModule
ASCZ USER32,EDX
MOV [str_User32],EDX
LIB [str_User32],EAX
MOV [hUser32],EAX
'MessageBox proc addr
ASCZ MsgBox,EDX
MOV [str_MessageBox],EDX
PROC [hUser32],[str_MessageBox],EAX
MOV [hMessageBox],EAX
CONST Title1 EQU ebp-20
CONST Caption1 EQU ebp-24
ASCZ MsgTitle,EDX
MOV [Title1],EDX
ASCZ Caption,EDX
MOV [Caption1],EDX
MOV EAX,[hMessageBox]
PUSH 0&
PUSH [Title1]
PUSH [Caption1]
PUSH 0&
CALL EAX
END &H10
' Строки вынесем в конец чтобы не путать дизассемблеры
USER32 DB "USER32.DLL",0
MsgBox DB "MessageBoxA",0
MsgTitle DB "Title",0
Caption DB "Caption",0
Номер ответа: 7
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #7
Добавлено: 22.09.04 05:17
Так ты разобрался, Call dword ptr [] работает?
А хороший макрос - это вещь.
Номер ответа: 8
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #8
Добавлено: 22.09.04 14:30
Там и так DWORD PTR. Не веришь смотри опкоды.
FF/55/8 CALL [EBP+8]
FF/55/8 CALL DWORD PTR [EBP+8]
Это ж не MASM.
У меня стоит автокоррекция. Например такой вид записи допустим:
MOV ECX,[EBP+8]
MOV CX,[EBP+8]
MOV CL,[EBP+8]
это тоже что и
MOV ECX, DWORD PTR [EBP+8]
MOV CX, WORD PTR [EBP+8]
MOV CL, BYTE PTR [EBP+8]
И это вполне логично с точки зрения процессора. Потому как различные операнды недопустимы. Например опкода MOV ECX, BYTE PTR [EBP+8] не существует. Или MOV CL, DWORD PTR [EBP+8].
А по поводу CALL, который кстати BYTE PTR не поддерживает, то там по умолчанию DWORD PTR. А знаешь почему? Да потому что адресация 32-битная. Тут кроме DWORD PTR ничего нельзя ставить. Короче - без вариантов. Что такое WORD PTR я думаю ты уже понял.
Короче все эти приставки (PTR) придумала Микрософт хрен знает с какого бодуна. Потому как длина операнда-памяти всегда равна длине второго операнда. Будь то регистр или число.
Такое добро нынче днём с огнём не сыскать
Номер ответа: 9
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #9
Добавлено: 22.09.04 16:19
По идее, опкоды CALL [EBP+8] и CALL DWORD PTR [EBP+8] одинаковые, вот только на первую команду компилер ml.exe ругается, на вторую нет. А приставки ...PTR - Возможно, это сделано для того, чтобы человек придерживался правильного стиля при написании. Что до некоторой степени предохраняет его от ошибок, которые могут возникнуть например с movzx eax,byte ptr[..]. В этом случае автоматом подставлять не получается, неизвестно, что будет: можно и byte ptr, можно и word ptr
Программа с CALL [EBP+8] работает, но только через отладчик OllyDbg. Почему - непонятно.
Номер ответа: 10
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #10
Добавлено: 22.09.04 22:52
По моему она и MOVSX. Всё больше таких нет, ориентированных именно на разные размеры операндов. Кстати в моём ассемблере нет операнда по умолчанию для этих операций. И без добавления приставки PTR он информирует об ошибочных операндах.
В смысле? Тебе удалось скомпилировать через MASM без добавления приставки PTR?
Номер ответа: 11
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #11
Добавлено: 22.09.04 23:18
Удалось. Правда RadASM при попытке компиляции и одновременно запуска из IDE ругнулся на эту строку и файл не запустился, но потом я ему указал запустить через дебаггер (в RadASM есть такая фича) и он вызвал OllyDbg c параметром "имя моей проги", и уже из Olly я запустил программу. Она исправно выдала MessageBox.
Номер ответа: 12
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #12
Добавлено: 22.09.04 23:38
По моему решение моей проблемы нашлось. Я не выделил память для локальной переменной.
Это делается так: SUB ESP,Count*4
Глянь
http://www.masmforum.com/viewtopic.php?t=4151
Только я никак не могу взять в толк что делает эта операция SUB ESP,imm. Не подскажешь?
Номер ответа: 13
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #13
Добавлено: 23.09.04 01:40
В стеке:
Var1(dword) --> [esp-10]
sub esp,4
Var1(dword) --> [esp-0С]
Переменная где была в памяти, там и осталась (её адрес прежний), но за счёт sub esp ты выделил под стек ещё 4 байта, а так как esp всегда указывает на вершину, то адрес твоей переменной по отношению к вершине сместился на 4 байта. И также сама вершина в абсолютном адресном пространстве сместилась на 4. К примеру: адрес в esp был 100000h, адрес Var1 был FFFF0, ты сместил esp на 4 байта вниз, в esp теперь содержится FFFFC (новый адрес вершины), и адрес Var1 относительно вершины (esp) теперь FFFFC-FFFF0=0С. Как я понимаю, sub esp,4 должен увеличить пространство под стек на 4 байта, и в этом дополнительном 4-байтном куске ты можешь разместить свою новую переменную, иначе эта инструкция нахрен не нужна. Имхо.
Ты мне вот такой прикол объясни: есть dll. Она работала, всё нормально. Потом внутри dll я исправил кое-что, откомпилил, слинковал, получил файл .dll и заменил им старый, называется также, положил как в системную папку, так и в папку с программой. И программа перестала его находить, хотя вот он, есть, и в системной папке тоже есть. А прога (и VB6 IDE) пишут, что не могут его найти. Они что ослепли на оба глаза сразу, или я сбесился? До этого переделывал её раз 20 наверное, проблем не было. А тут не видят они dll и всё. Перезагружался - не помогло
Номер ответа: 14
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #14
Добавлено: 23.09.04 01:48
А насчёт ошибки - я так понимаю, ты залез в адресное пространство, не выделенное для тебя, поэтому программу выбивало. И может обнуляло (вернее, не давало записать в область, где ты хотел сохранить адрес ф-ции) по той же причине.
Номер ответа: 15
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #15
Добавлено: 23.09.04 02:25
Нет, выбивало потому что обнуляло. В результате вместо вызова адреса MessageBoxA, вызывался 0. Да и в GPF'е он показывал EIP=0. За розъяснение спасибо. Общую картину понял, а вот в частности похоже там несколько другое. Ещё помедитирую и скажу что.
Да, ты заметил что в MASM EIP как операнд вообще не фигурирует? Да и опкодов я к нему не нашёл. Не знаешь как найти текущий адрес?
По поводу библы. По моему у меня тоже такое было. Это вроде твоя ошибка. Пришли пример я гляну.