编译lib.so时在汇编函数中调用另一个汇编函数的问题
解决汇编实现strpbrk复用strstr编译到libasm.so的问题
我来帮你排查一下你遇到的问题,先看你的strpbrk实现和编译环节里的几个关键问题:
你的代码里的核心问题
- 寄存器调用约定违反:在System V AMD64的调用规范里,rbx、rbp这类寄存器属于「被调用者保存寄存器」——也就是说,你的函数如果要用这些寄存器,必须先把它们的值压栈保存,不然调用strstr的时候,strstr可能会修改这些寄存器的值,导致你的后续逻辑错乱。你代码里直接用了rbx但没保存,这会出问题。
- 内存越界操作:你定义了
buf db 0, 0(两个字节的缓冲区),但用了mov [buf], ebx这个32位的存储指令——这会往buf里写4个字节,直接越界覆盖后面的内存,触发未定义行为。 - 字符串传递错误:
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
相关产品推荐
相关产品推荐

