Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.141.198.146] |
|
Сообщ.
#1
,
|
|
|
Подсмотрел код процедуры в Delphi:
procedure br; var p: pointer; begin HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, 24); end; Project12.dpr.16: begin 0000000000536660 55 push rbp 0000000000536661 4883EC30 sub rsp,$30 0000000000536665 488BEC mov rbp,rsp Project12.dpr.17: HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, 24); 0000000000536668 E8F348EEFF call GetProcessHeap 000000000053666D 4889C1 mov rcx,rax 0000000000536670 C7C208000000 mov edx,$00000008 0000000000536676 41C7C018000000 mov r8d,$00000018 000000000053667D E8AE49EEFF call HeapAlloc Project12.dpr.18: end; 0000000000536682 488D6530 lea rsp,[rbp+$30] 0000000000536686 5D pop rbp 0000000000536687 C3 ret теперь хочу сделать тоже самое в masm include c:\masm32\include64\masm64rt.inc NOSTACKFRAME .code my_test proc LOCAL p : QWORD push rbp sub rsp, 30h mov rbp, rsp call GetProcessHeap mov rcx, rax mov edx, HEAP_ZERO_MEMORY mov r8d, 24 call HeapAlloc lea rsp, [rbp + 30h] pop rbp ret my_test endp main proc push rbp sub rsp, 50h mov rbp, rsp call my_test ret main endp end После вызова HeapAlloc в переменную LOCAL p : QWORD попадает мусор. Много читал тем по стеку в win64, но видимо до сих пор что-то не понима. В Delphi может это вообще не процедуры а метки. Пытался и код выровнять в masm. Может это Delphi дизассемблер что-то неправильно показывает? Добавлено Это резерв для функций которые будут вызыватся в теле основной функции? То есть переменные в masm надо размещать после 32 байт? Добавлено То есть sub rsp, 30h это под одну локальную переменную + 32 для все вызовов что будут внутри. Плюс иногда возможно нужно выравнивание до 16 |
Сообщ.
#2
,
|
|
|
Студия сгенерировала больше места, не считая возврат результата.
LPVOID my_alloc() { 000000013F311A50 push rbp 000000013F311A52 push rdi 000000013F311A53 sub rsp,108h 000000013F311A5A lea rbp,[rsp+20h] 000000013F311A5F mov rdi,rsp 000000013F311A62 mov ecx,42h 000000013F311A67 mov eax,0CCCCCCCCh 000000013F311A6C rep stos dword ptr [rdi] LPVOID i; return HeapAlloc(GetProcessHeap(), 8, 24); 000000013F311A6E call qword ptr [__imp_GetProcessHeap (013F320000h)] 000000013F311A74 mov r8d,18h LPVOID i; return HeapAlloc(GetProcessHeap(), 8, 24); 000000013F311A7A mov edx,8 000000013F311A7F mov rcx,rax 000000013F311A82 call qword ptr [__imp_HeapAlloc (013F320030h)] } 000000013F311A88 lea rsp,[rbp+0E8h] 000000013F311A8F pop rdi 000000013F311A90 pop rbp 000000013F311A91 ret Добавлено Теперь надо понять как грамотно записывать в masm, чтобы был отступ. Не заводить же переменные пустышки для этого. Добавлено Плюс чтобы стеку программы дали памяти под все переменные в ней. Добавлено Это задаётся как-то так ? $pdata$my_test DD imagerel my_test DD imagerel my_test+48 DD imagerel $unwind$my_test |
Сообщ.
#3
,
|
|
|
Так правильно?
include c:\masm32\include64\masm64rt.inc NOSTACKFRAME .code my_test proc LOCAL p : QWORD push rbp mov rbp, rsp sub rsp, 32 + 8 + 8 call GetProcessHeap mov rcx, rax mov edx, HEAP_ZERO_MEMORY mov r8d, 24 call HeapAlloc add rsp, 32 + 8 + 8 pop rbp ret my_test endp main proc push rbp sub rsp, 50h mov rbp, rsp call my_test ret main endp end Добавлено поправил на add rsp, 32 + 8 + 8 перед выходом |
Сообщ.
#4
,
|
|
|
Блин, ну вот нету у меня под рукой masmового SDK64.
kin01, я сильно подозреваю, что дельфийный HeapAlloc() – это совсем не WinAPIховый, а только лишь некий thunk к нему. Посмотри в отладчике дальше, внутрь HeapAlloc(). Почти уверен, в kernel32 ты попадёшь не сразу. |
Сообщ.
#5
,
|
|
|
HeapAlloc в Delphi без обёртки.
А работа с динамической памятью там вообще идёт без него. Тут вообще проблема в другом. kin01, с чего вы решили, что локальная переменная p затирается? Если обращаетесь к p через masm64 (вроде mov rax,p), тогда логично, т.к. в первом коде у вас фрейм сделан по странной манере Delphi, а не как положено. Т.е. сначала уменьшается ESP, а затем делается mov ebp,esp. Надо наоборот. В общем-то, как в последнем вашем коде (в процедуре my_test, а в main осталось по-старому). Почему положено именно так (почему в Delphi сделано странно)? Потому есть есть инструкции enter и leave специально предназначенные для создания фрейма, и они работают как раз таким образом. Так что, в конце процедуры (перед ret) можно просто поставить leave безо всяких add rsp,... + pop rbp. Кстати, почему в main нет эпилога? И ret в конце я бы заменил на invoke ExitProcess, 0 всё-таки (т.к. если вы напишете такую прогу на fasm, там ret выкинет вас в никуда). Но тогда эпилог не нужен (из ExitProcess всё равно не будет возврата). include c:\masm32\include64\masm64rt.inc NOSTACKFRAME .code my_test proc LOCAL p : QWORD push rbp mov rbp, rsp sub rsp, 32+8+8 ; эти 3 инструкции можно заменить на один enter 48,0 mov rcx,1234567890ABCDEFh mov p,rcx ; test call GetProcessHeap mov rcx, rax mov edx, HEAP_ZERO_MEMORY mov r8d, 24 call HeapAlloc mov rcx,p ; test leave ret my_test endp main proc push rbp mov rbp, rsp sub rsp, 50h ; эти 3 инструкции тоже можно заменить на enter 50h,0 call my_test leave ; хотя, здесь это можно убрать, всё равно вызываем ExitProcess invoke ExitProcess,0 main endp end |
Сообщ.
#6
,
|
|
|
Jin X, к переменной обращения вообще нет. На самом деле значение этой переменной изменяется уже после вызова GetProcessHeap. Но это всё действительно из-за того что Delphi делает по странному кадр фрейма, а именно размещение локальных переменных.
|