鱼C论坛

 找回密码
 立即注册
查看: 124|回复: 10

关于第16章的字符映射例题

[复制链接]
发表于 2025-3-19 09:57:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 laocaiye 于 2025-3-19 11:22 编辑

第16章字符表映射例题,搞了半天,没搞明白自己的代码哪里有错。请看红色字体所述问题

assume cs:code

data segment
        db 13,29,46,78,124
data ends

code segment

start:                mov ax,data
                        mov ds,ax
                       
                        mov ax,code
                        mov cs,ax  

                        mov si,0  ;单步调试运行到此处就出问题,显示 ??? [bx+si]  也看不明白什么意思。感到莫名其妙
                        mov di,0
                       
                        mov cx,5
               
                        call showbyte
                       
                        mov ax,4c00h
                        int 21h
                       
showbyte:        push ax
                        push bx
                        push es
                        mov ax,0b800h
                        mov es,ax
                        jmp short s
                        table db '0123456789ABCDEF'

        s:                mov al,ds:[si]    ;循环读取数据段数据
                        mov ah,al
                        shr ah,1
                        shr ah,1
                        shr ah,1
                        shr ah,1
                        and al,00001111b    ;ah保存了数据的高4比特位,al保存了低4比特位
                       
                        mov bl,ah
                        mov bh,0
                        mov ah,table[bx]
                        mov es:[160*12+40*2+di],ah    ;把al中数据对应的table中的字节码保存到显示段[160*12+40*2+di]处
                        mov byte ptr es:[160*12+40*2+di].1,2    ;设置颜色为蓝色
                       
                        add di,2
                       
                        mov bl,al
                        mov bh,0
                        mov al,table[bx]
                        mov es:[160*12+40*2+di],al;把al中数据对应的table中的字节码保存到显示段[160*12+40*2+di]
                        mov byte ptr es:[160*12+40*2+di].1,2    ;设置颜色为蓝色
                       
                        add di,2
                        inc si
                        loop s
                       
                        pop es
                        pop bx
                        pop ax
                        ret
                       
code ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-3-19 09:57:23 | 显示全部楼层
你的代码存在几个问题,可能导致调试时出现 ??? 的情况。以下是一些关键问题和改进建议:

1. `mov ax, data` 需要 `mov ax, @data`  
在 `start` 处,你使用了 `mov ax, data`,但 `data` 是一个段名,应该使用 `mov ax, @data` 来正确加载数据段地址。

2. `mov cs, ax` 不能直接修改 CS  
在 `start` 处,你尝试 `mov cs, ax`,但 `CS` 不能直接修改。通常,代码段的地址已经由 `assume cs:code` 设定,不需要手动修改。

3. `mov al, ds:` 语法错误  
在 `showbyte` 过程的 `s` 处,你写了 `mov al, ds:`,但这里缺少偏移地址,应该是 `mov al, ds:[si]`。

4. `mov es:, ah` 语法错误  
在 `showbyte` 过程,你写了 `mov es:, ah`,但 `es:` 需要一个偏移地址,应该是 `mov es:[di], ah`。

5. `table` 需要放在 `code segment` 之外或使用 `db` 定义  
`table db '0123456789ABCDEF'` 直接放在 `showbyte` 过程内是不正确的,应该放在 `data segment` 或 `code segment` 的合适位置。

修正后的代码示例  
assume cs:code, ds:data

data segment
    db 13,29,46,78,124
data ends

code segment

start:      
    mov ax, @data
    mov ds, ax

    mov si, 0  
    mov di, 0
    mov cx, 5

    call showbyte

    mov ax, 4c00h
    int 21h

showbyte:   
    push ax
    push bx
    push es

    mov ax, 0b800h
    mov es, ax

    jmp short s

table db '0123456789ABCDEF'

s:  
    mov al, ds:[si]  
    mov ah, al
    shr ah, 4
    and al, 0Fh  

    mov bl, ah
    mov bh, 0
    mov ah, table[bx]
    mov es:[di], ah  
    mov byte ptr es:[di+1], 2  

    add di, 2

    mov bl, al
    mov bh, 0
    mov al, table[bx]
    mov es:[di], al  
    mov byte ptr es:[di+1], 2  

    add di, 2
    inc si
    loop s

    pop es
    pop bx
    pop ax
    ret

code ends
end start

总结  
  • `mov ax, data` 改为 `mov ax, @data`
  • 不能直接 `mov cs, ax`
  • `mov al, ds:` 改为 `mov al, ds:[si]`
  • `mov es:, ah` 改为 `mov es:[di], ah`
  • `table` 需要正确放置


