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

汇编四则计算器运行报A2006未定义符号、栈段放置错误求助

汇编四则计算器A2006未定义符号报错修复

问题基本信息

  • 项目为x86汇编语言实现的支持加减乘除四则运算的计算器,代码内注释为法语,不影响逻辑理解
  • 已知代码中栈段放置位置不符合规范
  • 编译阶段共抛出7个A2006未定义符号错误,具体报错信息如下:
(56) error A2006: undefined symbol : scan_num
(89) error A2006: undefined symbol : scan_num
(100)error A2006: undefined symbol : do_plus
(103)error A2006: undefined symbol : do_minus
(106) error A2006: undefined symbol : do_mult
(109) error A2006: undefined symbol : do_div
(128) error A2006: undefined symbol : main

报错根因

A2006错误的触发逻辑是汇编器在整个代码中找不到被引用符号的定义,你的代码存在三类问题:

  1. 程序入口标签不匹配:代码末尾用end main声明程序入口,但全代码仅定义了start作为入口标签,不存在main标签
  2. 核心功能逻辑缺失:代码中两次调用scan_num读取用户输入的数字,四个条件跳转分别对应加减乘除四个运算分支,但scan_num过程、do_plus/do_minus/do_mult/do_div四个分支标签和对应的实现逻辑完全没有编写
  3. 栈段定义违规:你在代码开头写了org 100h,这是DOS COM程序的标准写法,COM程序为单段结构,DOS加载时会自动分配栈空间,不需要用户单独定义栈段。你额外定义的SSEG栈段既没有通过assume语句关联到SS段寄存器,也没有在代码初始化阶段给SS、SP指针赋值,不符合汇编程序段定义规范。

修复步骤

  • 修正入口声明:将代码最后一行的end main修改为end start,匹配实际的入口标签,解决main未定义的报错
  • 补全缺失的功能逻辑:
    • 编写scan_num近过程:实现从键盘读取多字符数字输入、转换为16位二进制数存入CX寄存器的逻辑,处理回车结束、非法字符过滤的边界情况
    • 编写四个运算分支标签:
      • do_plus:实现num1 + num2,计算完成后调用打印过程输出结果,执行完跳转到exit
      • do_minus:实现num1 - num2,计算完成后调用打印过程输出结果,执行完跳转到exit
      • do_mult:用MUL指令实现乘法,注意16位乘法结果存放在DX:AX寄存器对中,处理好转接后输出结果,执行完跳转到exit
      • do_div:先判断num2是否为0,为0则跳转到错误提示分支;非0则用DIV指令计算,商存于AX、余数存于DX,处理后输出结果,执行完跳转到exit

    注意:所有运算分支执行完成后必须跳转到exit,避免代码顺序落入错误处理逻辑

  • 修正栈段定义:直接删除开头独立定义的SSEG栈段即可,符合COM程序的编写规范。如果要改为EXE格式程序,需要删除org 100h语句,在assume中添加ss:SSEG声明,并且在start开头初始化SS为SSEG段地址、SP为栈顶偏移。

附原始代码

SSEG  SEGMENT      STACK
      DB          32 DUP("STACK---")
SSEG  ENDS
;===========================================================code segment
            assume cs:cseg, ds:cseg, es:cseg
cseg        segment

            org 100h
;----------

name "CALCULATRICE"

PUTC    MACRO char
        PUSH AX
        MOV AL,char
        MOV AH, 0Eh
        INT 10h
        POP AX
ENDM

jmp start

;------------- Zone de donnée

msg0    db "BELLAL MOHAMED BUT1 2021/2022",0Dh,0Ah
        db "CALCULATOR3000 gerant les quatres opérations basiques ( + - * / )",0Dh,0Ah,"$"
msg1    db 0Dh,0Ah,0Dh,0Ah, "Entrer le premier terme de l'opération: $"
msg2    db "Choisissez l'opérateur à utiliser: + - * / : $"
msg3    db "Entrer le second terme de l'opération: $"
msg4    db 0Dh, 0Ah,"Le résultat est: $"
msg5    db 0Dh, 0Ah," ",0Dh,0Ah,"$"
err1    db "Saisie incorrecte",0Dh,0Ah,"$"
smth    db "Et .... $"

opr db "?" ; variable contenant l'opérateur

num1 dw ? ; variable contenant le premier terme de l'opération
num2 dw ? ; variable contenant le deuxième terme de l'opération

;--------------- PROGRAMME

start:
mov dx, offset msg0
mov ah, 9
int 21h

lea dx, msg1
mov ah, 09h     ; afficher le premier message
int 21h

; récupérer un nombre saisi par l'utilisateur et on le stock dans
; le registre CX

call scan_num

mov num1, cx ; stocker le nombre dans num1

; nouvelle ligne
putc 0Dh
putc 0Ah

lea dx, msg2
mov ah, 09h         ; affiche le deuxième message
int 21h

; récupérer l'opérateur
mov ah, 1
int 21h
mov opr, al

; nouvelle ligne
putc 0Dh
putc 0Ah

cmp opr, "q"        ; q pour quitter
je exit

cmp opr, "*"
jb wrong_opr
cmp opr, "/"
ja wrong_opr

lea dx, msg3
mov ah, 09h
int 21h

call scan_num

mov num2, cx

lea dx, msg4
mov ah, 09h
int 21h

;------------- CALCULER

cmp opr, "+"
je do_plus

cmp opr, "-"
je do_minus

cmp opr, "*"
je do_mult

cmp opr, "/"
je do_div

;---------- CAS PAR DEFAUT

wrong_opr:
lea dx, err1
mov ah, 09h
int 21h

exit:

lea dx, msg5
mov ah, 09h
int 21h

mov ah, 0

;---------
cseg        ends
            end main

内容的提问来源于stack exchange,提问作者BJW92i

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:33:26