You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译lib.so时在汇编函数中调用另一个汇编函数的问题

解决汇编实现strpbrk复用strstr编译到libasm.so的问题

我来帮你排查一下你遇到的问题,先看你的strpbrk实现和编译环节里的几个关键问题:

你的代码里的核心问题

  1. 寄存器调用约定违反:在System V AMD64的调用规范里,rbx、rbp这类寄存器属于「被调用者保存寄存器」——也就是说,你的函数如果要用这些寄存器,必须先把它们的值压栈保存,不然调用strstr的时候,strstr可能会修改这些寄存器的值,导致你的后续逻辑错乱。你代码里直接用了rbx但没保存,这会出问题。
  2. 内存越界操作:你定义了buf db 0, 0(两个字节的缓冲区),但用了mov [buf], ebx这个32位的存储指令——这会往buf里写4个字节,直接越界覆盖后面的内存,触发未定义行为。
  3. 字符串传递错误:movzx rsi, WORD[buf]是把buf的两个字节作为数值加载到rsi里,但strstr需要的是字符串的指针,不是字符串内容本身,这会导致strstr接收到错误的参数。

修正后的strpbrk代码

SECTION .data
buf db 0, 0  ; 临时存储单个字符+字符串结束符

SECTION .text
global strpbrk
extern strstr  ; 声明strstr是外部函数,需要链接时提供

strpbrk:
init:
push rbp
mov rbp, rsp
push rbx          ; 先保存rbx寄存器,符合调用约定
mov r9, rdi       ; 保存原字符串的起始地址
mov r10, rsi      ; 保存分隔符集合的地址
mov rdx, -1

loop:
inc rdx
mov rbx, r9
add rbx, rdx
movzx ebx, BYTE[rbx]
test bl, bl
jz end_not_found  ; 原字符串遍历完,没找到匹配的字符

; 构造合法的单字符字符串到buf
mov BYTE[buf], bl   ; 只写入当前字符(1字节)
mov BYTE[buf+1], 0  ; 手动添加字符串结束符

; 调用strstr:rdi=分隔符集合,rsi=单字符字符串的地址
mov rdi, r10
mov rsi, buf
call strstr
test rax, rax
jnz end_found     ; strstr返回非空,说明当前字符在分隔符里

jmp loop

end_found:
mov rax, rbx      ; 返回原字符串中匹配字符的地址
pop rbx
leave
ret

end_not_found:
mov rax, 0        ; 没找到匹配,返回NULL
pop rbx
leave
ret

完整的编译链接命令

你需要确保把strstr和strpbrk的目标文件都链接进共享库,用以下命令:

# 编译两个汇编文件为64位ELF目标文件
nasm -f elf64 src/strstr.asm -o src/strstr.o
nasm -f elf64 src/strpbrk.asm -o src/strpbrk.o
# 链接成共享库
ld -shared -o libasm.so src/strstr.o src/strpbrk.o

这样应该能解决你编译时的问题,同时保证strpbrk正确复用strstr的功能。

内容的提问来源于stack exchange,提问作者Raidden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:01:36