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

如何解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 19:24:03