Learning assembly - echo program name
I am trying to write a simple program in assembly that will write out the name of the program. Using gdb to debug, I've determined that the call to sys_write is returning -14 (EFAULT). I've also been able to verify that my strlen function is working correctly. It seems like there is some sort of memory access issue, but I don't understand what could be wrong given that strlen is accessing the same memory and working fine. What is going wrong?
Thanks!
The full code:
section .text
global _start
_start:
mov rax, [rsp+8]
push ra开发者_高级运维x
call strlen
add rsp, 8
mov rdx, rax ; bytes to write
mov rax, 4 ; sys_write
mov rbx, 1 ; stdout
mov rcx, [rsp+8] ; addr of string
int 0x80
; exit
mov rax, 1
mov rbx, 0
int 0x80
strlen:
mov rax, 0
mov rbx, [rsp+8]
strlen_loop:
cmp byte [rbx+rax], 0
je strlen_end
inc rax
jmp strlen_loop
strlen_end:
ret ; len in rax
As I wrote in a comment, x86_64 uses a different method for syscalls than 32-bit linux. In particular int $0x80
is no longer the way to do it (though it might semi-work if you have the 32-bit libraries installed....). See for instance this previous discussion.
Where on 32-bit x86 you would do:
mov eax, SYSCALL_NUMBER
mov ebx, first_param
mov ecx, second_param
mov edx, third_param
int 0x80
You should do the following on x86_64:
mov rax, SYSCALL_NUMBER_64 ; This is usually different from the 32-bit version!
mov rdi, first_param
mov rsi, second_param
mov rdx, third_param
syscall
To print the program name, change your program to the following and it should work. For anyone else interested in how the program environment looks on startup, see here.
section .text
global _start
_start:
mov rax, [rsp+8]
push rax
call strlen
add rsp, 8
mov rdi, 1 ; fd = stdout
mov rsi, [rsp+8] ; buf = addr to string
mov rdx, rax ; count = strlen(string)
mov rax, 1 ; write
syscall
mov rdi, 0 ; status = 0
mov rax, 60 ; exit
syscall
strlen:
mov rax, 0
mov rbx, [rsp+8]
strlen_loop:
cmp byte [rbx+rax], 0
je strlen_end
inc rax
jmp strlen_loop
strlen_end:
ret ; len in rax
Compiled using:
nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o
You add rsp with 8 at the beginning causing the sys_write
call to get another string than your strlen function. The strlen
does not alter the stack and the pushed rax
is not used later? Why don't you drop the push rax
and add rsp, 8
statements and see how that works our for you?
精彩评论