Как изменить символ в строке в сборке x86 (синтаксис AT & T) - PullRequest
0 голосов
/ 15 октября 2018

Я пытаюсь изменить символ в строке в сборке, получая доступ к определенному биту в rdi, где расположен адрес строки.Тем не менее, это дает мне segfault.Пожалуйста, помогите

.text 

hello_world:    .asciz "hellothere \n"



.global main

main: 

    movq $hello_world, %rdi 
    movq $0, %rax 
    call printf

    movq $hello_world, %rdi 

    movb $'a', %r10b
    movb %r10b, (%rdi)
    movq $0, %rax
    call printf

    call exit

1 Ответ

0 голосов
/ 15 октября 2018

Инициализированные статические данные, которые вы хотите изменить во время выполнения, поступают в .data, а не .text.

Раздел .text сопоставляется как read + exec, .data сопоставляется как read + write.

Компиляторы используют .section .rodata для статических данных только для чтения, чтобы группировать данные отдельно от кода.Эти разделы связаны как часть текстового сегмента .


Если вы хотите поместить 64-битный адрес в регистр, вы должны использовать lea hello_world(%rip), %rdi

Но если бы это была проблема (усечение адреса до 32-битного значения сразу с movq вместо movabs), вы получите ошибку компоновщика.

Итак, вы явно связываете этов не-PIE исполняемый файл в Linux (потому что вы использовали printf, а не _printf (так что это не OS X, где movq $symbol, %r64 будет использовать 64-битный абсолютный немедленный запрос), и не получил ошибок ссылок при использовании 32-Битовые абсолютные перемещения для символьных адресов. Разница между movq и movabsq в x86-64

(В Linux статические адреса в зависимых от позиции исполняемых файлах, использующих модель кода по умолчанию, помещаются в 32 бита.)


Вы можете упростить свою программу до этого, для исполняемого файла Linux без PIE:

.data    # mutable static data
hello_world:    .asciz "hellothere \n"

#.section .rodata    # read-only static data


.text    # code
.global main
main: 
    mov   $hello_world, %edi  # most efficient way to put a static addr in a reg
                              # in a position-dependent executable
    xor   %eax,%eax           # most efficient way to zero the whole 64-bit reg
    call  printf

    mov   $hello_world, %edi 
    movb  $'a', (%rdi)          # store directly to memory instead of using a partial register
    xor   %eax,%eax
    call  printf

    xor    %eax,%eax     # return 0, otherwise you might as well jmp printf
    ret                  # might as well just ret instead of calling exit since this is main, not _start

компилируется и работает правильно с gcc -no-pie hello-mutable.S && ./a.out, или не может связаться с gcc -pie.

Для сборки с -pie (по умолчанию во многих современных дистрибутивах), используйте lea hello_world(%rip), %rdi оба раза.


Конечно, вы также можете использовать puts вместо printf, потому что в строке формата нет символов %.(Просто удалите завершающий \n.) Компиляторы выполняют эту оптимизацию при компиляции C. Это более эффективно, и вам не нужно обнулять AL.

...