鱼C论坛

 找回密码
 立即注册
查看: 69|回复: 14

6.1有个检查点代码我不是很能理解。

[复制链接]
发表于 昨天 03:54 | 显示全部楼层 |阅读模式

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

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

x
assume cs:codesg

codesg segment
       dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
          
start: mov ax,0
       mov ds,ax
           mov bx,0
          
           mov cx,8
        s: mov ax,[bx]
       
           mov cs:[bx],ax
          
           add bx,2
           loop s
          
           mov ax,4c00h
           int 21h
          
codesg ends
end start
z
在这个代码里,我们知道空间是申请去了cs的空间,那么dw申请的8个位置会直接放在cs:0-16这个空间内,但是后面给ds赋值的时候,ds给予了0 那么当我提取数据的时候,就是只想ds:[bx] 去赋值给ax ,然后ax 再把值给cs:[bx]。这块我有个人的疑问,ds和cs是不同的空间,开始数据申请存放的空间到底是在cs里,还是ds里,还是ds被纳入了cs的空间内,如果不是这块是什么区分的概念?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 03:57 | 显示全部楼层
理解你的困惑,关键在于区分代码段(CS)和数据段(DS)在内存中的关系。以下是详细解释:

### 核心问题分析
1. **内存分配**:
   - `dw` 定义的8个字数据(16字节)存放在 `codesg` 段开头(偏移地址 `0~0Fh`)。
   - 程序加载后,`codesg` 段被操作系统分配到内存的某个位置,**CS 寄存器指向这个段的起始地址**。

2. **段寄存器的独立性**:
   - `mov ds, ax`(ax=0)将 **DS 设为 0000h**(指向内存最低端,通常是中断向量表)。
   - **CS 和 DS 指向不同内存区域**:
     - `CS:[bx]` → 你的程序代码/数据区
     - `DS:[bx]` → 内存0000:0000处(系统区域)

3. **数据流向**:
  
  1. s:  mov ax, [bx]      ; 从 DS:0 读取数据(中断向量表的内容)
  2.        mov cs:[bx], ax   ; 将数据写入 CS:0(覆盖原 dw 定义的数据)
  3.        add bx, 2
  4.        loop s
复制代码

   - 这会将**中断向量表的前16字节**复制到 `codesg` 段开头,覆盖你定义的 `0123h, 0456h...` 等数据。

### 内存示意图
  1. (假设 CS=2000h, DS=0000h)

  2. CS 段(你的程序)        DS 段(系统内存)
  3. +----------+           +----------+
  4. | 0123h    | <--CS:0   | 中断向量 | <--DS:0
  5. | 0456h    |           | 表数据   |
  6. | ...      |           | ...      |
  7. +----------+           +----------+
复制代码

- 执行后:`CS:0~0Fh` 的内容被替换为 `0000:0000~000Fh` 的内容。

### 关键总结
1. **数据存储位置**:`dw` 数据在 `CS` 段开头(代码段内)。
2. **段寄存器作用**:
   - `DS=0` 时,`[bx]` 访问的是 **0000h:bx(系统内存)**。
   - `CS:[bx]` 访问的是 **你的代码段**。
3. **复制操作的本质**:将系统中断向量表的前16字节复制到你的程序开头,覆盖原始数据。

### 为何这样设计?
这个程序实际是一个**自修改程序**(运行时修改自身代码区数据),但此处用于演示段寄存器的独立性。实际应用中直接覆盖代码段数据是危险的(可能导致崩溃)。

理解要点:**CS 和 DS 是独立寻址的,指向不同的物理内存区域**。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 04:17 | 显示全部楼层
那这两个段寄存器,在cs段创建dw定义了数据以后,寄存器指向的物理位置是一样的么?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 04:18 | 显示全部楼层
SmileFable 发表于 2025-06-29 04:17
那这两个段寄存器,在cs段创建dw定义了数据以后,寄存 ...


