16位FreeDOS汇编求助:数组值与指针相加异常问题
问题分析与解决方案
我来帮你拆解这个问题——你遇到的是16位汇编里操作数大小匹配的典型坑,咱们一步步说清楚:
核心原因:操作数大小被误解
你的代码中add bp, [tab + 1]的问题,在于没有明确告诉汇编器要读取的是单个字节,导致它错误地按16位字来处理内存数据:
bp是16位寄存器,在16位FreeDOS汇编环境(比如MASM/TASM这类兼容编译器)中,当你执行add 16位寄存器, [内存地址]时,汇编器默认会把内存地址处的内容当作**16位字(2字节)**来读取。- 但你的
tab是用db定义的字节数组,tab + 1对应的只是单个字节值2,它后面紧跟着的字节是6。汇编器按字读取时,会把这两个字节组合成小端模式的16位值0x0602。这样bp加上的就不是你想要的2,而是0x0602,指针偏移完全错误,自然取不到正确的字符。
而你换成add bp, 2时,是直接给bp加立即数2,操作数大小明确,所以能正确定位到目标字符。
修正方案:显式指定字节操作数
你需要明确告诉汇编器,要从tab+1处读取的是单个字节。根据你使用的汇编器,写法略有不同:
如果你用MASM/TASM:
mov bp, hexnum ; 获取hexnum的地址 add bp, byte ptr [tab + 1] ; 明确指定取tab+1处的单个字节(值2) mov dl, [bp] ; 从hexnum中取出'2'以便打印 mov ah, 2 int 0x21 tab: db 1,2,6,7 ; 待打印值的索引 hexnum: db '0','1','2' ; 十六进制字符数组
如果你用NASM:
NASM语法更简洁,直接用byte关键字指定即可:
mov bp, hexnum ; 获取hexnum的地址 add bp, byte [tab + 1] ; 明确指定取tab+1处的单个字节(值2) mov dl, [bp] ; 从hexnum中取出'2'以便打印 mov ah, 2 int 0x21 tab: db 1,2,6,7 ; 待打印值的索引 hexnum: db '0','1','2' ; 十六进制字符数组
额外小提示
在16位汇编里,寄存器和内存操作数的大小必须匹配,或者显式指定大小,否则很容易出现这种“逻辑看起来对但运行出错”的问题。比如用word ptr指定字操作数、byte ptr指定字节操作数,是这类场景下的常用技巧。
内容的提问来源于stack exchange,提问作者BSpirit
相关产品推荐
相关产品推荐

