Первый косяк:
Код:
002034eb: sub $0x18,%esp
Скорее всего именно это привело к появлению leave вместо pop ebp в эпилоге. Плюс это же вынуждало бы нас увеличить размер стекового кадра потока перед его запуском на 0x18 байт (ранее я говорил, что нужно следить за действиями, выполняемыми в прологе над стеком).
Цитата:
Картинки мелкие делаю - превью, чтобы модеры не ругались
Проще делать текстовые ссылки. На миниатюрах все равно почти ничего не разглядеть.
Цитата:
Оставил push ebp/pop ebp в прологе/эпилоге для совместимости, хотя теперь можно и без них.
Нет, правильно сделал, что оставил. Содержимое ebp может использоваться в коде, из которого вызывается переключалка, т.е. внешний код может понадеяться на то, что ebp сохраняется в переключалке, и не сохранять/восстанавливать ebp самостоятельно. Плюс ты можешь через esp[-2] (образ ebp в стартовом стековом кадре) передавать в новый поток адрес запуска в прикладном пространстве (или еще какой-нибудь параметр).
Цитата:
Что же делал leave такого пакостного?
Портил esp. Эта инструкция неявно делает mov esp,ebp (esp=ebp), а у нас внутри переключалки до выполнения pop ebp в регистре ebp хранится значение, ассоциируемое с потоком, выполняющим переключение, а не с активируемым потоком (т.е. после переключения на новый стек у нас продолжает использоваться старое значение ebp). Прежде чем использовать новое значение ebp, его нужно взять из контекста активируемого потока. Например, можно расширить стартовый стековый кадр до 16 байт, разместив в esp[-2] или в esp[-3] значение ebp, указывающее на esp[-1], а внутри переключалки вокруг основных команд, осуществляющих переключение, добавить push ebp/pop ebp. Можно сделать еще проще - оставить размер стартового стекового кадра прежним (не добавлять push ebp/pop ebp), а в переключалке после команды загрузки esp для нового потока просто сделать mov ebp,esp (ebp=esp) или для нашего последнего случая lea ebp,[esp+18h] (ebp=esp+18h).
Цитата:
Чем опасно использование EBP указателя и как оно инициирует #TS?
Описал причину выше. Если нам нужно использовать новое значение ebp еще до завершения переключения на новый поток, то нам нужно предварительно это значение сформировать. Возникновение #TS - это лишь один из возможных сценариев развития при использовании некорректного указателя в ebp. Поэтому я и говорил, что ошибка какая-то странная. По сути это неопределенная ошибка, непосредственно не связанная с TSS.
Цитата:
Это одна из немногих функций на асме полностью написанная мной самостоятельно, да ещё и для интеграции в код на C
Можно смещениям полей дать символические названия. Можно в структуре потока хранить указатель на вершину стека, чтобы не вычислять его каждый раз.