Intel x86-64汇编:如何将地址向前偏移指定字节数并输出子串
在x86-64汇编中实现地址偏移并输出子串的正确方法
你的问题出在对rsi寄存器的赋值逻辑上——让我给你拆解清楚问题所在,再给出可运行的修正代码:
核心错误分析
你写的mov rsi, [string+3]是在读取内存内容:它会把string+3地址里存储的字节(也就是字符'i'的ASCII值)加载到rsi中,但Linux的sys_write系统调用要求rsi是指向输出缓冲区的指针地址,不是缓冲区里的数据本身。这就导致内核收到了一个无效的地址(比如0x69,也就是'i'的ASCII码),自然无法正常输出内容。
修正后的完整代码
这里是可以正常运行的x86-64 Linux汇编代码,包含字符串定义、正确的指针偏移和程序退出逻辑:
section .data ; 用db定义字节型字符串,"string"共6个字节 string db "string" section .text global _start _start: ; 调用sys_write输出偏移后的子串"ing" mov rax, 1 ; syscall编号:sys_write对应1 mov rdi, 1 ; 文件描述符:1表示标准输出(stdout) mov rsi, string+3 ; 直接传递偏移后的地址!不需要加[] mov rdx, 3 ; 要输出的字节数:"ing"是3个字符 syscall ; 必须调用sys_exit正常退出,否则会执行后续垃圾代码导致崩溃 mov rax, 60 ; syscall编号:sys_exit对应60 mov rdi, 0 ; 退出码:0表示正常退出 syscall
关键细节说明
string+3是汇编器在编译阶段就计算好的地址:string是字符串的起始地址,加上3字节后,正好指向原字符串的第4个字符(索引从0开始),也就是'i'的位置,这正是我们要输出的"ing"的起始点。- 不要忘记添加
sys_exit调用:如果省略这部分,程序执行完sys_write后会继续执行内存中后续的随机指令,大概率会触发段错误。 - 字符串定义不需要额外加终止符(比如
0),因为我们已经通过rdx指定了输出长度为3,sys_write会严格按这个长度输出,不会依赖终止符。
内容的提问来源于stack exchange,提问作者Privya Korshnikov
相关产品推荐
相关产品推荐

