Важная информация
Показано с 1 по 4 из 4

Тема: Почему у переменной именно такое смещение в стеке?

  1. #1 Почему у переменной именно такое смещение в стеке? 
    Новичок
    Регистрация
    21.12.2018
    Сообщений
    1
    Сказал(а) спасибо
    2
    Поблагодарили 0 раз(а) в 0 сообщениях
    Здравствуйте. У меня есть код. (написан с посторонней помощью, поэтому один момент остался непонятен)
    Assembler Code:
    1.  
    2. .386
    3. .model flat, stdcall
    4. option  casemap:none    
    5.  
    6. include ..\INCLUDE\windows.inc            
    7. ;include ..\INCLUDE\comctl32.inc
    8. ;include ..\INCLUDE\Fpu.inc
    9. ;include ..\INCLUDE\user32.inc
    10. include ..\INCLUDE\kernel32.inc                        
    11. ;includelib ..\LIB\comctl32.lib      
    12. ;includelib ..\LIB\Fpu.lib
    13. ;includelib ..\LIB\user32.lib
    14. includelib ..\LIB\kernel32.lib
    15.  
    16. ;прототипы без DWORD , т.к. они плохо отображаются
    17. ExitProcess proto
    18. GetStdHandle proto
    19. WriteConsoleA proto
    20. ReadConsoleA proto
    21.  
    22. .stack 256
    23. .data
    24. STD_INPUT_HANDLE equ -10      
    25. STD_OUTPUT_HANDLE equ -11
    26. Max_Bsize equ 27
    27. Zero_Code equ 30h      
    28.  
    29. stdout dd ?
    30. stdin dd ?
    31. cWritten dd ?
    32.  
    33. maxCount dd 8                                    ;СУТЬ ВОПРОСА ЗДЕСЬ
    34. base2 dd 2  
    35. i dd 0Ah    
    36. k dd 0    
    37. inData dq ? , 0dh, 0ah    
    38. resMas db Max_Bsize dup (30h)
    39. ;и т.д.

    Далее в процессе выполнения необходимо использовать переменную maxCount и она помещается в eax так:
    mov eax, [esp+4];
    Подскажите, откуда взялось именно такое смещение(+4)? Как переменные по умолчанию добавляются в стек?

    Дополнение(помещение переменной в стек):
    Assembler Code:
    1.  
    2. start:
    3.  
    4. invoke GetStdHandle, STD_OUTPUT_HANDLE
    5.     mov stdout, eax
    6. invoke GetStdHandle, STD_INPUT_HANDLE
    7.     mov stdin, eax  
    8.     invoke ReadConsoleA, stdin, ADDR inData, sizeof inData, ADDR cWritten, 0
    9.  
    10.     xor eax, eax
    11.     xor ebx, ebx
    12.     xor ecx, ecx
    13.     xor edx, edx
    14.  
    15.     mov ebx, OFFSET inData  
    16.     push maxCount                  ;вот она помещается              
    17.     call StrToInt    
    18. ; и т.д.
    Последний раз редактировалось Chronita; 21.12.2018 в 02:57.
    Ответить с цитированием  
     

  2. #2  
    Супер модератор Аватар для >Quiet Snow<
    Регистрация
    11.04.2011
    Адрес
    Планета земля
    Сообщений
    3,919
    Сказал(а) спасибо
    1,842
    Поблагодарили 980 раз(а) в 838 сообщениях
    Записей в блоге
    1
    Судя по всему это подпрограмма.(не видно кода где у вас эта строчка)

    Когда идёт следующий код(вызов процедуры)
    Assembler Code:
    1. Call MyProc


    то процессор делает что-то типа
    Assembler Code:
    1. Push eip + длина команды Call
    2. Jmp адрес процедуры


    т.е. на вершине стека мы имеем адрес возврата в место, находящееся сразу после Call MyProc,
    адрес возврата(указатель, т.е. pointer) у нас четыре байта для x86.

    Касаемо почему +4. Существует много соглашений передачи параметров через стек: СDECLARATION(CDECL), PASCAL, STDCALL(WinAPI)
    Они регламентируют в какой последовательности в стеке находятся параметры функции.
    В случае STDCALL аргументы функций передаются через стек, справа налево. Очистку стека производит вызываемая процедура.
    Справа налево - смотрим в прототип процедуры, как там стоят параметры. При вызове процедуры в стек сначала будут заPUSH-ены
    по очереди все параметры справа налево( т.е. с конца прототипа процедуры), а потом адрес возврата.

    Cтек работает на уменьшение esp. Push eax сделает следующее:

    Assembler Code:
    1. SUB esp, 4
    2. MOV ss:[esp], eax


    Pop - соотв. наоборот.

    Цитата Сообщение от Chronita Посмотреть сообщение
    mov eax, [esp+4]
    означает лишь то, что где-то в процедуре был подвинут esp и программист взял на себя перегрузку данных из входных параметров
    в регистры, потому что так удобнее(ты можешь подгрузить данные не забивая все регистры сразу, экономия регистров - очень важна,
    когда пишешь на асме).


    P.S: Проверяйте информацию, в деталях могу откровенно косячить, главное чтобы вы суть поняли.
    Последний раз редактировалось >Quiet Snow<; 21.12.2018 в 03:36.
    Обучение прикладному программированию(по skype), качественно, недорого, 18+, вопросы в личку.
    «Если вы ничего не сделаете, я уверяю вас, ничего и не произойдёт» © Жак Фреско
    Ограниченно модерирую.
    Ответить с цитированием  
     

  3. Пользователь сказал cпасибо:

    Chronita (21.12.2018)

  4. #3  
    Супер модератор Аватар для >Quiet Snow<
    Регистрация
    11.04.2011
    Адрес
    Планета земля
    Сообщений
    3,919
    Сказал(а) спасибо
    1,842
    Поблагодарили 980 раз(а) в 838 сообщениях
    Записей в блоге
    1
    например
    esp = 300
    300 - наобум взял и в этой ячейке лежит какое-то значение(предполагаем что нужное).

    Цитата Сообщение от Chronita Посмотреть сообщение
    push maxCount ;вот она помещается
    call StrToInt
    maxCount задекларирован как dd - 4 байта.
    esp двигается назад(минусуется) на 4 байта
    теперь он равен 296 и в эту ячейку помещается maxCount
    далее идёт CALL, не знаю как организована процедура, есть ли там ENTER \ LEAVE, допустим что нет.
    CALL сразу забивает значение возврата т.е. eip (в ячейку 292), допустим всё это дело NEAR и селектор не требуется.
    Тогда мы можем сразу написать mov eax, [esp+4] (292 + 4 = 296 это адрес maxCount в стеке) и в eax мы получим
    наш первый параметр процедуры(или функции) StrToInt. Судя по названию это всё таки функция.

    Но сохранены ли там регистры. Eax - разрушается, это надо учитывать.


    Вы можете просто откомпилировать вашу прогу, скачать Turbo Debugger под винду(вроде версия 5 и выше) и
    посмотреть пошагово через него что происходит. Так на словах долго объяснять.
    Последний раз редактировалось >Quiet Snow<; 21.12.2018 в 04:21.
    Обучение прикладному программированию(по skype), качественно, недорого, 18+, вопросы в личку.
    «Если вы ничего не сделаете, я уверяю вас, ничего и не произойдёт» © Жак Фреско
    Ограниченно модерирую.
    Ответить с цитированием  
     

  5. Пользователь сказал cпасибо:

    Chronita (21.12.2018)

  6. #4  
    Супер модератор Аватар для >Quiet Snow<
    Регистрация
    11.04.2011
    Адрес
    Планета земля
    Сообщений
    3,919
    Сказал(а) спасибо
    1,842
    Поблагодарили 980 раз(а) в 838 сообщениях
    Записей в блоге
    1
    Посмотрел в книге от Галисеева, он там просто делает Pushad \ Popad, вызывая свои функции через invoke
    и не парится.
    Сама конвенция не регламентирует какие регистры надо сохранять, из этого можно сделать вывод что сохранять
    нужно все используемые.
    STDCALL судя по англоязычной вики, задизайнен для использования внутри функции регистров ECX и EDX.
    EAX используется в качестве возвращаемого значения функций.

    Вот тут подробнее:
    https://www.codeproject.com/Articles...ns-Demystified

    Хотя по факту нифига не Demystified .

    В начале классическое:
    Assembler Code:
    1.   Push        ebp  
    2.   Mov         ebp, esp

    Чтобы можно было использовать стек дальше(например для сохр. регистров), а адресовать параметры через ebp.
    Разумеется это для ленивых или если внутри есть цикл с командами стека. Так то можно самому посчитать куда "уплывёт"
    esp и вытянуть оттуда нужный параметр.

    И в конце:
    Assembler Code:
    1.   Mov         esp, ebp
    2.   Pop         ebp  
    3.   Ret

    Ret компилятор преобразовывает в ret n, где n - кол-во байт, для выгрузки из стека.

    Вообще нормальную информацию хрен найдёшь, какие регистры разрушает(например те же WinAPI), что сохранять,
    что не сохранять, чтобы лишних действий не делать. Сам чёрт ногу сломает, это всё просто надо тестить.
    Времени этим заниматься не найду, уж извиняйте.
    Обучение прикладному программированию(по skype), качественно, недорого, 18+, вопросы в личку.
    «Если вы ничего не сделаете, я уверяю вас, ничего и не произойдёт» © Жак Фреско
    Ограниченно модерирую.
    Ответить с цитированием  
     

Информация о теме
Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Ввод строковой переменной
    от Liquid Hamster в разделе .NET
    Ответов: 3
    Последнее сообщение: 28.09.2018, 01:05
  2. В TCP-стеке Linux и FreeBSD выявлена уязвимость
    от Free Admin в разделе Операционные системы
    Ответов: 0
    Последнее сообщение: 10.08.2018, 10:36
  3. AJAX отправка переменной из JS в PHP
    от Natalia Chistyakova в разделе PHP
    Ответов: 2
    Последнее сообщение: 12.11.2016, 15:24
  4. Доказать, что платежи производились именно с одного компа.
    от Людмила Алфёрова в разделе Общие вопросы программирования
    Ответов: 14
    Последнее сообщение: 30.03.2016, 12:42
  5. Рекурсия и немного о стеке
    от stabud в разделе FreeBasic
    Ответов: 3
    Последнее сообщение: 10.01.2013, 10:36
Ваши права
  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •