Являются ли регистры данных EAX, EBX, ECX и EDX взаимозаменяемыми - PullRequest
0 голосов
/ 18 ноября 2018

Я вхожу в мир программирования на ассемблере. Я пытаюсь понять все найденное на: https://www.tutorialspoint.com/assembly_programming

Я наткнулся на код ниже.

section .text
     global _start      ;must be declared for using gcc
_start: ;tell linker entry point

;This part works fine.
;mov    edx, len    ;message length
;mov    ecx, msg    ;message to write

;This does not work because I interchanged edx and ecx.
mov ecx, len    ;message length
mov edx, msg    ;message to write

mov ebx, 1      ;file descriptor (stdout)
mov eax, 4      ;system call number (sys_write)
int 0x80        ;call kernel
mov eax, 1      ;system call number (sys_exit)
int 0x80        ;call kernel

section .data

msg db  'Hello, Kaunda!',0xa    ;our dear string
len equ $ - msg         ;length of our dear string

Могу ли я добавить переменную 'len' или 'msg' в любой из регистров данных (EAX, EBX, ECX и EDX).

По словам заказа:

WHY - это содержимое переменной len, переданное в регистр EDX, а не ECX или любой другой регистр. Существует ли четкое руководство, чтобы узнать, какая переменная входит в какой регистр.

Я читал о функциях каждого из регистров EAX, EBX, ECX и EDX, но мне все еще неясно. Их функции похожи на меня.

Обновление: я запускаю код с https://www.tutorialspoint.com/compile_assembly_online.php Я думаю, что это среда Linux

1 Ответ

0 голосов
/ 18 ноября 2018

Когда вы запускаете int 0x80, ваша программа прерывается, и ядро ​​проверяет состояние регистров. Начиная с eax он получает номер системного вызова, который вы хотите выполнить, а из других регистров получает дополнительные данные. Например, для системного вызова write он извлекает дескриптор файла из ebx, указатель на буфер, который вы хотите записать из ecx, и количество байтов, которое вы хотите записать из edx. Ядро не знает, каковы ваши намерения, оно просто тупо захватывает то, что находится в регистрах, поэтому оно имеет значение, какие регистры вы используете.

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

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

Например, когда вы пишете функцию, вызываемую кодом других людей, ожидается, что вы вернете результат своей функции в eax и сохраните содержимое регистров ebx, esi, edi esp и ebp. Если вы используете эти регистры для своих собственных целей, вы должны сначала сохранить их значения где-нибудь (например, в стеке) и восстановить их до их исходных значений перед возвратом.

Существуют также некоторые инструкции, которые ожидают наличия операндов в определенных регистрах (например, stos или idiv), но для большинства инструкций вы можете выбирать любые регистры, которые вы хотите.

В тех случаях, когда это имеет значение, правила, для которых используются регистры, записываются в документе Application Binary Interface (ABI) . Этот документ может пониматься как соглашение между всеми программистами относительно того, какие данные ожидать, в какие регистры при вызове функций или операционной системы. Строгое соблюдение ABI необходимо для правильной работы вашего кода при вызове / вызове по чужому коду.

На i386, архитектуре, для которой вы сейчас программируете, Linux использует i386 SysV ABI . Как правило, каждая операционная система использует разные ABI для каждой архитектуры, поэтому перед написанием кода для новой операционной системы или архитектура обязательно проверьте соответствующий ABI.

...