开发者

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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