你的问题触及了8086内存寻址的核心机制。关键在于:**CS和DS指向不同的物理内存区域**,即使程序定义了数据在代码段中。以下是详细解释:

### 关键概念图解
(假设操作系统加载程序时 CS=2000h)

| 寄存器 | 指向位置         | 物理地址计算         | 实际内容                 |
|--------|------------------|----------------------|--------------------------|
| CS     | 代码段起始       | 2000h × 16 = 20000h  | 你的程序代码 + dw 定义的数据 |
| DS     | 内存绝对0地址    | 0000h × 16 = 00000h  | 系统中断向量表           |

### 具体分析你的代码
1. **数据存储位置**:
  
  1. dw 0123h,0456h,... ; 这些数据存放在 CS:0~CS:0Fh
复制代码

   - 物理地址:`20000h~2000Fh`

2. **数据访问方式**:
  
  1. mov ds,0       ; DS 现在指向 0000:0000 (物理地址00000h)
  2.    mov bx,0
  3.    mov ax,[bx]    ; 读取的是 DS:BX = 00000h 处的系统数据
  4.    mov cs:[bx],ax ; 写入到 CS:BX = 20000h 处
复制代码

   - 这里发生了**跨段覆盖**:把系统内存(DS)的数据复制到代码段(CS)

### 为什么物理地址不同?
8086物理地址计算公式:  
**物理地址 = 段寄存器 × 16 + 偏移地址**

在你的代码中:
- 当访问 `[bx]` 时:
  - 使用 DS 段:`DS×16 + BX = 0×16 + 0 = 00000h`
- 当访问 `cs:[bx]` 时:
  - 使用 CS 段:`CS×16 + BX = 2000h×16 + 0 = 20000h`

### 重要结论
1. **段寄存器决定内存窗口**:
   - CS 和 DS 像两个不同的"镜头"
   - 相同偏移地址 [bx] 透过不同"镜头"看到完全不同的物理位置

2. **数据隔离**:
  
  1. dw 数据 ; // 永远存在 CS 段
  2.    mov [bx],ax ; // 默认操作 DS 段(除非加段前缀)
复制代码


3. **你的代码实际效果**:
   - 把中断向量表(00000h~0000Fh)的前16字节
   - 复制覆盖到代码段开头(20000h~2000Fh)
   - 原始定义的 `0123h,0456h...` 数据被覆盖丢失

### 正确理解姿势
把内存想象成一本大书:
- CS 是标着"程序章"的书签
- DS 是标着"系统数据章"的书签
- `[bx]` 是页码,但书签不同指向的章节完全不同

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 05:56 | 显示全部楼层
检查点6.2 sp为什么要给36,直接给2不行么? 在循环里,栈一次push 进去2个字节数据,马上就pop出来了,我看答案给了36 我不知道为什么
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 05:59 | 显示全部楼层
SmileFable 发表于 2025-06-29 05:56
检查点6.2 sp为什么要给36,直接给2不行么? 在循环里 ...


你的问题涉及栈指针SP的初始设置,核心在于**栈空间的计算**和**8086栈操作特性**。以下是详细分析:

### 关键原理
1. **栈增长方向**:8086中栈**从高地址向低地址**增长(push时SP先减2,再存数据)。
2. **栈指针初始值**:SP必须指向**栈空间最高地址的下一个字节**(即栈空间末尾+1),确保第一个push操作能正确使用预留空间。
3. **栈空间计算**:需根据代码段中预留的栈空间大小确定SP。

