为何TASM编写的RPN计算器在mov bx, offset data_stack行崩溃?
TASM RPN计算器崩溃问题分析与修复
你的程序在mov bx, offset data_stack处看似崩溃,实际是后续逻辑的多处错误导致栈结构混乱、非法内存访问,以下是具体问题和修复方案:
核心错误点
- 错误的操作数宽度:
mov dx, [bx]使用16位寄存器读取字节型数据,一次性读取两个字符(比如第一个操作会读'3'和空格),压栈后破坏栈的对齐,后续pop操作会取出错误数据,直接导致执行异常。 - 未过滤无效字符:字符串中的空格、终止符0被直接压栈,后续会被当成运算符/操作数处理,导致栈溢出或非法计算。
- ASCII字符未转数值:数字字符是ASCII码(如'3'=0x33),直接参与加减会得到错误结果(比如'3'+'4'=0x67,对应ASCII的'g')。
- 无计算终止逻辑:计算循环没有判断栈是否只剩最终结果,会一直pop直到栈空,触发空栈访问崩溃。
修复后的代码
.model small .stack 100h .data data_stack db '3 4 +', 0 result db 0 .code start: mov ax, @data mov ds, ax mov bx, offset data_stack read_argument: mov al, [bx] cmp al, 0 ; 到达字符串末尾,开始计算 je calculate_expression cmp al, ' ' ; 跳过空格 je next_char ; 判断是数字还是运算符 cmp al, '+' je push_operator cmp al, '-' je push_operator ; 是数字,转成数值(ASCII减0x30) sub al, 30h push_operator: push ax ; 压入16位寄存器,保证栈对齐 next_char: inc bx jmp read_argument calculate_expression: pop ax ; 取出栈顶元素 cmp al, '+' ; 判断是运算符 je add_operands cmp al, '-' je subtract_operands ; 栈中只剩结果,保存并打印 mov result, al jmp print_result add_operands: pop bx ; 取出第一个操作数 pop cx ; 取出第二个操作数 add cl, bl ; 计算数值和 push cx ; 将结果压栈 jmp calculate_expression subtract_operands: pop bx ; 取出减数 pop cx ; 取出被减数 sub cl, bl ; 计算数值差 push cx ; 将结果压栈 jmp calculate_expression print_result: mov ah, 02h mov dl, result add dl, 30h ; 转成ASCII字符以便打印 int 21h exit_program: mov ah, 4Ch int 21h end start
关键修复说明
- 改用字节寄存器
al读取字符串字符,避免跨字节读取错误。 - 跳过空格字符,只处理数字和运算符。
- 数字字符转成十进制数值(减0x30),运算后再转回ASCII打印。
- 用16位寄存器压栈/出栈,保证栈的16位对齐(TASM栈操作默认是16位)。
- 添加计算终止判断:当栈顶是数值而非运算符时,说明得到最终结果,跳转打印。
内容的提问来源于stack exchange,提问作者Muhab Joumaa
相关产品推荐
相关产品推荐

