Являются ли регистры "специфичными" для определенного типа значения, или я могу присвоить любое значение любому регистру?
На x86 регистры ЦП в основном "общего назначения", то есть в вашем собственном коде вы можете использовать eax
против edx
довольно свободно, за исключением нескольких инструкций, использующих неявные регистры (div, mul, stos, movs, ...
).
Затем существуют специальные регистры (сегмент, управление, флаг, eip
).
Таким образом, вы обычно можете присвоить любое значение любому [общему] регистру.
Какая разница, если я назначу "eax, 4" или "edx, 4" или что если я назначу "ecx, 4".
Разница в том, что значение 4
будет сохранено либо в eax
, либо в регистре edx
. Оба они являются 32-битными регистрами x86 «общего назначения», оба хранят только тридцать два 0 или 1 значения, ничего более (также они не хранят никакой информации о «типе» или о том, как значение возникло в регистре, как он был отформатирован в источнике и т. д. * mov eax,16
идентичен mov eax,0x10
, процессор видит только конечный двоичный машинный код, который идентичен для обоих вариантов исходного кода, и загружает двоичное значение 00..0010000
(16 ) в реестр eax
). То есть пока что особой разницы нет, кроме ваших личных предпочтений.
Часть, где выбор eax
против edx
начнет иметь значение при использовании этих регистров (интерпретация значений битов определенным образом), и это в вашем примере происходит с int 80h
.
Эта инструкция вызывает 32-битные службы ядра Linux, то есть за ней скрываются тысячи строк кода, которые выполняют различные функции для приложений, и эти строки уже были скомпилированы поставщиком дистрибутива (или вами), и они являются частью двоичное ядро.
И разработчики Linux уже решили, что eax
содержит id-номер запрашиваемой службы, а другие регистры содержат аргументы для этой конкретной службы.
eax = 4
равно sys_write
, в то время как ваш второй пример с eax = str_len
вызовет какую-то другую службу, в зависимости от длины строки ("Hello world."
имеет длину 12 символов, поэтому ядро linux будет пытаться обслуживать sys_chdir
сервис для eax = 12
аргумента).
Таким образом, ваш второй пример не выводит «Hello world», и, судя по контексту, это просто недопустимый пример.
Когда вы вызываете какой-то внешний код, не принадлежащий вам, вы должны искать в документации, как правильно его назвать, и где / как передаются аргументы и какие условия должны быть выполнены (например, в 64-битном режиме при вызове функций C вы должны также выровнять адрес стека rsp
по границам 16B).
Для 32-битного ядра Linux системная служба документов ... не знаю, какие документы являются лучшими и надежными, эта ссылка из информации тега x86, как представляется, содержит подробную и полную информацию о том, как выполнять такие вызовы службы: https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/
Хотя в этой ссылке от Google https://syscalls.kernelgrok.com/ перечислены конкретные службы и ожидаемые аргументы (в сочетании с проверкой руководства по Linux для sys_write
и других должно быть достаточно).
Конкретный sys_write
из вашего примера ожидает аргументы как:
- eax = 4
- ebx = дескриптор файла (1 = стандартный вывод)
- ecx = данные для записи (адрес памяти первого байта данных)
- edx = длина данных для записи (в байтах).