使用emu8086实现字符串复制时遇未知操作码错误的问题排查
嘿,我来帮你拆解这个emu8086的汇编问题~
错误含义先搞懂
- unknown opcode skipped: 64:这个错误是说模拟器碰到了它认不出来的操作码
64(这其实是x86架构里FS段寄存器的前缀指令),为啥会出现?因为你的代码语法写错了,导致汇编器生成了无效的机器码,模拟器只能跳过这个错误指令继续执行。 - not 8086 instruction - not supported yet:意思是你写的代码里有不符合8086指令集规范的写法,或者用了emu8086还不支持的指令/语法。
你的代码里到底错在哪?
咱们逐行揪问题:
1. mov di, a 写法完全错误
在8086汇编里,如果你想把变量a的内存地址放到di寄存器里,直接写mov di, a是不行的——汇编器会把这个错误写法解析成带FS段前缀的指令,也就是那个导致64错误的元凶。正确的写法有两种:
lea di, a ; 把a的有效地址加载到di
或者
mov di, offset a ; 直接把a的偏移地址赋值给di
2. mov a, di 类型不匹配还逻辑多余
你定义的a是字节型变量(db 0),但di是16位寄存器,8086根本不允许把16位的数据塞进一个字节单元里,这属于类型不匹配的错误。而且从逻辑上来说,这行完全没必要:你已经用di指向了a的起始地址,复制完成后a里已经存好字符串了,直接用a的地址就行,根本不用把di的值存回a。
3. mov dx, a 没传对地址
int 21h的09h功能要求dx指向字符串的首地址,而且这个字符串得用$结尾(不是你用的0)。你直接写mov dx, a会把a这个字节里的数值加载到dx,这显然不是你要的地址。正确的写法是:
lea dx, a
或者
mov dx, offset a
4. 字符串结束符不匹配
你的msg用0结尾,但int 21h的09h功能只认$作为结束标记,所以复制后的字符串结尾是0的话,会导致输出乱码直到找到$。最简单的解决办法是把msg的定义改成:
msg: db "Hello, World!", '$'
修正后的完整代码
org 100h jmp start msg: db "Hello, World!", '$' ; 用$适配09h功能的结束要求 a: db 13 dup(0) ; 给目标字符串留足够空间,避免溢出 start: mov si, offset msg ; 加载源字符串地址到si lea di, a ; 加载目标地址到di call _make_str lea dx, a ; 把目标字符串地址传给dx mov ah, 09h int 21h mov ah, 0 int 16h ret _make_str: pusha _next: mov al, [si] mov [di], al inc si inc di cmp al, '$' ; 以$作为循环结束条件 jne _next popa ret
这样修改后,代码应该就能正常复制字符串并输出了~
内容的提问来源于stack exchange,提问作者Pantokrator
相关产品推荐
相关产品推荐

