我正在步入汇编语言编程的世界。我正在努力了解以下内容: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
等寄存器除外(用于任何您想要的目的。
使用哪些寄存器唯一重要的地方是当你想与其他人编写的代码交互时,比如调用函数或操作系统时,或者编写将被其他人调用的函数时。在这种情况下,您必须将相关寄存器设置为预期值,或者可能保留其内容。
例如,当您编写由他人代码调用的函数时,希望您在eax
中返回函数的结果,并保留寄存器ebx
、esi
、edi
、esp
和ebp
的内容。如果您将这些寄存器用于自己的目的,则必须首先将其值保存在某个位置(例如堆栈上(,并在返回之前将其恢复为原始值。
也有一些指令希望在某些寄存器中有操作数(如stos
或idiv
(,但对于大多数指令,您可以自由选择所需的任何寄存器。
在重要的情况下,寄存器用于何种目的的规则会写在应用程序二进制接口(ABI(文档中。本文档可以理解为所有程序员之间关于在调用函数或操作系统时在哪些寄存器中预期哪些数据的协议。当调用/被其他人的代码调用时,严格遵守ABI对于使您的代码正确工作是必要的。
在i386上,Linux使用i386 SysV ABI。。通常,每个操作系统对每个体系结构使用不同的ABI,因此在为新的操作系统或体系结构编写代码之前,一定要检查相关的ABI。