64位x86汇编:函数返回字符串存入数组失败问题排查
64位汇编字符串存储数组问题排查与解决
我正在用64位汇编开发,分为两个文件:一个负责生成带随机新字符的字符串,另一个包含数组。当前遇到的问题是:用打印函数输出数组中的字符串时显示为空,尝试多种修改方式均未解决——要么触发段错误,要么所有数组元素指向同一内容。
现有代码片段
字符串编辑文件的返回代码
returnString: mov rax, newString ret
数组初始化代码
section .bss array: resq 4 allocString: resb 128 section .text _start: mov qword[array], defaultMes0 xor r8,r8 add r8, 8 mov qword[array + r8], defaultMes1 add r8, 8 mov qword[array + r8], defaultMes2 add r8, 8 mov qword[array + r8], defaultMes3 add r8, 8
存储函数返回字符串到数组的rev函数代码
rev: mov rax, 8 movzx rdx, byte [index] ; Clear rdx to avoid issues with imul imul rdx ; Multiply index by 8 mov rdi, qword [array + rax] call stringEdit lea rbx, [allocString] translateLoop: mov dl, [rax] mov [rbx], dl ;both incremented and counter also incremented inc rax inc rbx ;comparison, if less than bl then done until it is equal to enterNum (place of split) cmp byte[rax], 0x0 jne translateLoop mov rax, 8 movzx rdx, byte [index] ; Clear rdx again imul rdx ; Multiply index by 8 mov qword [array + rax], rbx
已尝试的无效方案
修改返回代码为:
returnString: mov rax, [newString] ret修改后打印仍为空。
直接将函数返回值存入数组:
call stringEdit mov qword [array + rax], rdi ;;moved it to the rdi before解引用
newString打印触发段错误;不解引用时,所有数组元素指向同一内容,导致每次调用函数后所有索引共享相同结果。
解决方案
核心问题分析
- 共享缓冲区冲突:
rev函数复用全局的allocString作为目标缓冲区,所有数组元素最终指向同一块内存,后续调用会覆盖之前的内容。 - 返回值含义混淆:若
newString是字符串数组的直接地址,mov rax, newString是正确的;若newString是指针变量,则需解引用mov rax, [newString]才能拿到字符串地址。 - 数组索引计算错误:
rev开头的偏移计算逻辑混乱,mov rax,8后做乘法,导致array + rax的偏移指向错误位置。
修复步骤
分配独立缓冲区
放弃全局共享的allocString,在.bss为每个数组元素预留独立的字符串空间:section .bss array: resq 4 ; 存储字符串指针 arrayStrings: resb 4*128 ; 4个128字节的独立缓冲区在
rev中计算当前索引对应的缓冲区地址:movzx rdx, byte [index] imul rdx, 128 ; 每个缓冲区占128字节 lea rbx, [arrayStrings + rdx] ; 指向当前索引的独立缓冲区修正返回值逻辑
- 若
newString是直接定义的字符数组(如在.data/.bss中),保留mov rax, newString,返回字符串首地址。 - 若
newString是指针变量(如newString: resq 1),则用mov rax, [newString]返回它指向的字符串地址。
- 若
修正数组索引计算
重新整理索引偏移逻辑,确保正确指向数组元素:movzx rdx, byte [index] imul rdx, 8 ; 每个数组元素是8字节指针 mov rdi, qword [array + rdx] ; 获取原字符串指针存储新指针时同样使用正确的偏移:
mov qword [array + rdx], rbx ; 将独立缓冲区地址存入数组优化字符串复制循环
用已读取的dl判断终止符,减少内存访问:translateLoop: mov dl, [rax] mov [rbx], dl inc rax inc rbx cmp dl, 0x0 ; 直接用dl判断,避免重复访问[rax] jne translateLoop
修复后的rev函数示例
rev: movzx rdx, byte [index] imul rdx, 8 ; 计算数组指针偏移(每个元素8字节) mov rdi, qword [array + rdx] ; 获取原字符串指针 call stringEdit ; rax = 新字符串首地址 movzx rdx, byte [index] imul rdx, 128 ; 计算独立缓冲区偏移 lea rbx, [arrayStrings + rdx] ; 指向当前索引的缓冲区 translateLoop: mov dl, [rax] mov [rbx], dl inc rax inc rbx cmp dl, 0x0 jne translateLoop movzx rdx, byte [index] imul rdx, 8 mov qword [array + rdx], rbx ; 保存缓冲区地址到数组 ret
内容的提问来源于stack exchange,提问作者SeaNemi
相关产品推荐
相关产品推荐