### 以你的代码为例(修正版)
  1. assume cs:codesg
  2. codesg segment
  3.     dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h  ; 8个字=16字节 (偏移0~15)
  4.     dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0  ; 16个字=32字节 (栈空间,偏移16~47)

  5. start:
  6.     mov ax, cs
  7.     mov ss, ax      ; SS=CS (栈段与代码段重合)
  8.     mov sp, 36      ; 关键点:SP=36? 还是48?

  9.     mov ax, 0
  10.     mov ds, ax      ; DS=0 (指向中断向量表)
  11.     mov bx, 0
  12.     mov cx, 8
  13. s:  push [bx]       ; 从DS:0~15取数据入栈
  14.     pop cs:[bx]     ; 出栈到CS:0~15 (覆盖原始dw数据)
  15.     add bx, 2
  16.     loop s

  17.     mov ax,4c00h
  18.     int 21h
  19. codesg ends
  20. end start
复制代码


### SP=36还是48?看栈空间计算
- **数据区**:`dw 0123h,...` → **16字节**(偏移0~15)
- **栈空间**:`dw 0,0,...` → **32字节**(偏移16~47)
- **栈顶初始位置**:必须 = 栈空间结束地址 + 1  
  `SP = 16(数据区大小) + 32(栈空间大小) = 48`

### 为什么你看到SP=36?
可能因栈空间定义不同:
- 若栈空间为 **10个字(20字节)**:
  1. 数据区:16字节 (0~15)
  2.   栈空间:20字节 (16~35)
  3.   SP = 16 + 20 = 36  ; 此时SP=36正确
复制代码

- 但你的代码中栈空间是**16个字(32字节)**,  
  正确值应为 **SP=48**(16+32)。

### 直接SP=2为什么不行?
1. **破坏代码风险**:  
   SP=2时,栈顶指向代码段偏移2(即`0456h`数据位置)。  
   push操作会覆盖`CS:0~2`的数据(破坏程序)。
   
2. **未使用预留栈空间**:  
   预留的32字节栈空间(偏移16~47)完全未被使用。

### 正确结论
- **SP必须匹配预留栈空间大小**:  
  `SP = 数据区大小 + 栈空间大小`
- **你的代码应设SP=48**(因栈空间=32字节)  
  若栈空间=20字节,则SP=36正确。

### 操作演示(SP=48时)
| 步骤 | SP变化 | 操作说明          | 栈空间使用范围 |
|------|--------|-------------------|----------------|
| 初始 | 48     | 栈顶指向安全边界  | 未使用         |
| push | 46     | 数据存入CS:46~47  | 47~46 (高→低)  |
| pop  | 48     | 从CS:46~47取数据  | 恢复初始状态   |

**最终效果**:安全将中断向量表数据复制到代码段开头,避免覆盖关键代码。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 06:14 | 显示全部楼层
   SP=2时,栈顶指向代码段偏移2(即`0456h`数据位置)。  
   push操作会覆盖`CS:0~2`的数据(破坏程序)。

push完 pop 然后 栈里本来就是空的 再次push pop,栈里不会放东西啊,怎么会覆盖?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 06:15 | 显示全部楼层
SmileFable 发表于 2025-06-29 06:14
SP=2时,栈顶指向代码段偏移2(即`0456h`数据位置)。 ...


你的观察非常敏锐!确实在循环中每次push后立即pop,理论上栈空间应该被复原。但关键在于**push操作本身会写入内存**,即使立即pop,也会在瞬间覆盖数据。让我用详细步骤解释:

### 以SP=2为例的操作流程
(假设CS=2000h, SS=2000h)
  1. 初始状态:
  2.   SP=2 (指向20002h)
  3.   CS:0~15内存:0123h,0456h,0789h... (原始数据)

  4. 第一次循环:
  5.   push [0] 操作:
  6.     1. SP=SP-2 → SP=0
  7.     2. 将DS:0处的字(中断向量表内容)写入SS:SP(20000h)
  8.        → 此时20000h处的0123h被覆盖为中断向量值

  9.   pop cs:[0] 操作:
  10.     1. 从SS:SP(20000h)读取数据 → 读取的是刚写入的中断向量值
  11.     2. 写入CS:0 → 覆盖目标位置
  12.     3. SP=SP+2 → SP=2

  13. 表面看SP复原了,但内存发生了不可逆变化!
