[英]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.