这样修改后,你的代码应该可以正确运行,并在屏幕上显示字符映射的结果。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-19 10:11:07 | 显示全部楼层
那就奇怪了,为何以前都这样写没问题呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-19 10:11:22 | 显示全部楼层
laocaiye 发表于 2025-03-19 10:11
那就奇怪了,为何以前都这样写没问题呢?


你的疑问很合理,实际上,很多汇编代码在不同的编译器、汇编器(如 MASM、TASM、NASM)以及不同的运行环境(如 DOS 真实模式、保护模式)下可能会有不同的行为。以下是一些可能的原因,解释为什么以前的代码能运行,而现在可能会出问题:

### 可能的原因:
1. **汇编器版本不同**  
   - 以前的代码可能是在不同版本的 MASM 或 TASM 下编译的,而不同版本的汇编器可能会有不同的默认行为。例如,MASM 可能会自动解析 `mov ax, data`,而某些版本可能需要 `mov ax, @data`。

2. **运行环境不同**  
   - 以前的代码可能是在 DOS 真实模式下运行,而现在可能是在 DOSBox、Windows 兼容模式或其他模拟环境下运行,这些环境可能对段寄存器的初始化方式有所不同。

3. **CS 不能直接修改**  
   - 你的代码中 `mov cs, ax` 这一行是非法的,在 8086 及以上的 CPU 中,CS 不能直接用 `mov` 指令修改,必须使用 `jmp` 或 `call` 进行间接修改。如果以前的代码能运行,可能是因为:
     - 代码段已经正确设置,`mov cs, ax` 这行代码实际上没有执行。
     - 运行环境(如 DOS)自动忽略了这个错误。

4. **数据访问方式不同**  
   - `mov al, ds:` 这样的写法是不完整的,应该是 `mov al, ds:[si]` 或 `mov al, [si]`。如果以前的代码能运行,可能是因为:
     - 旧版本的汇编器自动推测了正确的偏移地址。
     - 代码段和数据段的默认设置使得 `ds:` 访问了正确的地址。

5. **table 的位置**  
   - `table db '0123456789ABCDEF'` 直接放在 `showbyte` 过程内是不规范的,应该放在 `data segment` 或 `code segment` 的合适位置。如果以前的代码能运行,可能是因为:
     - 旧版本的汇编器允许这种写法,并自动调整了数据位置。
     - 代码段的布局恰好使得 `table` 在正确的位置。

### 解决方案:
- **使用 `@data` 访问数据段**:`mov ax, @data`
- **不要直接修改 `CS`**,去掉 `mov cs, ax`
- **正确访问数据**,使用 `mov al, ds:[si]`
- **确保 `table` 在合适的位置**,放在 `data segment` 或 `code segment` 的末尾

如果你仍然遇到问题,可以尝试使用 `debug` 或 `DOSBox` 进行单步调试,看看具体是哪一行代码导致了错误。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-19 10:20:33 | 显示全部楼层
我一直就是使用DOSBOX,从开始学习就是按上传的代码格式写的,一直都没问题啊,怎么今天出这个毛病了。我昨天在VM中安装的MS-DOS,难道这也会有影响?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-19 10:20:48 | 显示全部楼层
laocaiye 发表于 2025-03-19 10:20
我一直就是使用DOSBOX,从开始学习就是按上传的代码格 ...


是的,在 **VM 中安装 MS-DOS** 可能会影响代码的运行,原因如下:  

### **1. DOSBox 与 真实 MS-DOS 的差异**  
DOSBox 是一个模拟器,它的行为与真实的 MS-DOS 可能有所不同,尤其是在以下方面:  
- **内存管理**:DOSBox 可能会自动初始化段寄存器,而 MS-DOS 需要手动设置。  
- **指令兼容性**:某些非法指令(如 `mov cs, ax`)在 DOSBox 可能不会报错,但在 MS-DOS 下会导致异常。  
- **默认段寄存器**:DOSBox 可能会自动设置 `DS`,而 MS-DOS 可能不会。  

### **2. `mov cs, ax` 可能导致问题**  
在 **8086 及以上的 CPU** 中,**CS 不能直接修改**,必须使用 `jmp` 或 `call` 进行间接修改。例如:  
mov ax, new_code_segment
push ax
retf
如果你的代码在 DOSBox 下运行正常,但在 MS-DOS 下出错,可能是因为 DOSBox **容忍了这个错误**,而 MS-DOS **严格执行了 CPU 规则**。  

### **3. `mov ax, data` 可能的影响**  
在 MS-DOS 下,`mov ax, data` 可能不会正确加载数据段地址,建议改为:  
mov ax, @data
mov ds, ax
DOSBox 可能会自动修正这个问题,而 MS-DOS 可能不会。  

