数据寄存器 EAX、EBX、ECX 和 EDX 是否可以互换

Kau*_*nda 2 x86 assembly nasm cpu-registers

我正在步入汇编语言编程的世界。我试图了解在以下位置找到的所有内容: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
Run Code Online (Sandbox Code Playgroud)

我可以选择将变量 'len' 或 'msg' 放在任何数据寄存器(EAX、EBX、ECX 和 EDX)中吗?

关于命令词:

为什么将变量的内容len传输到 EDX 寄存器而不是 ECX 或任何其他寄存器?是否有明确的指南来了解哪个变量进入哪个寄存器?

我已经阅读了有关 EAX、EBX、ECX 和 EDX 每个寄存器的功能的信息,但我仍然不清楚。他们的功能看起来和我很相似。

更新:我已经从https://www.tutorialspoint.com/compile_assembly_online.php运行代码

我认为是Linux环境

fuz*_*fuz 10

当您发出 时int 0x80,您的程序被中断,内核会检查寄存器的状态。从eax它获取您要执行的系统调用的编号,并从其他寄存器获取其他数据。例如,对于write系统调用,它从 中获取文件描述符ebx、指向要从中写入的缓冲区的指针ecx以及要从中写入的字节数edx。内核不知道您的意图是什么,它只是愚蠢地获取寄存器中的任何内容,因此您使用哪些寄存器很重要。

但是,一般来说,将什么寄存器用于什么值并不重要。在您自己的代码中,esp只要您不与其他人的代码交互,您就可以随意使用几乎所有的寄存器(例如 registers as 除外)。

唯一需要使用哪些寄存器的地方是当您想与其他人编写的代码进行交互时,例如调用函数或操作系统时,或者编写将被其他人调用的函数时。在这种情况下,您必须将相关寄存器设置为预期值或可能保留其内容。

例如,当你写一个通过别人的代码调用的函数,它期望你返回你的函数的结果eax,并保持寄存器的内容ebxesiediesp,和ebp。如果您出于自己的目的使用这些寄存器,则必须首先将它们的值保存在某处(例如,在堆栈中)并在返回之前将它们恢复为原始值。

还有一些指令期望操作数位于某些寄存器中(例如stosidiv),但是对于大多数指令,您可以自由选择您想要的任何寄存器。

在重要的情况下,寄存器用于什么目的的规则写在应用程序二进制接口 (ABI)文档中。这份文件可以理解为所有程序员之间关于调用函数或操作系统时期望哪些数据在哪些寄存器中的协议。在调用/调用其他人的代码时,必须严格遵守 ABI 才能使您的代码正常工作。

在 i386 上,你当前正在编程的架构,Linux 使用i386 SysV ABI .. 通常,每个操作系统为每个架构使用不同的 ABI,所以在为新的操作系统或架构编写代码之前,请务必查看相关的ABI。

  • @Kaunda 好吧,当您将长度放入“ecx”并将指向消息的指针放入“edx”时,内核仍然认为“ecx”包含指向消息的指针而“edx”包含消息的长度。解释为指针的长度指向无用,而解释为数字的指针通常是一个非常大的数字,因此内核返回错误“EFAULT”,意思是“无效地址”,正如@prl 已经解释的那样。将内核的错误代码转换为错误消息是您的工作。内核本身很少关心这个(除非在极少数情况下)。 (2认同)