How could I do it?
(question from comments on self-answer)
Well, first you read Instruction reference guide to understand what the instruction does, and then you can use it, if it fits your purpose. This is the important step, keep re-reading instruction details every so often, to verify it does modify registers and flags in a way you expect it. Especially if in debugger you see the CPU state of change you didn't expect.
As you are in linux, the ds
/es
segment registers are very likely already set to reasonably values (covering .data
section), so after setting eSi
to Source address, eDi
to Destination address, and eCx
to Count, you write instead of COPY_LOOP:
just rep movsb
... and then exit trough int 80h (eax=1)
. (notice the emphasized letters in register names, Intel picked those intentionally to make it easy to recall)
BTW, just now I noticed, you wrote in your code sort of bugs:
inc si/di
should be inc esi/edi
, because you use esi/edi to address. If you would be copying array over 64k memory boundary, inc si
would wrap around on it.
set ecx
to 3, in 32b mode the loop
instruction does use whole 32b ecx
, not 16b part cx
only. If the code ahead of copy would use some large number in ecx
setting some of upper 16 bits, your loop would copy many more bytes than only 3.
ahead of calling int 80h
again you must set whole eax
with the function number, otherwise you risk to have some garbage in upper 16 bits of eax
from previous code, requesting invalid function.
So after applying these your code may look like this:
section .text
global _start
cpu 386
_start:
MOV ESI, TABLE_A
MOV EDI, TABLE_B
MOV ECX, 3
REP MOVSB ; copy ECX bytes from DS:ESI to ES:EDI
MOV EAX,1 ; call sys_exit, again FIXED to EAX!
INT 80h
section .data
TABLE_A DB 10, 5, 1
TABLE_B DB 0, 0, 0
If you did read the docs about registers, you should already understand what is difference between eax
and ax
. In Linux you are in 32b mode (when you link the binary as 32b elf, nowadays the 64b may be default on 64b system, which differs a bit from 32b mode), so by default use the 32b register variants. Unless you really want the 16b/8b variant for particular reason, and you make sure the code doesn't work later with 32b register while you set only less of it (like loop
, rep movsb
and int 80h
do).
Also it makes the code usually faster, as using 16b ax
in 32b mode requires additional opcode byte ahead of instruction, for example mov eax,ebx
is 2 bytes opcode 89 D8
, mov ax,bx
is 3 bytes opcode 66 89 D8
.