x86 Сборочный набор различий "push'es" и "pusha"

Мне сказали поместить действительные регистры в стек, чтобы не перезаписывать их позже в "подпрограмме", и мне ясно, что все это знают. Но когда я прочитал код моих товарищей, я нашел следующий код:

puts: ; display character in ax
        push ax
        push bx
        push cx
        push dx
        mov dx, ax
        mov ah, 9h
        int 21h
        pop dx
        pop cx
        pop bx
        pop ax 
        ret 

Потом я увидел pusha а также popa команды. Я полагаю, это можно сделать следующим образом:

puts: ; display character in ax
        pusha
        mov dx, ax
        mov ah, 9h
        int 21h
        popa
        ret 

Есть ли разница между pusha и набор pushэс? Заранее спасибо.

3 ответа

Решение

Да, pusha а также popa функционально эквивалентны, хотя бы потому, что они выдвигают / выталкивают все регистры. Однако нужно ли это делать для простого вызова прерывания DOS?

Перевод в режим прерывания
...

Как и во всех операциях, делайте столько, сколько нужно, и ничего больше. Вызов прерывания должен сохранять регистры - кроме тех, которые задокументированы для изменения. Обычные статусные звонки возвращают свой результат в AX и может изменить флаги, и ничего не менять. Если прерывание меняет что-то еще (ds:dxНапример, это должно быть указано в документации.

В вашем коде, используя ah=09 / int 21единственное изменение

Возвращение: AL = 24 часа

и поэтому все остальные регистры можно смело считать "сохраненными".

Есть причина, по которой прерывание сохраняет как можно больше. Во всем мире прерывание ("настоящие", а не вызываемые пользователем) может произойти в любое время, когда выполняется другой код.

Есть также веская причина не использовать pusha/popa без разбора. Ваш стек имеет ограниченный размер - конечно, он большой, но так же, как и количество подпрограмм, которые могут быть вложены. И в 32- и 64-битном коде регистры также намного больше.

Каждая подпрограмма должна сохранять только те регистры, которые, как известно, меняются, и, отражая это, вы должны сохранять только те, которые вам понадобятся позже, прежде чем вы вызовете такую ​​подпрограмму. В примере кода их нет, так что вы можете безопасно удалить все нажатия и выталкивания.

pusha операция толкает больше, чем ax, bx, cx а также dx регистры:

"Вставляет все регистры общего назначения в стек в следующем порядке: (E)AX, (E)CX, (E)DX, (E)BX, (E)SP, (E)BP, (E)SI, (E)DI. Значение SP - это значение до фактического нажатия SP."

Вы можете сделать в основном то же самое, нажав регистры, используя восемь push инструкции, но это будет толкать другое значение для sp, Вы можете просто опустить указатель стека, так как на самом деле нет необходимости нажимать его. Нажатие и извлечение семи регистров заполняет ту же цель, что и pusha а также popa даже если это не делает то же самое:

push ax
push bx
push cx
push dx
push bp
push si
push di
...
pop di
pop si
pop bp
pop dx
pop cx
pop bx
pop ax

pusha сохраняет еще несколько регистров, в частности, значение sp перед выполнением, bp, si, а также di, Помимо этого, поведение в значительной степени идентично.

Другие вопросы по тегам