汇编语言读取控制台参数异常:无输出或乱码问题求助
汇编读取命令行参数的问题排查与修复
看起来你在x86汇编处理命令行参数时踩了几个常见的坑,我帮你梳理下问题所在,然后给出修正后的代码:
1. 命令行参数的栈结构理解有误
当C风格的main函数被调用时,栈的布局是这样的(从栈顶到栈底):
- 首先是返回地址(调用
main时压入的) - 然后是argc(参数数量)
- 接着是
argv[0](程序自身的路径/名称指针) - 之后是
argv[1]、argv[2]...直到argv[argc](NULL指针)
你之前的代码里,两次pop ebp拿到了返回地址和argc,这部分是对的,但进入primerCaso后再pop ebp,拿到的是argv[0](程序名),而不是你想要的argv[1](传入的参数),这就导致你打印的内容根本不是目标参数。
2. printf的调用方式完全错误
printf是C标准库函数,遵循cdecl调用约定:
- 必须先压入可变参数,最后压入格式字符串
- 调用完成后,调用者要手动清理栈(因为
cdecl要求调用者负责栈平衡) - 你之前直接
push opcion调用printf,既没有传递格式字符串(比如%s),也传递了错误的指针(后面会说),自然没有输出。
3. 数据类型不匹配导致乱码
你定义的opcion: resb 255是一个字节数组,但argv的每个元素是32位指针(4字节大小)。你执行mov [opcion], ebp是把指针存在opcion的前4字节里,然后push opcion是把这个数组的地址传给printf——相当于你给printf传了一个「指向指针的指针」,而不是字符串指针,printf会把这个地址里的内容当成字符串来解析,结果就是乱码。
修正后的完整代码
我帮你调整了代码,解决了上面的所有问题,同时添加了参数不足的错误提示:
SECTION .data format: db "%s", 10, 0 ; 格式字符串:打印字符串+换行 no_arg_msg: db "Error: 需要传入至少一个参数", 10, 0 SECTION .bss ; 这里如果不需要存储指针的话,可以不用定义opcion,直接用寄存器存即可 SECTION .text extern printf, exit, system global main clear: ; 补全clear函数(如果你的clear是清屏功能) push clear_cmd call system add esp, 4 ret clear_cmd: db "clear", 0 main: call clear ; 处理栈中的返回地址和argc pop ebx ; 弹出返回地址,暂时存在ebx(也可以直接pop丢弃) pop ecx ; ecx = argc(参数数量) cmp ecx, 2 jl interseccionCasos ; argc < 2,参数不足 je primerCaso call quit primerCaso: pop ebx ; 弹出argv[0](程序名,直接丢弃) pop edx ; edx = argv[1](我们要打印的目标参数指针) ; 调用printf打印参数 push edx ; 第二个参数:要打印的字符串指针 push format ; 第一个参数:格式字符串指针 call printf add esp, 8 ; 清理栈:两个参数,每个4字节,共8字节 call quit interseccionCasos: ; 参数不足时打印提示 push no_arg_msg call printf add esp, 4 ; 清理栈:一个参数,4字节 call quit quit: push 0 call exit ret ; 这里ret不会执行,因为exit会终止程序
编译与运行
因为你用的是32位汇编(使用ebp等32位寄存器),编译时需要指定32位模式:
gcc -m32 -o rpn rpn.s
运行测试:
- 输入
./rpn 2,会输出2 - 输入
./rpn "5 + 28",会输出5 + 28
内容的提问来源于stack exchange,提问作者José Sánchez
相关产品推荐
相关产品推荐

