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

从C语言向x86汇编传递字符串参数问题求助

解决C调用x86汇编字符串比较函数的参数传递问题

这问题我之前踩过坑!核心大概率是C与汇编之间的调用约定不匹配,毕竟x86下不同调用约定(比如cdecl、stdcall)对参数传递顺序、栈清理规则的要求完全不同——你单独写汇编时可能没遵循C的调用规则,导致参数读取错位,自然没法正常工作。下面给你一步步排查和解决的思路:

1. 先确认调用约定匹配

C语言默认使用cdecl调用约定(大部分编译器如GCC、Clang、MSVC默认都是),规则是:

  • 参数从右往左压入栈
  • 由**调用者(C代码)**负责清理栈

你的汇编函数必须严格遵循这个规则,否则参数位置会完全错误。比如:

  • C里要明确声明函数原型:
    // 假设返回1表示str1>str2,0表示否则
    int str_greater(const char *str1, const char *str2);
    
  • 汇编里要正确设置栈帧并读取参数:
    str_greater:
        push ebp          ; 保存旧的基址指针
        mov  ebp, esp     ; 用栈指针设置新基址,固定栈帧
        ; 此时栈布局:ebp+4是返回地址,ebp+8是第一个参数str1,ebp+12是第二个参数str2
        mov  esi, [ebp+8] ; 把str1地址加载到esi
        mov  edi, [ebp+12]; 把str2地址加载到edi
        ; 你的字符串比较逻辑...
        pop  ebp          ; 恢复基址指针
        ret               ; cdecl下调用者清栈,直接ret即可
    

如果你的汇编函数跳过了push ebp/mov ebp, esp这步,栈帧没固定,读取的参数地址肯定是错的。

2. 检查字符串的换行符问题

你用fgets()读取的字符串会包含末尾的换行符(如果输入没超过长度),但单独测试汇编时可能用的是不带换行的字符串,这会导致比较结果不符合预期。建议在C里先把换行符去掉:

char str1[31], str2[31];
// 读取字符串
fgets(str1, 31, stdin);
fgets(str2, 31, stdin);
// 去掉末尾的换行符(如果存在)
str1[strcspn(str1, "\n")] = '\0';
str2[strcspn(str2, "\n")] = '\0';

3. 验证参数地址是否正确

可以在C里打印两个字符串的内存地址,然后在汇编里调试确认参数是否正确传递:

#include <stdio.h>
// ... 函数声明和读取字符串的代码
printf("str1 地址: %p\nstr2 地址: %p\n", str1, str2);
int result = str_greater(str1, str2);

然后用调试器在汇编函数开头打断点,查看ebp+8和ebp+12的值是否和上面打印的地址一致。如果不一致,说明调用约定或者栈帧设置有问题;如果一致,那问题可能出在你的字符串比较逻辑里。

4. 确认汇编的比较逻辑正确性

单独测试汇编时正常,但结合C调用后异常,也可能是汇编逻辑对字符串结束符的处理有问题——比如C里的字符串是\0结尾,但你汇编里可能没处理好,或者比较规则(比如ASCII顺序、是否忽略大小写)和预期不符。可以在汇编里加调试输出(或者用调试器单步),看每一步的字符比较结果是否符合预期。

内容的提问来源于stack exchange,提问作者bock.steve

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:52:34