从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
相关产品推荐
相关产品推荐

