Ответ 1
Когда вы указываете параметр .intel_syntax noprefix
, вы указываете ассемблеру Gnu, что вы будете использовать синтаксис MASM. То, что вы написали, это, по сути, синтаксис NASM, который во многом похож на синтаксис MASM, но в другом случае он тонко отличается.
Для полного обсуждения различий см. этот раздел руководства NASM.
Для краткого обзора синтаксиса NASM и MASM см. этот документ.
(Этот второй документ использовался для размещения в Интернете, в более читаемом формате HTML, здесь, но ссылка опустилась, и я к сожалению, не удается найти копию в Wayback Machine.)
Большая вещь, которая должна измениться в вашем коде, заключается в том, что вам нужно включить директиву PTR
после каждого из спецификаторов размера. Так, например, вместо:
mov dword [rsp], '/pro'
mov dword [rsp+4], 'c/fl'
вам нужно написать:
mov dword ptr [rsp], '/pro'
mov dword ptr [rsp+4], 'c/fl'
Кроме того, хотя синтаксис MASM обычно записывает шестнадцатеричные константы с конечным h
, вместо ведущего 0x
, режим "MASM" газа не поддерживает это, и вам нужно использовать стиль C 0x
, даже при использовании синтаксиса Intel.
Я думал, что
push byte 60
считается действительной инструкцией в синтаксисе Intel.
Нет, не совсем. Единственными значениями размера, которые вы можете PUSH
и POP
из стека, являются собственная ширина регистра процессора. Итак, в 32-битных двоичных файлах вы должны нажать и поместить 32-битные значения, тогда как в 64-битных двоичных файлах вы должны нажать и поместить 64-битные значения. * Это означает, что эти строки кода технически неправильно:
push 'ag'
push byte ptr 0x7f
push byte ptr 60
MASM предоставит вам предупреждение о недопустимом размере операнда для последних двух инструкций, размер которых явно указан, но он будет неявно расширять эти константы до 64-битных значений и успешно собираться. Я предполагаю, что ассемблер Gnu тоже может сделать это автоматическое расширение значений, поэтому вам нужно просто отбросить директиву размера:
push 'ag'
push 0x7f
push 60
__
* С технической точки зрения вы можете использовать префикс переопределения размера операнда, чтобы вы могли нажимать 16-битное мгновенное на стек, как в 32-битном, так и в 64-битном режиме. Но вы действительно не должны этого делать, потому что это неправильно выравнивает стек, создавая проблемы с производительностью (и, если вы взаимодействуете с кодом, скомпилированным на других языках, ломает ABI). Вставляйте только 16-битные значения в стек при записи 16-битного кода. Если вы хотите нажать 16-битное значение в 32-битном или 64-битном режиме, просто позвольте ассемблеру расширять его до 32-разрядного или 64-битного, соответственно.