简体   繁体   English

如何在程序集x86中更改字符串中的字符(AT&T语法)

[英]How to change a character in a string in assembly x86 (AT&T syntax)

Im trying to change the character in a string in assembly, by accessing a certain bit in the rdi where the string address is placed. 我试图通过访问放置字符串地址的rdi中的某个位来更改汇编字符串中的字符。 However, it is giving me a segfault. 但是,这给了我一个段错误。 Please help 请帮忙

.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

Initialized static data you want to modify at runtime goes in .data , not .text . 您要在运行时修改的初始化静态数据位于.data ,而不是.text

The .text section is mapped read+exec, .data is mapped read+write. .text部分映射为read + exec, .data部分映射为read + write。

Compilers use .section .rodata for read-only static data, to group data separately from code. 编译器将.section .rodata用于只读静态数据,以将数据与代码分开进行分组。 That sections is linked as part of the text segment . 这些部分被链接为文本段的一部分


If you want to put a 64-bit address in a register, you should use lea hello_world(%rip), %rdi 如果要在寄存器中放入64位地址,则应使用lea hello_world(%rip), %rdi

But if that was the problem (truncating the address to a 32-bit immediate from movq instead of movabs ), you'd get a linker error. 但是,如果这是问题所在(将地址从movq而不是movabs截断为32位立即movabs ),则会出现链接器错误。

So clearly you're linking this into a non-PIE executable on Linux (because you used printf not _printf (so it's not OS X where movq $symbol, %r64 will use a 64-bit absolute immediate), and didn't get link errors from using 32-bit absolute relocations for symbol addresses. Difference between movq and movabsq in x86-64 所以很明显,您将其链接到Linux上的非PIE可执行文件中(因为您使用的不是printf _printf (因此不是OS X的movq $symbol, %r64将使用64位绝对立即数),并且没有得到在符号地址中使用32位绝对重定位导致的链接错误。x86-64中movq和movabsq之间的差异

(On Linux, static addresses in position-dependent executables using the default code model fit in 32 bits.) (在Linux上,使用默认代码模型的位置相关可执行文件中的静态地址适合32位。)


You can simplify your program to this, for a Linux non-PIE executable: 您可以将程序简化为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

compiles and runs correctly with gcc -no-pie hello-mutable.S && ./a.out , or fails to link with gcc -pie . 使用gcc -no-pie hello-mutable.S && ./a.out编译并正确运行,或者无法与gcc -pie链接。

To build with -pie (the default on many modern distros), use lea hello_world(%rip), %rdi both times. 要使用-pie (许多现代发行版中的默认设置)进行构建,请同时使用lea hello_world(%rip), %rdi


Of course you could also use puts instead of printf because your format string has no % chars in it. 当然,您也可以使用puts代替printf因为您的格式字符串中没有% char。 (Just remove the trailing \\n .) Compilers do this optimization when compiling C. It's more efficient, and you wouldn't need to zero AL. (只需删除尾随的\\n 。)编译器在编译C时会进行此优化。它效率更高,并且您无需将AL设置为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM