несколько вопросов о стeке

Тема в разделе "WASM.BEGINNERS", создана пользователем RuAsm, 27 мар 2007.

  1. RuAsm

    RuAsm Виктор

    Публикаций:
    0
    Здраствуйте!
    1. на 32 битном процессоре, в стек можно положить только 32 битное знаечение? строку например из 10 байт никак не положить?
    2. и для чего нужен регистр ebp?

    ответьте пожалуйста на эти вопросы
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Это ещё почему. Стек - это обыкновенная память.
    Код (Text):
    1. mov eax, esp
    2. mov byte ptr [eax], 'a'
    EBP - регистр - указатель базы, для адресации локальных переменных, но конечно не обязательно.
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    команда PUSH по дефолту кладет 32 бита (это зависит от разрядности кода).
    С префиксом 66 может положить и слово. Байт она не кладет никогда.
    Другой вопрос - положить чтото в стек напрямую через ESP.

    sub esp, 1 ; заталкиваем
    mov byte [esp], 4

    add esp, 1 ; выталкиваем
     
  4. l_inc

    l_inc New Member

    Публикаций:
    0
    Присоединяюсь к вопросу о ebp. Никогда не понимал, зачем он нужен. Слова "указатель базы кадра стека" ни о чем не говорят. Точнее говорят, но как указатель может использоваться тот же eax, например. Чем ebp лучше чем еах? В большинстве подпрограмм, например, ebp используется в качестве копии esp:
    Код (Text):
    1. push ebp
    2. mov ebp, esp
    3. ....
    4. mov ecx, [ebp+6]; (доступ к аргументу)
    5. ....
    6. mov esp, ebp
    7. pop ebp
    Чем следующий код хуже?
    Код (Text):
    1. push eax
    2. mov eax, esp
    3. ....
    4. mov ecx, [eax+6]; (доступ к аргументу)
    5. ....
    6. mov esp, eax
    7. pop eax
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    l_inc
    Ничем. Просто у регистров есть свои имена =) ecx - например счетчик. Просто как правило стараются использовать одни регистры для одинаковых целей.
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    1) когда внутри функции ты сделаешь несколько push, у тебя esp изменится. Как тогда аргументы достать? В ebp запоминают esp при входе в функцию. Чтобы из любой точки можно было достать аргументы:
    Код (Text):
    1. push ebp  ; старый ebp
    2. mov ebp, esp  ; сохраняем esp в ebp
    3. push 1
    4. push 2
    5. push 3
    6. ; все равно мы теперь сможем достать аргументы через ebp, а через esp уже не сможем.
    2) Чем хуже eax? Ничем. Просто в процессоре i8086 косвенная адресация была доступна только через определенные регистры. Это потом начиная с 386 можно адресовать через любой регистр, в том числе и eax.
    А в 8086 адресация была фиксированная. Самым удобным был регистр BP, который изначально был зарезервирован для этой цели - доступ к стеку. BP = Base Pointer.
    Начиная с 386 все 16битные регистры расширились до 32битных и получили префикс E. Регистр BP стал EBP - Extended Base Pointer. Назначение осталось тем же.
    Просто договорились использовать именно его для этих целей. Хотя это не обязательно. В нем можно хранить что угодно
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    l_inc
    Да ничем, просто eax, как правило используется для других операций, а ebp - только как указатель на стек.
    Ведь не сможешь же использовать div без eax. А в твоём коде его надо будет куда-то сохранять. И вообще читайте про назначение регистров. Какие в каких операция целесообразнее использовать.
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Другая причина, как я сказал, это то, что в 8086 нельзя адресовать через ax. Система косвенной адресации была очень жесткой
    Насколько я помню, в качестве базовых регистров допускались только BP, BX, SI, DI.

    Нашел схему адресации в 8086/80286:

    [ BX/BP + SI/DI + IMM16 ]
     
  9. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Добавлю еще, что при использовании ebp сегментным регистром по-умолчанию будет ss, т.е. сегмент стека.

    Интересно, а сама идея стековых кадров пришла еще во времена 16 бит? Я так понимаю, основная причина их появления -- невозможность адресоваться по sp...
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    а когда еще то =) Стековые кадры под досом тоже были :)
    Основная причина скорее всего другая. Возможность простого доступа к аргументам текущей и вышестоящих функций независимо от SP.
     
  11. l_inc

    l_inc New Member

    Публикаций:
    0
    Booster
    Какие регистры целесообразно использовать, ИМХО, зависит только от логики работы программы. И если мне не нужно использовать операции с фиксированным аргументом (или результатом работы) в eax (в принципе, я его только для примера привел; не будем использовать цепочечные команды, будем хранить указатель кадра в esi), то почему бы его не использовать для этих целей; конечно приходилось бы больше жаться, но в программках на асме жаться всегда приходится, а лишний регистр в процессоре, ИМХО, - роскошь.
    To all
    А вообще, спасибо. А то я думал, что только мне bp/ebp лишним кажется. Тем более, как оказывается, к стеку он (в плане архитектуры ЦП) никакого отношения, кроме названия, не имеет (Mika0x65, спасибо, Ваш аргумент по поводу сегментного регистра по умолчанию учел).
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    На самом деле в винде сегментный регистр значения не имеет, у CS, DS, ES, SS стоит одинаковая база и равная 0.
    Таким образом виртуальный адрес во всех сегментах совпадает с линейным.
    Один FS стоит особняком.
    Но в том же досе это не так =) Так что замечание, безусловно, полезное.

    Ну не скажи..
    Все же, ИМХО, стоит придерживаться общепринятых принципов. Конечно, никто не запрещает, например, возвращать из функции значение в EBP, однако было бы логичнее это делать через EAX. ECX часто используется для счетчика. А EBP часто используется для хранения кадра стека..

    В маленьких функциях, конечно, можно обойтись и без кадра стека.
    Например, функция сложения своего аргумента и десяти:
    Код (Text):
    1. func:
    2.   mov eax, [esp+4]
    3.   add eax, 10
    4.   ret 4
     
  13. green

    green New Member

    Публикаций:
    0
    l_inc
    Не совсем так. Посмотри описание команд ENTER, LEAVE.
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    green
    Дык это ж и есть те самые пролог/эпилог, которые я приводил, пытаясь объяснить, почему мне ebp лишним кажется. Если бы при работе с ebp в ЦП предлагалась какая-то особая поддержка для работы со стеком, тогда можно было бы сказать, что он архитектурно выделяется. А так - просто лишняя ячейка памяти с особым названием. С таким же успехом можно было бы добавить регистр mcx (MyCool register) и сказать, что общепринятым считается хранить в нем только самые крутые значения в программе.
    Так что замечание не принято. :)
    P.S.
    RuAsm
    Извиняюсь, что перехватил тему. Надеюсь, что комментарии форумчан к моему вопросу были полезными при ответе на ваш вопрос о ebp. :)
     
  15. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    ESP - тоже ничем абсолютно не выделяется, если судить по твоим критериям. Подумаешь, там принято хранить адрес стека. Я могу там и числа перемножать. Кто запретит?
     
  16. l_inc

    l_inc New Member

    Публикаций:
    0
    Great
    Не а. Не согласен. Esp вполне очевидно используется при работе с командами pop/push. Его значение неявно изменяется, как часть алгоритма работы операций, являющихся частью архитектуры МП. А ebp - действительно просто ячейка памяти.
     
  17. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    А значение ebp неявно изменяется при enter/leave. А значение ECX меняется неявно при loop, значение esi(edi) при цепочечных командах, .... Список продолжить сколько команд неявно меняют регистры?
    Чем ESP по-твоему такой "особенный", а EBP такой "обычный" ?
    имхо, они одинаковы по своей "обычности"
     
  18. l_inc

    l_inc New Member

    Публикаций:
    0
    Ой. Забыл, что enter/leave - не директивы транслятора и не макросы (хотя и макросы тоже). Теперь почти согласен. "Почти": но разве enter/leave не были введены, начиная с 286-го? А назначение за bp (как и сам bp) закрепилось, подозреваю, раньше.
    Ну... я спрашивал только о ebp. Все остальные регистры мне не казались лишними. :)
     
  19. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    в 8086(286) использование sp и bp по умолчанию подразумевало сегмент ss для остальных регистров это был ds, и хотя можно было и явно указать ss:[bx] но это было на байт длиннее. Можно конечно прямо использовать esp не заморачиваясь на ebp, но тогда придется самому отслеживать уменьшение/увеличение esp после всех push/pop в маленькой процедуре это еще приемлемо, mov [esp+8],eax (89442408 - 4 байта) mov [ebp+8],eax (894508 - 3 байта)
     
  20. cppasm

    cppasm New Member

    Публикаций:
    0
    Назначение за bp закрепилось раньше, потому что на 8086 нельзя было адресоваться через sp - это раз. А как тогда обращаться к переменным в стеке если адресация через остальные регистры предусматривает в качестве сегмента по умолчанию ds.
    Плюс сегментация тогда активно использовалась (впрочем и сейчас тоже, только не в Win) - так что ds!=ss в очень многих случаях.
    А писать каждую команду с префиксом - это лишние байты и лишние такты при декодировании.

    Кстати, раз уж пошло обсуждение архитектуры.
    Никто не в курсе что значит r в x64?
    Ну то есть eax - extended ax, а rax - это что?
    Я думаю не от болды ведь :)