Изучение ассемблера - название эхо-программы - PullRequest
2 голосов
/ 10 августа 2011

Я пытаюсь написать простую программу на ассемблере, которая запишет название программы.Используя gdb для отладки, я определил, что вызов sys_write возвращает -14 (EFAULT).Я также смог убедиться, что моя функция strlen работает правильно.Кажется, что есть какая-то проблема с доступом к памяти, но я не понимаю, что может быть не так, учитывая, что strlen обращается к той же памяти и работает нормально.Что не так?

Спасибо!

Полный код:

section .text
    global _start

_start:
    mov rax, [rsp+8]
    push rax
    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

Ответы [ 2 ]

4 голосов
/ 10 августа 2011

Как я написал в комментарии, x86_64 использует другой метод для системных вызовов, чем 32-битный linux.В частности, int $0x80 больше не является способом сделать это (хотя это может оказаться неполной работой, если у вас установлены 32-битные библиотеки ....).Смотрите, например, это предыдущее обсуждение .

Где на 32-битном x86 вы бы сделали:

mov eax, SYSCALL_NUMBER
mov ebx, first_param
mov ecx, second_param
mov edx, third_param
int 0x80

На 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

Чтобы напечатать название программы, измените вашЗапрограммируйте следующее, и оно должно работать.Для всех, кто интересуется, как выглядит программная среда при запуске, см. здесь .

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

Скомпилировано с использованием:

nasm -g -f elf64 -o sc.o sc.asm
gcc -nostartfiles -o sc sc.o
0 голосов
/ 10 августа 2011

В начале вы добавляете rsp с 8, в результате чего вызов sys_write получает другую строку, чем ваша функция strlen.strlen не изменяет стек, а нажатая rax не используется позже?Почему бы вам не сбросить операторы push rax и add rsp, 8 и посмотреть, как это работает для нас?

...