复制代码


### 关键破坏点
1. **push写入瞬间**:
   - 当SP=0时,push将数据写入CS:0(20000h)
   - **原始数据0123h被永久覆盖**(即使pop取走数据,内存值已改变)

2. **数据流污染**:
   - 第二次push时:
     - 写入位置:CS:0(但此时CS:0已是中断向量值)
   - pop操作将把这个"被污染的值"复制到CS:2
   - 原始数据链被破坏

### 正确方案(SP=36/48)的优势
  1. 初始状态:
  2.   SP=36 → 指向栈空间末尾(20024h)
  3.   栈空间:20010h~20023h (安全区域)

  4. push [0] 操作:
  5.   SP=34 → 数据写入20022h~20023h (未使用区域)
  6. pop cs:[0] 操作:
  7.   从20022h~20023h取数 → 写入CS:0
  8.   SP恢复36
复制代码

- **完全隔离**:栈操作只在预留的20010h~20023h区间进行
- **原始数据保护**:CS:0~15的数据仅在pop时被**主动覆盖**,不会被意外破坏

### 为什么"空栈"仍有风险?
- push/pop不是原子操作:写入内存发生在pop之前
- 内存覆盖是即时且不可逆的,即使只存在几纳秒
- 在多线程环境(虽然8086没有)或中断发生时可能引发严重问题

### 结论
虽然SP=2时程序可能能运行(在8086实模式下),但它:
1. 破坏了原始数据完整性
2. 违背了栈空间隔离的设计原则
3. 存在潜在风险(如中断发生在push后pop前)

因此必须设置SP指向预留栈空间末端,确保栈操作只在安全区域进行。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 06:18 | 显示全部楼层
这个栈的覆盖还是不是很了解,我debug的时候 sp的数值也只是在26,24之间还会切换,并没有走到24以下的空间,如果SP=2有风险,那么我用SP=4 是不是就可以没有风险了,因为每次循环 push pop的时候,数字总会在4和2之间来回切换。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 06:20 | 显示全部楼层
SmileFable 发表于 2025-06-29 06:18
这个栈的覆盖还是不是很了解,我debug的时候 sp的数值 ...


你的思考非常有价值!让我们通过详细的内存操作步骤来分析 SP=4 的情况,你会清晰看到问题所在。假设代码段从 20000h 开始:

### 内存初始状态 (CS=2000h, SS=2000h)
| 地址   | 偏移 | 原始数据 |
|--------|------|----------|
| 20000h | 0    | 0123h    |
| 20002h | 2    | 0456h    | ← 你关注的区域
| 20004h | 4    | 0789h    |
| ...    | ...  | ...      |

### 当 SP=4 时的操作流程
(以第一次循环为例,bx=0)

#### 步骤1: `push `
1. SP = SP - 2 = 2  
   (栈顶现在指向 20002h)
2. 将 DS:0(中断向量值,假设为 ABCDh)写入 SS:SP(20002h)  
   **结果**:20002h 处的原始值 0456h 被覆盖为 ABCDh

此时内存变化:
| 地址   | 偏移 | 当前值 |
|--------|------|--------|
| 20000h | 0    | 0123h  |
| 20002h | 2    | ABCDh  | ← 已被覆盖!
| 20004h | 4    | 0789h  |

#### 步骤2: `pop cs:`
1. 从 SS:SP(20002h) 读取值 → 读取到 ABCDh
2. 写入 CS:0(20000h) → 覆盖 0123h
3. SP = SP + 2 = 4

最终状态:
| 地址   | 偏移 | 当前值 |
|--------|------|--------|
| 20000h | 0    | ABCDh  | ← 期望的中断向量值
| 20002h | 2    | ABCDh  | ← 被污染的残留值!
| 20004h | 4    | 0789h  |

### 关键问题分析
1. **数据污染残留**:
   - 20002h 处的 ABCDh 会**一直保留**在内存中
   - 这不是"临时覆盖",而是**永久性覆盖**

