I'm stepping into the world of Assembly Language Programming. I'm trying to understand everything found on: https://www.tutorialspoint.com/assembly_programming
I came across the code below:
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
Can I choose to put the variable 'len' or 'msg' in any of the data registers (EAX, EBX, ECX and EDX).
On order words:
WHY is the content of variable len
transferfed into EDX register and not ECX or any other register? Is there a clear guideline to know which variable goes into which register?
I've read about about the functions of each of the registers EAX, EBX, ECX and EDX but I'm still not clear. Their functions looks similar to me.
Update: I've running the code from https://www.tutorialspoint.com/compile_assembly_online.php
I think that is Linux environment
When you issue an
int 0x80
, your program is interrupted and the kernel inspects the state of the registers. Fromeax
it grabs the number of the system call you want to execute and from the other registers it grabs additional data. For example, for thewrite
system call, it grabs the file descriptor fromebx
, a pointer to the buffer you want to write fromecx
and the number of bytes you want to write fromedx
. The kernel does not know what your intentions are, it just stupidly grabs whatever is in the registers, so it does matters which registers you use.However, in general, it does not matter what registers you use for what values. In your own code, you are free to use almost all registers (except for such as registers as
esp
) for whatever purpose you want as long as you don't interact with other peoples code.The only places where it matters which registers are used is when you want to interact with code written by other people, such as when calling functions or the operating system or when writing functions that are going to be called by others. In such cases, you have to set the relevant registers to the expected values or possibly preserve their contents.
For example, when you write a function called by other people's code, it is expected that you return the result of your function in
eax
and preserve the contents of the registersebx
,esi
,edi
,esp
, andebp
. If you use these registers for your own purposes, you have to first save their values somewhere (e.g. on the stack) and restore them to their original values before returning.There are also some instructions that expect there operands to be in certain registers (such as
stos
oridiv
), but for most instructions you are free to choose whatever registers you want.In the cases where it matters, the rules which registers are used for what purpose are written down in an Application Binary Interface (ABI) document. This document can be understood as an agreement between all programmers as to which data to expect in which registers when calling functions or the operating system. Strict adherence to the ABI is necessary to make your code work correctly when calling/called by other people's code.
On i386, the architecture you are currently programming for, Linux uses the i386 SysV ABI.. Generally, each operating system uses a different ABI for each architecture, so before writing code for a new operating system or architecture be sure to check out the relevant ABI.