数据寄存器 EAX、EBX、ECX 和 EDX 是否可以互换
Are the data registers EAX, EBX, ECX and EDX interchangeable
我正在步入汇编语言编程的世界。我试图了解在以下位置找到的所有内容: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)中吗?
关于订单词:
为什么变量 len
的内容被传送到 EDX 寄存器而不是 ECX 或任何其他寄存器?是否有明确的指导方针来知道哪个变量进入哪个寄存器?
EAX、EBX、ECX、EDX这几个寄存器的功能我都看过了,但还是不太清楚。他们的功能和我差不多
更新:我 运行 来自 https://www.tutorialspoint.com/compile_assembly_online.php
的代码
我认为是Linux环境
当您发出 int 0x80
时,您的程序被中断并且内核检查寄存器的状态。它从 eax
中获取您要执行的系统调用的编号,并从其他寄存器中获取其他数据。例如,对于 write
系统调用,它从 ebx
中获取文件描述符,从 ecx
中获取指向要写入的缓冲区的指针以及要从中写入的字节数edx
。内核不知道你的意图是什么,它只是愚蠢地抓住寄存器中的任何东西,所以你使用哪个寄存器很重要。
但是,一般来说,使用什么寄存器来表示什么值并不重要。在您自己的代码中,只要您不与其他人的代码交互,您可以随意使用几乎所有寄存器(除了像 esp
这样的寄存器)用于任何您想要的目的。
唯一需要使用哪些寄存器的地方是当你想与其他人编写的代码交互时,例如调用函数或操作系统时,或者编写将被其他人调用的函数时。在这种情况下,您必须将相关寄存器设置为预期值或可能保留其内容。
例如,当你写一个被别人的代码调用的函数时,你希望你return你的函数的结果在eax
中并且保留寄存器的内容ebx
、esi
、edi
、esp
和 ebp
。如果您将这些寄存器用于您自己的目的,您必须首先将它们的值保存在某个地方(例如在堆栈上)并在 returning.
之前将它们恢复为原始值
还有一些指令要求操作数存在于某些寄存器中(例如 stos
或 idiv
),但对于大多数指令,您可以自由选择所需的任何寄存器。
在重要的情况下,应用程序二进制接口 (ABI) 文档中记录了哪些寄存器用于哪些目的的规则。这份文档可以理解为所有程序员之间的协议,即在调用函数或操作系统时期望哪些数据在哪些寄存器中。当 calling/called 被其他人的代码使用时,必须严格遵守 ABI 才能使您的代码正常工作。
在 i386 上,您当前正在为其编程的体系结构,Linux 使用 i386 SysV ABI..通常,每个操作系统为每个体系结构使用不同的 ABI,因此在为新的代码编写代码之前操作系统或架构一定要查看相关的ABI。
我正在步入汇编语言编程的世界。我试图了解在以下位置找到的所有内容: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)中吗?
关于订单词:
为什么变量 len
的内容被传送到 EDX 寄存器而不是 ECX 或任何其他寄存器?是否有明确的指导方针来知道哪个变量进入哪个寄存器?
EAX、EBX、ECX、EDX这几个寄存器的功能我都看过了,但还是不太清楚。他们的功能和我差不多
更新:我 运行 来自 https://www.tutorialspoint.com/compile_assembly_online.php
的代码我认为是Linux环境
当您发出 int 0x80
时,您的程序被中断并且内核检查寄存器的状态。它从 eax
中获取您要执行的系统调用的编号,并从其他寄存器中获取其他数据。例如,对于 write
系统调用,它从 ebx
中获取文件描述符,从 ecx
中获取指向要写入的缓冲区的指针以及要从中写入的字节数edx
。内核不知道你的意图是什么,它只是愚蠢地抓住寄存器中的任何东西,所以你使用哪个寄存器很重要。
但是,一般来说,使用什么寄存器来表示什么值并不重要。在您自己的代码中,只要您不与其他人的代码交互,您可以随意使用几乎所有寄存器(除了像 esp
这样的寄存器)用于任何您想要的目的。
唯一需要使用哪些寄存器的地方是当你想与其他人编写的代码交互时,例如调用函数或操作系统时,或者编写将被其他人调用的函数时。在这种情况下,您必须将相关寄存器设置为预期值或可能保留其内容。
例如,当你写一个被别人的代码调用的函数时,你希望你return你的函数的结果在eax
中并且保留寄存器的内容ebx
、esi
、edi
、esp
和 ebp
。如果您将这些寄存器用于您自己的目的,您必须首先将它们的值保存在某个地方(例如在堆栈上)并在 returning.
还有一些指令要求操作数存在于某些寄存器中(例如 stos
或 idiv
),但对于大多数指令,您可以自由选择所需的任何寄存器。
在重要的情况下,应用程序二进制接口 (ABI) 文档中记录了哪些寄存器用于哪些目的的规则。这份文档可以理解为所有程序员之间的协议,即在调用函数或操作系统时期望哪些数据在哪些寄存器中。当 calling/called 被其他人的代码使用时,必须严格遵守 ABI 才能使您的代码正常工作。
在 i386 上,您当前正在为其编程的体系结构,Linux 使用 i386 SysV ABI..通常,每个操作系统为每个体系结构使用不同的 ABI,因此在为新的代码编写代码之前操作系统或架构一定要查看相关的ABI。