2. **后续循环的连锁反应**:
   第二次循环 (bx=2):
   - `push `:将 DS:2 的值写入 20000h(覆盖 ABCDh)
   - `pop cs:2`:将 20000h 的值写入 20002h(覆盖残留的 ABCDh)

   结果:
   - CS:0 被二次覆盖
   - CS:2 获得的是**被污染后的值**而非原始中断向量值

### 为什么 SP=36 安全?
(假设栈空间在 20010h~20023h)

操作流程:
- `push `:写入 **20022h**(栈空间内)
- `pop cs:0`:从 **20022h** 读取
- 内存影响:
  - 20000h~2000Fh(数据区):仅在 pop 时被**主动覆盖**
  - 20010h~20023h(栈空间):push/pop 临时使用
  - **数据区和栈空间完全隔离**

### 终极结论
1. **SP=4 的问题**:
   - push 操作会永久覆盖 20002h 处的数据
   - 残留值会影响后续操作(特别是当 bx=2 时)
   - 破坏原始数据的完整性

2. **安全栈空间的本质要求**:
  
  1. [数据区] [空闲隔离带] [栈空间]
  2.    ↑           ↑         ↑
  3.    CS:0      安全距离   SP初始位置
复制代码

   - 栈操作必须在**专门预留的区域**进行
   - 这个区域不能与有效数据区重叠

3. **为何你看到 SP 在 24~26 跳动**:
   - 这是正常现象,说明栈操作被限制在安全区域内
   - SP=24 时指向栈空间内最低地址
   - SP=26 时指向更高地址
   - **永远不会触及 0~15 的数据区**

### 实践建议
下次调试时,在 push 后立即查看内存:
  1. -g (运行到push后)
  2. -d 2000:0 f ; 查看数据区
  3. -d 2000:20 2f ; 查看栈空间
复制代码

你会直观看到:
- SP=4 时:数据区中间出现异常值
- SP=36 时:只有栈空间有变化,数据区保持完整直到被主动覆盖

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 06:24 | 显示全部楼层
SP=36我觉得也没有必要,毕竟只有前16有数据,后面dw的数据都是0,如果说要保留数据完全不污染,栈顶的设计是不是要大于dw请求cs段空间的数值再加2? 这样dw定义的数据放在ss中永远不会污染,而多余出来的2空间用来push和pop?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 06:27 | 显示全部楼层
SmileFable 发表于 2025-06-29 06:24
SP=36我觉得也没有必要,毕竟只有前16有数据,后面dw ...


你的思考方向完全正确!确实**不需要预留整个栈空间**,只要确保栈顶在数据区之外即可。让我们优化这个设计:

### 最小安全栈顶设计原则
1. **核心公式**:  
   `初始SP = 数据区大小 + 2`  
   (+2是为了给第一个push操作留出空间)

2. **你的案例具体计算**:  
   - 数据区:8个字 = **16字节** (偏移0~15)  
   - 最小安全SP:16 + 2 = **18(12h)**  

### 优化后的代码实现
assume cs:codesg
codesg segment
    ; 数据区 (16字节)
    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
   
    ; 仅预留2字节缓冲区 (实际只需1字空间)
    dw 0   ; 偏移16~17 (关键缓冲区)

start:
    mov ax, cs
    mov ss, ax
    mov sp, 18      ; 指向缓冲区末尾+1 (12h)

    mov ax, 0
    mov ds, ax
    mov bx, 0
    mov cx, 8
s:  push
    pop cs:
    add bx, 2
    loop s

    mov ax,4c00h
    int 21h
codesg ends
end start

### 为什么SP=18足够安全?
1. **内存布局**:
   - 0~15(0Fh):原始数据区
   - 16~17(10h~11h):2字节缓冲区
   - SP=18(12h):初始栈顶

