TL: DR: Никогда не используйте директиву BITS
, если это не необходимо .
Директива BITS не изменяет тип выходного файла, выбранный с помощью -felf64
или -felf32
.(-felf
является синонимом -felf32
, если вы когда-либо видели, что используется в примерах.)
Для создания 32-разрядных статических исполняемых файлов я использую сценарий оболочки asm-link
, который в итоге делает это:
nasm -felf32 -g -Fdwarf foo.asm &&
ld -melf_i386 -o foo foo.o
Формат отладки stabs
устарел, хотя, пока ваш отладчик поддерживает его, он, вероятно, подходит для отображения строк исходного кода asm в инструкции asm.В любом случае, -Fstabs
является значением по умолчанию, если вы используете -g
.(Я не читал все это, но https://www.ibm.com/developerworks/library/os-debugging/index.html имеет некоторую информацию о STAB против DWARF.)
В большинстве случаев директива BITS в лучшем случае бесполезнав худшем случае активно вредно. Вместо такой полезной ошибки, как push ebx
, которая не кодируется, если вы пытаетесь встроить 32-битный код в 64-битный объектный файл, он позволяет таким вещам происходить.(Хотя это не спасло бы вас здесь, потому что весь этот код собирался обоими способами.)
Единственное время, когда BITS
полезно, это когда вы хотите использовать nasm -fbin
и создайте плоский двоичный файл, который вы можете передать ndisasm или использовать в качестве шелл-кода, или сами определите ELF или любые другие заголовки метаданных с помощью db
( Учебное пособие по вихревому созданию действительно исполняемых ELF-исполняемых файлов для Linux ).nasm
не предоставляет параметр командной строки для изменения режима BITS 16
по умолчанию для -fbin
.
Или, если вы действительно хотите смешать 16, 32 и 64-битный кодв файле, который загружается в 16-битном режиме и переключается в 64-битный режим: это основной вариант использования для BITS
. или для включения некоторого BITS 32
или BITS 16
машинного кода в качестве данных в вашем 64-битном исполняемом файле.
Не вставляйте строку BITS 32
в верхней части файла как часть шаблона, это не поможет или не поможет. Используйте комментарий типа ;;; 32-bit x86 Linux code, NASM syntax
, если хотите описать, что находится в этом исходном файле и как его можно построить / запустить.
Вы можете и должны использовать DEFAULT REL
хотя, поэтому, если вы создаете 64-битный код, вы получите относительные к RIP режимы адресации для операндов памяти, таких как [somedata]
(имя символа без регистров GP).Это на один байт короче, чем 32-разрядные режимы абсолютной адресации, и будет работать в исполняемом файле PIE.
Интересный факт: 32-разрядный режим имеет 2 избыточных способа кодирования [disp32]
режимов абсолютной адресации.x86-64 переназначил более короткий (без байта SIB) как RIP-относительный. Именно поэтому ваша 64-битная разборка 32-битного машинного кода имеет DWORD PTR [rip+0x6000c0]
, где rel32 - абсолютный адрес символа.