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

为何emu8086下8086汇编年龄判断程序输入不同值总输出最后一条消息

emu8086 8086汇编年龄分段判断程序bug修正

问题描述

  • 程序设计目标:读取用户输入的姓名、学号、年龄,按年龄区间输出对应身份提示
  • 实际运行现象:无论输入何种年龄值,仅输出老年提示(you are old)
  • 原程序代码:
org 100h

INCLUDE 'emu8086.inc'

jmp start1 ; 程序入口跳转
;========================
msg1    db " Program Converter umur" ,13,10,13,10,'$'
msg2    db " Nama :  $"
msg3    db " NIM : $"
msg4    db " input your age : $"
msg5    db " you are baby $"
msg6    db " you are kids $"
msg7    db " you are teen $"
msg8    db " you are adult $"
msg9    db " you are old $"

start1:
LEA DX,msg1
MOV AH,9
INT 21H
PUTC 13
PUTC 10

start2:
LEA DX,msg2
MOV AH,9
INT 21H         
CALL GET_STRING
PUTC 13
PUTC 10

start3:
LEA DX,msg3
MOV AH,9
INT 21H     
CALL GET_STRING
PUTC 13
PUTC 10

start4:
LEA DX,msg4
MOV AH,9
INT 21H         
CALL GET_STRING
PUTC 13
PUTC 10

CMP CX,5
JB baby   
JE baby 
CMP CX,10 
JB kids 
JE kids
CMP CX,20
JB teen
JE teen
CMP CX,50
JB adult
JE adult
JA old

baby :
LEA DX,msg5
MOV AH,9
INT 21h
PUTC 13
PUTC 10

kids :
LEA DX,msg6
MOV AH,9
INT 21h
PUTC 13
PUTC 10

teen :
LEA DX,msg7
MOV AH,9
INT 21h
PUTC 13
PUTC 10

adult :
LEA DX,msg8
MOV AH,9
INT 21h
PUTC 13
PUTC 10

old :
LEA DX,msg9
MOV AH,9
INT 21h
PUTC 13
PUTC 10

MOV AH,0
INT 16H
ret

错误原因分析

  • 年龄数值获取错误:emu8086 的 GET_STRING 宏返回的 CX 是输入字符串的字符个数(例如输入年龄“25”时,CX=2),而非输入数字的二进制值,直接用 CX 做区间比较完全无效。
  • 分支穿透问题:baby、kids、teen、adult 分支的代码执行完成后,没有跳转到程序结束指令,会直接顺序执行后续分支的代码,最终必然走到 old 分支,输出老年提示。
  • 输入缓冲区未定义:GET_STRING 宏需要指定输入缓冲区(用于存储用户输入的字符),原代码未定义缓冲区,也未将 DI 指向缓冲区,导致输入操作的结果不可控。

修正方案

  • 新增ASCII字符串转二进制数值的逻辑:将输入的年龄ASCII字符(例如“25”)转换为对应的16位二进制值(0019h)。
  • 定义输入缓冲区:为姓名、学号、年龄的输入分别定义缓冲区,符合 GET_STRING 宏的调用要求。
  • 分支终止跳转:每个身份分支执行完成后,添加 jmp exit 指令跳转到程序结束,避免分支穿透。
  • 用转换后的年龄寄存器(例如 AX)做区间比较,而非字符个数 CX。

修正后程序代码

org 100h

INCLUDE 'emu8086.inc'

; 定义输入缓冲区(符合GET_STRING要求:首字节=最大字符数,次字节=实际输入数,后续=字符存储)
name_buf  db 20, ?, 20 dup(?)  ; 姓名缓冲区:最多19个字符
nim_buf   db 20, ?, 20 dup(?)  ; 学号缓冲区:最多19个字符
age_buf   db 3, ?, 3 dup(?)     ; 年龄缓冲区:最多2个字符(支持1-99岁)

jmp start1 ; 程序入口跳转
;========================
msg1    db " Program Converter umur" ,13,10,13,10,'$'
msg2    db " Nama :  $"
msg3    db " NIM : $"
msg4    db " input your age : $"
msg5    db " you are baby $"
msg6    db " you are kids $"
msg7    db " you are teen $"
msg8    db " you are adult $"
msg9    db " you are old $"

start1:
LEA DX,msg1
MOV AH,9
INT 21H
PUTC 13
PUTC 10

; 读取姓名
start2:
LEA DX,msg2
MOV AH,9
INT 21H         
LEA DI, name_buf  ; 指向姓名缓冲区
CALL GET_STRING
PUTC 13
PUTC 10

; 读取学号
start3:
LEA DX,msg3
MOV AH,9
INT 21H     
LEA DI, nim_buf   ; 指向学号缓冲区
CALL GET_STRING
PUTC 13
PUTC 10

; 读取年龄
start4:
LEA DX,msg4
MOV AH,9
INT 21H         
LEA DI, age_buf    ; 指向年龄缓冲区
CALL GET_STRING
PUTC 13
PUTC 10

; --- 新增:将年龄ASCII字符串转为二进制数值(存在AX) ---
MOV AX, 0          ; 初始化年龄数值为0
MOV CL, age_buf[1] ; 实际输入的年龄字符数(CX低8位)
MOV CH, 0          ; CX=实际输入字符数
MOV SI, 2          ; SI指向年龄缓冲区的第一个字符(age_buf[2])
convert_age:
MOV BX, AX         ; 保存当前数值
MOV AX, 10
MUL BX             ; 当前数值*10(处理两位数:例如先算2*10=20,再加5)
MOV BL, age_buf[SI]; 取当前ASCII字符(例如'5'=35h)
SUB BL, 30h        ; 转成数字(35h-30h=5)
MOV BH, 0
ADD AX, BX         ; 累加数值
INC SI
DEC CX
JNZ convert_age    ; 循环直到所有字符处理完成

; --- 区间比较(用AX=年龄数值) ---
CMP AX, 5
JB baby   
JE baby 
CMP AX, 10 
JB kids 
JE kids
CMP AX, 20
JB teen
JE teen
CMP AX, 50
JB adult
JE adult
JA old

baby :
LEA DX,msg5
MOV AH,9
INT 21h
PUTC 13
PUTC 10
JMP exit  ; 跳转终止,避免穿透

kids :
LEA DX,msg6
MOV AH,9
INT 21h
PUTC 13
PUTC 10
JMP exit  ; 跳转终止

teen :
LEA DX,msg7
MOV AH,9
INT 21h
PUTC 13
PUTC 10
JMP exit  ; 跳转终止

adult :
LEA DX,msg8
MOV AH,9
INT 21h
PUTC 13
PUTC 10
JMP exit  ; 跳转终止

old :
LEA DX,msg9
MOV AH,9
INT 21h
PUTC 13
PUTC 10

; 程序结束
exit:
MOV AH,0
INT 16H  ; 等待按键
ret

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 21:27:06