如何解决Linux x86_64下AT&T语法汇编代码Segmentation fault报错
汇编逆波兰计算器问题修复
核心错误点
strcmp参数传错:原始代码调用strcmp匹配操作符时,错误传入立即数$cuvant(存储字符串指针的变量的内存地址),而非变量存储的实际字符串指针cuvant,导致所有操作符匹配失败,代码直接顺序执行到opadd标签,栈操作异常触发崩溃。- 寄存器被意外修改:32位Linux System V调用约定中
ebx属于被调用者保存寄存器,调用libc函数后使用popl %ebx平衡栈会修改ebx原值,触发libc运行时错误,正确做法是使用add $栈大小, %esp平衡栈。 - 除法操作未清空
EDX:div指令默认使用EDX:EAX作为被除数,EDX残留垃圾值会触发除法异常,直接导致程序退出。 - 操作符匹配无兜底逻辑:输入非法操作符时所有匹配失败后无错误处理,直接进入
opadd逻辑,弹出非法栈值导致程序异常。 - 操作符判断逻辑缺陷:用
atoi返回值是否为0判断当前token类型,若输入合法数字0会被误识别为操作符,触发逻辑错误。
修复后完整代码
.data formatPrintf: .asciz "%d\n" sir: .space 1000 delim: .asciz " " formatScanf: .asciz "%1000[^\n]" cuvant: .space 4 primulNumar: .space 4 y: .space 4 eval: .space 4 add_op: .asciz "add" sub_op: .asciz "sub" mul_op: .asciz "mul" div_op: .asciz "div" .text .global main main: pushl $sir pushl $formatScanf call scanf add $8, %esp pushl $delim pushl $sir call strtok add $8, %esp pushl %eax call atoi add $4, %esp movl %eax, primulNumar pushl primulNumar et_loop: pushl $delim pushl $0 call strtok add $8, %esp cmp $0, %eax je exit mov %eax, cuvant pushl %eax call atoi add $4, %esp # 改用判断token首字符是否为字母来区分数字和操作符,避免0的误判 movb (%eax), %dl cmpb $'a', %dl je operatie cmpb $'s', %dl je operatie cmpb $'m', %dl je operatie cmpb $'d', %dl je operatie pushl %eax jmp et_loop operatie: push cuvant push $add_op call strcmp add $8, %esp cmp $0, %eax je opadd push cuvant push $sub_op call strcmp add $8, %esp cmp $0, %eax je opsub push cuvant push $mul_op call strcmp add $8, %esp cmp $0, %eax je opmul push cuvant push $div_op call strcmp add $8, %esp cmp $0, %eax je opdiv # 非法操作符直接退出 jmp exit opadd: popl %edx popl %eax add %edx, %eax pushl %eax jmp et_loop opmul: popl %eax popl %ebx mul %ebx pushl %eax jmp et_loop opdiv: popl %ebx popl %eax xorl %edx, %edx div %ebx pushl %eax jmp et_loop opsub: popl %eax popl %edx sub %eax, %edx pushl %edx jmp et_loop exit: popl eval pushl eval pushl $formatPrintf call printf add $8, %esp pushl $0 call fflush add $4, %esp movl $1, %eax xorl %ebx, %ebx int $0x80
编译运行方法
x86_64环境下编译32位汇编需要提前安装32位运行库,编译命令如下:gcc -m32 -o rpn_calc rpn_calc.s -no-pie
运行后输入2 3 add 4 mul即可得到输出20。
内容的提问来源于stack exchange,提问作者Very Nice
相关产品推荐
相关产品推荐