### **4. `table` 的位置**  
你的 `table db '0123456789ABCDEF'` 直接放在 `showbyte` 过程内,这在某些汇编器下可能会导致问题。建议将 `table` 放在 `data segment` 或 `code segment` 的末尾。  

---

### **如何验证?**  
1. **在 DOSBox 和 MS-DOS 下分别运行**,看看是否有不同的错误信息。  
2. **使用 `debug` 进行单步调试**,检查 `CS`、`DS`、`SI`、`DI` 的值是否正确。  
3. **尝试去掉 `mov cs, ax`**,看看是否仍然出错。  

如果你仍然遇到问题,可以提供具体的错误信息,我可以帮你进一步分析!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-19 10:26:51 | 显示全部楼层
和机器人实在说不明白。我压根就没使用MS-DOS运行代码,我是用DOSBOX运行的代码,以前就是用mov ax,data   mov ds,ax这种形式写的,一直都没问题,今天居然出现这个奇葩问题。  看来AI代替人,真的不可能。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-19 10:27:04 | 显示全部楼层
laocaiye 发表于 2025-03-19 10:26
和机器人实在说不明白。我压根就没使用MS-DOS运行代码 ...


你的困惑完全可以理解,既然你一直在 **DOSBox** 运行代码,并且以前 `mov ax, data` 这种写法没有问题,而今天突然出错,那可能的原因有以下几种:  

### **可能的原因分析**  

#### **1. DOSBox 配置是否发生了变化?**  
- 你可以检查 `dosbox.conf` 配置文件,看看是否有改动,比如 **内存分配** 或 **CPU 模拟模式** 是否不同。  
- 试试 **重启 DOSBox**,或者 **恢复默认配置** 运行代码。  

#### **2. 代码是否有无意的改动?**  
- 你可以对比一下 **以前能运行的代码** 和 **现在的代码**,看看是否有细微的改动,比如 **段定义、变量名、指令顺序** 等。  
- 你可以尝试 **用旧代码重新编译运行**,看看是否仍然出错。  

#### **3. 汇编器(MASM/TASM)是否不同?**  
- 你以前用的汇编器版本和现在是否一致?  
- 试试 `MASM 5.0` 和 `MASM 6.11`,或者 `TASM`,看看是否有不同的行为。  

#### **4. DOSBox 是否有兼容性问题?**  
- 你可以尝试 **换一个 DOSBox 版本**(比如 `DOSBox-X` 或 `DOSBox SVN`),看看是否仍然出错。  
- 也可以尝试 **在 VM 里的 MS-DOS 运行**,看看是否有相同的问题。  

#### **5. 代码段和数据段的加载是否正确?**  
- 你可以在 `mov ds, ax` 之后,**用 `debug` 检查 DS 的值**,看看是否正确指向 `data segment`。  
- 试试 **手动设置 `DS`**,比如:  
mov ax, @data
  mov ds, ax
  这样可以确保 `DS` 正确指向数据段。  

---

### **如何排查?**  
1. **重启 DOSBox,恢复默认配置**,看看是否仍然出错。  
2. **用 `debug` 检查 `DS` 的值**,看看是否正确。  
3. **尝试用旧代码重新编译运行**,看看是否仍然出错。  
4. **换一个 DOSBox 版本或汇编器版本**,看看是否有不同的结果。  

如果你仍然遇到问题,可以提供 **具体的错误信息**,我可以帮你进一步分析!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-3-19 11:04:03 From FishC Mobile | 显示全部楼层
下面这两句是谁教的?
mov ax,code
mov cs,ax
        这个世界除了阁下,恐怕不会再有第二个人会这么写代码!
         直接删除。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-19 11:21:46 | 显示全部楼层
经过重新安装DOSBOX,我的代码根本就问题,应该是软件出了问题,但是原因不明。根本就不是小鱼机器人说的什么乱七八糟解答,机器人回答问题真让人崩溃。另外使用 mov ax,@data形式压根就是错误。还有:shr ah,4是根本性错误,循环移位,必须把次数放在cl中。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-3-19 14:17:51 | 显示全部楼层
jackz007 发表于 2025-3-19 11:04
下面这两句是谁教的?

        这个世界除了阁下,恐怕不会再有第二个人会这么写代码!

因为我软件问题,在执行前两句代码后就开始出错,我是在调试过程中,增加了这么两句。因为也没查出来什么问题,所以在发布问题时就忘记删除了。发现是软件问题后,就删除了,程序运行正常。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-3-31 08:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表