I try to open file in assembly, to move value at memory locations(address) to rdi:
mov r13, [rsi+8*1] ; rsi - where addresses of cmdline parameters are.
mov [file_1], r13
; some calls...
mov rax, 2
mov rdi, [file_1] ;
xor esi, esi ; automatically zero-extended to rsi
mov rax, 8
mov rdi, [rsp+.fd_1]
xor esi, esi
mov edx, edx
(gdb) p/x &file_1
$1 = 0x601058
(gdb) x/xg 0x601058
(gdb) x/s 0x7fffffffe16a
Syscall 2 opens a file.
The parameters are:
rax: syscall #2 rdi: pointer: zero terminated filename rsi: int: flags rdx: int: mode
You use the following code:
... mov rax, 2 //syscall_2 = open file ... syscall
So far so good, however, according to the documentation:
Given a pathname for a file, open() returns a file descriptor, a small, nonnegative integer for use in subsequent system calls.
So you've only done the first part, you hopefully gotten a file descriptor, with that you can read data from the file, you need to add that part to the code.
Finally when you're done you need to clean up after yourself and close the file.
Let me complete the code for you.
//********* get a file_descriptor. push r15 //save non-volatile registers push r14 mov eax,2 //syscall_2 = open file mov rdi,[file_1] //filename xor esi,esi //flags = O_RDONLY xor edx,edx //mode = 0, good habits: don't leave parameters undefined. syscall //get me a file descriptor (fd). test eax,eax //is the fd positive? mov edi,eax //param1=fd mov eax,1 //set failure code, just in case. js failure //no,it's negative,report failure. //*********** read some data //Step 2, we have a fd, lets read the data in the file. mov r15,rax //save the fd in a non-volatile register for later. xor eax,eax //syscall_0 = read data from file mov rsi,[buffer] //an array to place the data into //`buffer` is the pointer to the buffer. mov edx,[len] //the max_len of the buffer, must be >= 2. dec edx //keep an extra byte to put a zero terminator into. //put 2 zero's if you're reading unicode_16 data. syscall //Read that data. xor r14,r14 //assume a length of zero in case of failure. //we can't jump to failure, we still need to clean up! test eax,eax //do we have a fail? cmovs rax,r14 //if failure, then set zero length result, else do nothing. mov [len],eax //set len to the length of data read. mov byte ptr [buffer+eax],0 //add a zero byte to terminate the data. //************ clean up //we are done, got the data. Let's close the file. mov r14,rax //if rax=0 then we had an error, store for later use mov rdi,r15 //param1 = fd mov eax,3 //syscall_3: close file syscall //close that file. test eax,eax //did close go ok? mov eax,3 //set failure code just in case. js failure //negative = failure //************ report back //if we get here, all went ok, report success and return. xor eax,eax //return 0 for success. //we still need to check if `read()` failed. sub r14,1 //carry = 1 only if r14 = 0 = failure else carry = 0 //sub eax,(0+carry) //if success then no-op else eax=eax-1 sbc eax,eax //eax = -1 if we had a failure when reading. failure: pop r14 //restore non-volatile registers pop r15 ret //all done
About 64 bits vs 32 bits
Also I read that mov has 32 bit source operand [...]
This is complete and utter hogwash.
X64 is a fully fledged 64 bit processor, that does what is says on the tin.
If you use a 64 bit register (any register that starts with an
R (and doesn't end with a
d or a
b)) you use all 64 bits in that register.
Pointers to memory should always go into a 64bits
If a register starts with an
E (or ends with a
d) it's a 32 bit register (the lower 32 bits).
Any write operation on a 32 bits register zeros out the top 32 bits of the overlapped 64 bit register, e.g.
mov eax,1 sets
rax to 1;
mov eax,-1 sets
$0000 0000 FFFF FFFF;
mov eax,2 and
mov rax,2 do the exact same thing.
mov eax,2 is two bytes shorter and is thus preferred.
If you read/write from/to memory the operation will follow the size of the register unless you specify otherwise.
If you write an immediate to memory you must specify the size.
You cannot write a 64-bit immediate to memory, you'll have to use 2 instructions to do that:
mov R64,imm64 + mov [mem],R64.
Any write to a 16-bits or 8-bits register does not zero out the top part of the associated 32/64 bits register!
If you want to write assembly, you need to actually learn assembly from the ground up.
Because you're programming in Linux I recommend getting a copy of Jeff Duntemann's book: Assembly Language Step By Step, for Linux
Jeff is a legend and can explain assembly better than anyone on this planet.