Ответьте, пожалуйста, на следующие вопросы: 1. Локальные переменные храняться в стеке - это я знаю. А счетчик, который указывает на количество переменных он где храниться? 2. как подключить в программу на Си файл написанный на ассемблере(лучше объектный, но если нельзя, то пойдет и текстовый), не встраивая тело asm в сишную программу.
Доброе время суток, Alexander! 1. нет такого, или крайне компиляторно зависимо. 2. все объявляете extern и линковщику даете ваш obj файл. Ответ отправлен: 21.05.2004, 10:47 Отправитель: vitya Отвечает CrackLab
Приветствую Вас, Alexander! 1. Счетчика количества переменных нету. Просто в самом начале процедуры освобождается место в стеке, равное размеру используемых в процедуре локальных переменных. Например если у нас есть функция ReturnKvadrat(int x) { int y,z; y = x*x; return y; } То можно посчитать что в стеке в начале процедуры зарезирвируется 8 байт. 4 байта на y и 4 байта на z. Т.е. в дизассемблере начало процедуры будет выглядеть как push ebp mov ebp, esp add esp, -8 <--- сдвигаем стек на 8 байт для хранения 2х локальных переменных далее работа с ними будет будет через регистр ebp. Например y = 2 внутри процедуры внутри дизассемблера выглядело бы как mov dword ptr [ebp-4], 2 а z = 3 как mov dword ptr [ebp-8], 3 Ну это не так важно, самое главное что счетчика нет =) 2. Тут надо смотреть на каком С (DOS C++, C++ Builder,
Visual C++) вы работаете и каким асм компилятором (MASM, TASM) вы получаете объектный файл или статическую библиотеку. Уточните эти данные и я постараюсь помочь. Ответ отправлен: 20.05.2004, 23:25 Отправитель: CrackLab Отвечает bocha
1)нигде Если у функции фиксированое число параметров то зачем ей счетчик параметров? Если у функции переменное чило параметров, то в каком-нибуть из фиксированых аргументов, или она определяет конец параметров по какому-нибуть признаку. например определим функцию fun1(char* a,...), которая принимает список указателей на строки, и условием конца определим нулевой указатель, тогда при вызове функсии , в ней мы выбираем параметры из стека по одному и смотрим, не достигли-ли мы конца списка аргументов примерно так: ... lea ecx, dword ptr[ebp+8];в ecx-адрес первого аргумента Loop1: mov eax, dword ptr[ecx] test eax, eax jz End_loop1 ... add ecx, 4 jmp Loop1 End_loop1: ... или так void fun1(char *a,...) { char **c =&a; while(*c)**c++ = 'a'; } тогда void main() { char a,s,d,f,g,h; fun1(&a,&s,&d,&f,&g,&h,0);//не
забыть поставить 0 } от параметров в данном случае стек очищает функция main() как это реализуется можно посмотреть, попросив компилятор сгенерировать файл листинга Для VC6:Project -> setings-> c/c++->category:listing file -> listing file type:assembly with source code Извините, невнимательно прочитал вопрос, речь идет не об аргументах, а о локальных переменных, обычно в начале функуии выполняются такие действия: push ebp mov ebp, esp теперь для выделения памяти под локальные пеменные sub esp, переменная_1_количество_байт_кратное_4 sub esp,переменная_2_количество_байт_кратное_4 можно и одной командой, главное, чтобы esp увеличивался на чило кратное 4. обращение к переменным mov ax, word ptr[ebp-смещение_переменной] перед выходом из функции mov esp, ebp pop ebp стек востановлен, так что счетчик не требуется 2)Предполагаем: Windows,
VC6, MASM32 1.Копируем ML.exe и ML.err в msvs_dirvc98in 2.Копируем masm32include -> vc98include //можно не все 2а.Сносим masm32 ;) 3.создаем проект, если уже есть, то Project->add to project-> files свой асм файл 4.FileView -> Выделяем файл пкм ->Setings->All configuration 5.Закладка Custom builds на нее в поле commands копируем командную строку: ml /c /coff /I$(TargetDir)include /Fo$(ProjDir)$(OutDir)$(InputName).obj $(InputName).asm для конфигурации debug после /coff через пробел добавить /Zi, чтобы пользоваться возможностями встроенного отладчика. в поле Outputs: $(OutDir)$(InputName).obj Теперь можно писать программы и на с, и на ассемблере, и вперемешку 6.жмем Ok, (Ctrl)F5(F7)или кнопку на панели инструментов, смотрим сообщения об ошибках 7.Если же нужно поключить один только об'ектный файл, смотри п.3, вместо asm-obj и все.Но отлаживать разные
модули без возможности ставить брикпоинты где нужно, в т.ч. и в нужной строке asm-файла, а так же править код наместе...Конечно можно воспользоваться int 3, но тогда asm нужно будет постоянно перекомпилировать,невозможно смотреть значения переменных по именам, да и переключатся постоянно из одной среды в другую..? ЗЫ: $(_)-встроеные в VC макросы для командной строки(две кнопочки в самом низу окошка) ЗЫЗЫ:если ассемблер и компилятор С от разных производителей , то подключить об'ектный файл не получится.
Ответ отправлен: 21.05.2004, 11:09 Отправитель: bocha Отвечает barsik
Добрый день, Alexander! проверь регистр _SP
Ответ отправлен: 21.05.2004, 11:46 Отправитель: barsik Отвечает Sedric
Доброе время суток, Alexander! 1.Нет такого счетчика.Есть регистр SP(Stack Pointer), который указывает на адрес верхушки стека. В Досе это была песня:изменять его содержимое как угодно, но Windows положила на это свою волосатую лапу! 2.Для этого достаточно прикрутить к своей проге этот объектный, а уж линкер разберется, что куда.А текстовый файл не получится Ответ отправлен: 21.05.2004, 13:46 Отправитель: Sedric Отвечает Fess
Здравствуйте, Alexander! 1) Скажу честно - точно не знаю. Но если логически поразмыслить... В С++ переменные не содержат внутри себя каких-либо дескрипторов. Также дескрипторы, насколько я знаю, не размещены в отдельных словах памяти, как в Lisp. Но при этом компилятору необходимо поддерживать области видимости. Самое очевидное, простое и, как часто бывает, эффективное решение - использовать разные стеки для разных областей видимости. Либо (второе решение) использовать какую-нибудь глобальную таблицу, типа vtbl для виртуальных функций. Но тогда возникает несколько проблем: а) куда эту таблицу разместить (та же проблема существует и для vtbl), что порождает несовместимость, а несовместимость на уровне переменных это крах... б) как разместить указатель на эту таблицу. В общем первое решение намного выгоднее и, скорее всего, так и есть. 2) Между прочим
Ассемблер поддерживает СОМ. Но не объяснять же принципы этого в рассылке... Лучше почитай статью "СОМ в Ассемблере" Bill T. пер. Aquila, 2 части. Есть на wasm.ru, может видел. Adios!
Ответ отправлен: 21.05.2004, 17:28 Отправитель: Fess Отвечает www
Здравствуйте, Alexander! Вопросы скорее по ассемблеру чем по С! 1. Нафига этот счетчик хранить. ИМХО главное стек корректно очистить. 2. Включаешь в проект этот (объектный) файл и компилируешь. Только этот файл должен быть создан под ту же платформу и лучше компилятором того же производителя что и программа на C. Если хочешь из командной строки см. опции линкера соответствующего компилятора.
Ответ отправлен: 21.05.2004, 20:29 Отправитель: www
Вопрос № 1621
ПривеТ!! Покажите пример где используется winapi ReadProcessMemory/WriteProcessMemory. Спасибо.
Здравствуйте, qh! Здесь не совсем С++, но я думаю разберетесь: http://www.thecodeproject.com/csharp/minememoryreader.asp?print=true Ответ отправлен: 21.05.2004, 10:43 Отправитель: vitya Отвечает CrackLab
Добрый день, qh! Пример с комментариями в приложении.
Приложение: Ответ отправлен: 20.05.2004, 23:08 Отправитель: CrackLab Отвечает bocha
Добрый день, qh! Выделив память, мы должны каким-то образом скопировать строку из локального адресного пространства в удаленное. Для этого в Windows есть две функции: BOOL ReadProcessMemory( HANDLE hProcess, PVOID pvAddressRemote, PVOID pvBufferLocal, DWORD dwSize, PDWORD pdwNumBytesRead); BOOL WriteProcessMemory( HANDLE hProcess, PVOID pvAddressRemote, PVOTD pvBufferLocal, DWOHD dwSize, PDWORD pdwNumBytesWritten); Параметр hProcess идентифицирует удаленный процесс, pvAddressRemote и pvBufferLocal определяют адреса в адресных пространствах удаленного и локального процесса, a dwSize — число передаваемых байтов. По адресу, на который указывает параметр pdwNumBytesRead или pdwNumBytesWritten, возвращается число фактически считанных или записанных байтов (с)Дж.Рихтер Т.е. делают они то, что и должны исходя из названия - читают и пишут память
в другом процессе. Необходимо только получить hProcess, и pvAddressRemote, о том как это сделать читай там же.
Ответ отправлен: 22.05.2004, 04:41 Отправитель: bocha
Вопрос № 1622
Здравствуйте, эксперты! Почему то не работает код в C++ Borland 5.02. Пишет Expression syntax и указывает на место, где я использую макрос BIOS_DATA. Может у меня среда разработки не правильно настроена (в этой среде пишу впервые). Пишу программу для DOS в Windows 98 SE.
Добрый день, Эдуард! Все нормально компилируется и собирается, и даже выполняется. Может быть у Вас в настройках проекта стоит Win32 консоль или что-нибуть в этом роде? Ответ отправлен: 21.05.2004, 18:30 Отправитель: bocha
Вопрос № 1623
Привет!! Еще один вопрос по поводу памяти. Как определить сколько байт программа занимает в памяти?
Доброе время суток, qh! Этот размер сравним с размером на диске, если это PE-файл. Но при загрузке файла в память размер его изменяется. А вообще-то всем процессам дают по четыре гектара на NT-ях
Ответ отправлен: 23.05.2004, 13:36 Отправитель: Sedric Отвечает barsik
Здравствуйте, qh! V windows 98 :start->run naberi mem /c/p V win XP start->cmd: naberi mem Ответ отправлен: 22.05.2004, 16:44 Отправитель: barsik Отвечает CrackLab
Приветствую Вас, qh! Привет, тебе нужно вкратце почитать про строение PE-заголовка файла. Может быть есть другой способ, но мне на ум пришел только вот какой: Значит размер тела программы равен размеру PE-заголовка (или размеру программы до первой секции) + сумма Virtual Size всех секций. Естественно понятие сколько байт программа занимает в памяти растяжимое, ведь она использует еще стек + кучу для хранения всего что нужно для работы и т.д. Но если ты имеешь в виду только то, что в исходном состоянии находится в .exe файле то я написал способ. Значит ищешь справочник по PE файлам, там смотришь как найти Virtual Size всех секций. Складываешь их + прибавляешь размер PE заголовка (или правильнее будет размер памяти начиная с адреса по которому программа загружена в память (ImageBase) до адреса по которому в памяти начинается первая секция). Попробуй разобраться
самостоятельно и если что не понятно будет - спрашивай. Ответ отправлен: 21.05.2004, 14:52 Отправитель: CrackLab
Вопрос № 1624
Здравствуйте Уважаемые Эксперты! Подскажите плиз, какая функция есть для Винды типа Exec для Дос. Прочитал в описаниях библиот.функций BC++ что exec только для DOSа, а в нете вроде и для Win. Зарание спасибо!
Доброе время суток, vlad! Есть куча функций WinAPI для этого. Навскидку: ShellExecute,CreateProcess,CreateProcessEx and so on. Читайте справочник по WinAPI Ответ отправлен: 23.05.2004, 13:36 Отправитель: Sedric Отвечает Gibbel
Добрый день, vlad! все гениальное, как всегда, просто... Для Windows используется функция WinExec(). UINT WinExec( LPCSTR lpCmdLine, UINT uCmdShow ); Так же есть функции CreateProcess(), CreateProcessAsUser(), ShellExecute(), ShellExecuteEx() и множество других. Ответ отправлен: 21.05.2004, 15:38 Отправитель: Gibbel Отвечает CrackLab
Приветствую Вас, vlad! Можно использовать одну из 4х функций: WinExec ShellExecute CreateProcess spawn Прочтите документацию по каждой из них и выберите ту, которую будете использовать. Однако рекомендуется использовать функцию CreateProcess либо ShellExecute. Ответ отправлен: 21.05.2004, 15:59 Отправитель: CrackLab Отвечает bcc
Доброе время суток, vlad! WinExec Ответ отправлен: 21.05.2004, 17:08 Отправитель: bcc Отвечает vitya
Добрый день, vlad! ShellExecute(Ex), CreateProcess, WinExec. Ответ отправлен: 21.05.2004, 17:08 Отправитель: vitya Отвечает bocha
Добрый день, vlad! ShellExecute-устаревшая CreateProcess-используй ее Ответ отправлен: 22.05.2004, 02:51 Отправитель: bocha
Форма отправки вопроса
Внимание!
Мы рекомендуем открывать рассылку в программе Internet Explorer 5.0+
или отправлять вопросы с сайта по адресу:
http://rusfaq.ru/cgi-bin/Message.cgi.