Ответ 1
NASM/YASM легко отличить от MASM/TASM/emu8086. YASM использует синтаксис NASM, с небольшими отличиями в том, что он принимает для констант и директив.
Я не знаю, как отличить MASM от TASM, или TASM от emu8086, или FASM, поэтому я оставлю это для другого ответа по адресу.
В NASM явные размеры таких вещей, как операнды памяти, используют dword
или byte
. В стиле TASM/MASM вы должны написать dword ptr
или byte ptr
.
В MASM (и я думаю, TASM/emu8086) голое имя символа ссылается на содержимое. Вы должны использовать offset foo
чтобы получить адрес foo. В NASM вы должны использовать [foo]
для создания операнда памяти, а foo
- это адрес.
Возможно, есть и другие различия в синтаксисе (например, в переопределении сегментов), но их должно быть достаточно, чтобы определить, является ли что-то в стиле NASM или в стиле MASM.
NASM:
global foo
foo: ; a function called foo()
add dword [ecx], 2
add dword [counter], 1 ; Error without "dword", because neither operand implies an operand-size for the instruction. And the [] is required.
mov eax, [static_var]
mov eax, [static_array + ecx*4] ; Everything *must* be inside the []
mov esi, static_var ; mov esi,imm32 with the address of the static_var
ret
section .data
static_var: dd 0xdeadbeef ; NASM can use 0x... constant. MASM only allows 0DEADBEEFh style
section .bss
counter: resd 1 ; reserve space for one dword (initialized to zero)
buf: resb 256 ; reserve 256 bytes
Обратите внимание :
после названий меток здесь, даже для данных. Это рекомендуется, но не обязательно: любой неизвестный токен в начале строки считается меткой, поэтому counter resd 1
будет собираться. Но loop resd 1
не будет, потому что loop
является действительной мнемоникой инструкции.
MASM/TASM (у меня могут быть некоторые из этих ошибок, я не использую MASM или TASM):
GNU GAS .intel_syntax noprefix
в основном то же самое, но без волшебной ассоциации размера операнда для меток. И директивы GAS/псевдоинструкции совершенно разные, например .byte 0x12
против db 12h
.
.CODE
foo PROC ; PROC/ENDP definitely means not NASM
add dword ptr [ecx], 2
add counter, 1 ; operand-size magically implied by the dd after the counter label. [] is optional
mov eax, static_var ; mov eax, [static_var] is the same, and recommended by some for clarity
mov eax, static_array[ecx*4] ; [ static_array + ecx*4 ] is also allowed, but not required.
mov esi, OFFSET static_var ; mov esi,imm32 with the address.
ret
ENDP
.data ; no SECTION directive, just .data directly
static_var dd 0deadbeefH
;;; With a : after the name, it would be just a label, not a "variable" with a size associated.
.bss
; (In most OSes, the BSS is initialized to zero. I assume MASM/TASM allows you to write dd 0 in the BSS, but I'm not sure)
counter: dd 0 ; reserve space for one dword (zeroed)
buf db 256 dup(?) ; reserve 256 bytes (uninitialized).
За исключением случаев, когда я комментировал иначе, любое из этих отличий является гарантированным признаком того, что это NASM/YASM или MASM/TASM/emu8086
Например, если вы когда-либо видите пустой символ в качестве операнда назначения (например, mov foo, eax
), это определенно не NASM, потому что mov imm32, r32
не имеет смысла. Если символ на самом деле не является макроопределением для регистра, например, %define result eax
разрешит mov result, 5
. (Хороший улов, @MichaelPetch). Если источник полон макросов, ищите определения. %define
означает NASM, а MACRO
означает MASM/TASM.
MASM/TASM не имеет директив resb
/resd
. Вместо этого они имеют count DUP(value)
, где значение может быть ?
,
У NASM есть times 30 db 0x10
чтобы повторить байт 0x10
30 раз. Вы можете использовать его на чем угодно, даже на инструкциях. Он также имеет директивы %rep
для повторения блока.
MASM и NASM имеют значительные макроэкономические возможности, но используют другой синтаксис.
В теге x86 есть ссылки на руководства по сборке и многое другое.