#assembly #x86 #stack #cpu-registers
#сборка #x86 #стек #cpu-регистры
Вопрос:
В нашем курсе есть практика использования assembly, которая выглядит следующим образом.
Что сохраняется в регистре EAX после этого кода?
mov eax, 10
push eax
push 20
mov ecx, eax
pop eax
Итак, из того, что я понял, первая строка означает, что 10 помещается в EAX, а во второй строке EAX помещается в стек.
Но что это значит? Удаляется ли содержимое eax?
Если 20 также помещается в стек, то стек равен 10 и 20?
Будет ли EAX регистрироваться после кода примерно как 10, 10, 20 или что-то еще и как оно отформатировано?
Комментарии:
1.
push
просто дублирует содержимое, реплицируя его в стек; нет никаких изменений в источнике (просто записывается память и корректируется указатель стека).pop
также не уничтожает исходную ячейку памяти, но поскольку указатель стека настроен, выделенная ячейка памяти теперь находится ниже указателя стека и поэтому считается свободной для перезаписи.2. felixcloutier.com/x86/push документирует именно то, что происходит при
push
выполнении инструкции; ни больше, ни меньше. Каждая инструкция просто документирует свое влияние на состояние архитектуры. Выполните эту последовательность в отладчике одним шагом, если вы не уверены, что произойдет от моделирования в вашей голове. (И, кстати, инструкции обычно оставляют регистр или ячейку памяти неизмененными после ее чтения, если только это не явная часть инструкции, напримерxchg
.)
Ответ №1:
Давайте пройдемся по этому шаг за шагом:
mov eax, 10 ; This assigns the value 10 to the register EAX
push eax ; This puts the value of EAX onto the stack (a LIFO structure)
push 20 ; This puts the DWORD value 20 onto the stack
mov ecx, eax ; This moves the value of the register EAX to the register ECX - the left hand side is the destination in x86 assembly with intel syntax
pop eax ; This puts the top value of the stack into EAX and decreases the stackpointer to now point to the preceding item
Последняя инструкция требует некоторой дополнительной информации. Я упоминал, что стек представляет собой структуру данных LIFO. Это означает «Последний вход-первый выход«.
Поэтому значение EAX(= 10) сначала помещается в стек. На следующем шаге значение 20 помещается в стек. mov ecx, eax
Инструкция не имеет смысла для этой задачи и может быть проигнорирована. Теперь, с pop eax
помощью, последний элемент (помните LIFO), который был помещен в стек, извлекается и помещается в регистр EAX.
Следовательно, окончательный ответ — EAX = 20.
Комментарии:
1. Хорошо, что левая сторона является местом назначения для обычного / собственного синтаксиса или синтаксиса Intel для x86, но правая сторона синтаксиса AT amp; T является местом назначения (левая сторона не является местом назначения для всех сборок x86). Первая инструкция является подсказкой здесь, что это, вероятно, синтаксис intel, и поэтому ecx получает копию eax. К счастью, эта инструкция не имеет отношения к результату, поэтому стиль синтаксиса не влияет на этот вопрос. Здесь уместны только две инструкции, и у них нет проблем с intel и AT amp; T.
2. @old_timer: я добавил уведомление о том, что рассматриваемая часть использует синтаксис Intel . В противном случае, если бы код использовал синтаксис AT amp; T, он был бы заполнен
%
символами, поэтому любой мог легко заметить это.