我正在进入汇编语言编程的世界。我试图了解在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环境
答案 0 :(得分:2)
发出int 0x80
时,程序被中断,内核检查寄存器的状态。它从eax
中获取您要执行的系统调用的编号,并从其他寄存器中获取其他数据。例如,对于write
系统调用,它从ebx
获取文件描述符,从ecx
指向要写入的缓冲区的指针,以及要从其中写入的字节数edx
。内核不知道您的意图是什么,它只是愚蠢地获取寄存器中的内容,因此使用哪个寄存器很重要。
但是,一般而言,使用哪个寄存器的值并不重要。在您自己的代码中,只要您不与其他人的代码交互,就可以随意使用几乎所有寄存器(除了esp
之类的寄存器之外),以达到您想要的目的。
使用哪个寄存器的唯一重要地方是当您想与其他人编写的代码进行交互时,例如在调用函数或操作系统时,或者在编写将由其他人调用的函数时。在这种情况下,您必须将相关寄存器设置为预期值,或者可能保留其内容。
例如,当您编写由其他人的代码调用的函数时,期望您在eax
中返回函数的结果并保留寄存器ebx
,{{1 }},esi
,edi
和esp
。如果您出于个人目的使用这些寄存器,则必须先将它们的值保存在某个位置(例如,在堆栈上),然后将它们恢复为原始值,然后再返回。
也有一些指令期望操作数位于某些寄存器中(例如ebp
或stos
),但是对于大多数指令,您可以自由选择所需的任何寄存器。
在重要的情况下,应用程序二进制接口(ABI)文档中记录了用于什么目的的寄存器规则。可以将本文档理解为所有程序员之间的协议,涉及在调用函数或操作系统时在哪个寄存器中期望哪个数据。严格遵守ABI是使您的代码在由他人的代码调用/调用时正确工作的必要条件。
在i386(您当前正在为其编程的体系结构)上,Linux使用i386 SysV ABI。通常,每个操作系统对每个体系结构使用不同的ABI,因此在为新的操作系统或体系结构编写代码之前,请确保查看相关的ABI。