2. **操作过程**(以第一次循环为例):
   - `push `:
     - SP=18-2=**16**(10h)  // 指向缓冲区起始
     - 将中断向量值写入 **CS:16~17**(10h~11h)
   - `pop cs:`:
     - 从 **CS:16~17**(10h~11h) 读取值
     - 写入CS:0目标位置
     - SP=16+2=**18**(恢复)

3. **隔离效果**:
   - 数据区(0~15):仅被pop**主动覆盖**
   - 缓冲区(16~17):临时存储push的值
   - **零污染**:push操作不会触及0~15区域

### 对比不同SP设置的风险
| SP值 | 数据安全 | 栈操作区域       | 风险               |
|------|----------|------------------|--------------------|
| 2    | 高危     | 数据区内部       | 永久覆盖原始数据   |
| 4    | 中危     | 部分数据区       | 残留污染           |
| 18   | 安全     | 专用缓冲区       | 完全隔离           |
| 36   | 安全     | 过大预留空间     | 浪费内存但安全     |

### 为什么教材用SP=36?
1. **教学目的**:强调栈空间概念
2. **错误容忍**:防止学生忘记恢复SP
3. **清晰展示**:大空间便于调试观察
4. **历史习惯**:早期示例代码的延续

### 最佳实践建议
1. **最小缓冲区法**(推荐):  
  
  1. ; 数据区
  2.    dw ...
  3.    ; 仅1字缓冲区
  4.    dw 0  
  5.    mov sp, 数据区大小+2
复制代码


2. **动态计算**(更专业):
  
  1. mov sp, (offset $) + 2  ; $=当前地址
复制代码


3. **绝对安全法则**:  
   **SP初始值必须 > 数据区最大偏移+1**

最终结论:你的优化思路完全可行,SP=18(12h)是这个场景下的最精简安全方案!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 06:28 | 显示全部楼层
好的,思考以后了解了问题本质,多谢答疑。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 06:29 | 显示全部楼层
SmileFable 发表于 2025-06-29 06:28
好的,思考以后了解了问题本质,多谢答疑。


不客气!你的思考非常深入,能抓住"数据隔离"这个核心本质非常难得。关于栈和段寄存器的使用,我再帮你总结几个关键点:

### 8086内存安全三原则
1. **栈顶隔离**:SP必须指向数据区/代码区之后
   - 公式:SP ≥ 数据区结束偏移 + 2
   - 你优化的SP=18就是完美实践

2. **段寄存器分工**:
   - CS专管代码执行
   - DS专管数据读取
   - SS专管栈操作
   - 除非必要,不要跨段访问

3. **栈操作本质**:
  
  1. push src  ; 等效于:
  2.              ; sub sp, 2
  3.              ; mov , src
  4.    pop dest  ; 等效于:
  5.              ; mov dest,
  6.              ; add sp, 2
复制代码

   每次push都会在内存留下"痕迹",必须确保这个痕迹落在安全区

### 调试技巧
下次遇到类似问题时:
1. 用`d cs:0`查看数据区
2. 用`r`查看寄存器状态
3. 单步执行`t`并观察:
   - push后立即查看内存变化
   - 重点检查SP指向的内存地址内容

你的分析能力已经超越多数初学者,继续保持这种"揪住本质"的思考方式!有问题随时来问~

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 9 小时前 | 显示全部楼层
cs和ds是两个独立的段寄存器,互不包含。

你用dw声明的数据是在codesg段(和cs有关)。

只有当ds和cs都指向codesg段时,ds:[bx]才会访问到你声明的数据。

mov ds,0这样写,ds:[bx]访问的是物理内存0区,不是你的codesg段。

ds不会自动等于cs,也不会“包含”cs的空间。

要访问你声明的数据,应该让ds等于codesg段地址,比如:

  1. mov ax, codesg
  2. mov ds, ax
复制代码

这样ds:[bx]才能访问到你的dw数据。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-30 13:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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