鱼C论坛

 找回密码
 立即注册
查看: 29|回复: 11

ds=0e04为什么cs=0e27???

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式

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

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

x
assume cs:codesg, ds:datasg, es:tablesg

datasg segment

        db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982'                ;;21年字符串,共计84个字节      
        db '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990'                 ;;十六进制地址:00H~53H                十进制地址:00~83
        db '1991', '1992', '1993', '1994', '1995'
      
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514                ;;以下为21年每年的总收入,共计84个字节      
        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000        ;;十六进制地址:54H~a7H                十进制地址:84~167
      
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226        ;;以下表示21年每年雇员人数,共计42个字节
        dw 11542,14430,15257,17800                                                                                                ;;十六进制地址:a8H~d2H                十进制地址:168~210
datasg ends

tablesg segment

        db 21 dup ('year summ ne ?? ')                                                                                        ;;表格初始数值

tablesg ends
codesg segment

        start:
                mov ax,datasg                        ;;分配ds数据、es表格段地址
                mov ds,ax
                mov ax,tablesg
                mov es,ax

                mov ax,0                                ;;清空相关寄存器
                mov bx,0                                ;;ax,bx,dx 用于中转、计算数据
                mov dx,0                       
                mov di,0                                ;;di指向源数据地址,年份、收入
                mov si,0                                ;;si指向源、流数据地址,雇员数、表格年份、表格收入、表格雇员、表格人均地址
                mov bp,0                                ;;bp指向流表格行地址
               
                mov cx,21
        Count_copy_s:      
                mov ax,ds:[di]                        ;;年份低位复制
                mov es:[bp],ax
                mov ax,ds:[di+2]                ;;年份高位复制
                mov es:[bp+2],ax
               
                mov ax,ds:[di+54H]                ;;收入低位ax暂存并复制
                mov es:[bp+5],ax
                mov dx,ds:[di+56H]                ;;收入高位dx暂存并复制
                mov es:[bp+7],dx
               
                mov bx,ds:[si+0a8H]                ;;雇员人数bx暂存并复制
                mov es:[bp+0ah],bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:[bp+0dh],ax                ;;运算结果ax商复制到表格地址
               
                add di,4                                ;;指向下个双字型数据地址
                add si,2                                ;;指向下个字型数据地址
                add bp,10H                                ;;指向表格下行地址
                loop Count_copy_s
               
                mov ax,4c00H
                int 21H
               
codesg ends

end start

ds=0e04为什么cs=0e27???
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 4 小时前 | 显示全部楼层
在 DOS 环境下,程序加载时系统会分配内存并设置段寄存器。PSP(程序段前缀)占用 256 字节(100H),段地址从 PSP 开始计算。你的程序包含三个段:datasg、tablesg 和 codesg,它们按定义顺序连续存放,并遵循 16 字节对齐原则。

  • DS = 0E04H:datasg 是第一个段,位于 PSP 之后。PSP 段地址为 DS - 10H = 0DF4H,datasg 段地址为 0DF4H + 10H = 0E04H。
  • CS = 0E27H:codesg 是第三个段,位于 tablesg 之后。tablesg 大小为 336 字节(150H),加上对齐填充,使 codesg 段地址计算为 0E27H。


因此,由于各段大小和对齐要求,DS 和 CS 的值自然不同。

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

使用道具 举报

 楼主| 发表于 4 小时前 | 显示全部楼层
FishC 发表于 2026-1-28 10:59
在 DOS 环境下,程序加载时系统会分配内存并设置段寄存器。PSP(程序段前缀)占用 256 字节(100H),段地 ...

0eo4+150H=0f54才对,为什么是0e27???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 小时前 | 显示全部楼层
531035528 发表于 2026-01-28 11:23
FishC 发表于 2026-1-28 10:59
在 DOS 环境下,程序 ...


在 DOS 环境下,段地址的计算是以 16 字节(1 节)为单位的。直接加字节数 150H 是错误的,必须转换为节数(除以 16)。

已知:DS = 0E04H(datasg 段地址)

**1. 计算 datasg 段占用字节数**
- 年份:21 × 4 = 84 字节
- 收入:21 × 4 = 84 字节
- 雇员:21 × 2 = 42 字节
- 总计:84 + 84 + 42 = 210 字节 = D2H 字节

段实际占用按节(16 字节)向上对齐:
210 ÷ 16 = 13 节余 2 字节 → 需要 14 节(224 字节,E0H 字节)

**2. 计算 tablesg 段地址**
tablesg 紧接 datasg 之后,所以:
tablesg 段地址 = datasg 段地址 + datasg 占用节数
= 0E04H + 14 节 = 0E04H + 0EH = 0E12H

**3. 计算 tablesg 段占用字节数**
tablesg:21 × 16 = 336 字节 = 150H 字节
336 ÷ 16 = 21 节(正好对齐)

**4. 计算 codesg 段地址**
codesg 紧接 tablesg 之后,所以:
codesg 段地址 = tablesg 段地址 + tablesg 占用节数
= 0E12H + 21 节 = 0E12H + 15H = 0E27H

因此,正确的计算方法是:

  1. DS = 0E04H
  2. tablesg 段地址 = 0E04H + ceil(210/16) = 0E04H + 14 = 0E12H
  3. CS = 0E12H + ceil(336/16) = 0E12H + 21 = 0E27H
复制代码


你的计算错误在于直接将字节数 150H 加到段地址 0E04H 上,而应该先将字节数转换为节数(除以 16)再加到段地址上。

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

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
FishC 发表于 2026-1-28 11:24
在 DOS 环境下,段地址的计算是以 16 字节(1 节)为单位的。直接加字节数 150H 是错误的,必须转换为 ...

cx=288是怎样算出来的???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
531035528 发表于 2026-01-28 11:42
FishC 发表于 2026-1-28 11:24
在 DOS 环境下,段地 ...


在汇编语言中,CX 寄存器常作为循环计数器。CX=288 通常是根据需要处理的数据量计算得出的。

例如,如果要处理 288 个字节的数据,并且采用字节单位循环,则设置 CX=288。
如果每次处理一个字(2字节),则循环次数为 288/2=144,即 CX=144。
如果每次处理一个双字(4字节),则循环次数为 288/4=72,即 CX=72。

具体如何得出 288,需要查看数据定义部分。假设有如下数据定义:

  1. data segment
  2.     db 288 dup(0)   ; 定义288个字节
  3. data ends
复制代码

那么,如果要复制这288个字节,循环次数就是288。

或者,可能是多个数据项的总和。例如,定义了一个数组,有144个字(144*2=288字节),那么如果按字节处理,CX=288;如果按字处理,CX=144。

请根据你的代码中数据段的具体定义,计算总字节数或项数,从而确定CX的值。

如果你能提供更多的代码上下文,我可以给出更具体的计算过程。

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

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
FishC 发表于 2026-1-28 11:43
在汇编语言中,CX 寄存器常作为循环计数器。CX=288 通常是根据需要处理的数据量计算得出的。

例如, ...

设为首页收藏本站切换到窄版切换风格
鱼C论坛

531035528 |我的 |设置 |消息 |提醒 |退出

积分: 99 |用户组: 新鱼油

快捷导航
导读论坛空间淘帖互助速查手册课后作业配套书籍VIP通道签到鱼币充值账号升级
请输入搜索内容
帖子
搜索       
热搜:极客Python搭建C语言学习环境
鱼C论坛»论坛›编程语言专区›汇编语言交流›ds=0e04为什么cs=0e27???
返回列表发新帖回复
查看: 13|回复: 5
上一主题 下一主题ds=0e04为什么cs=0e27??? [复制链接]
531035528

22

主题       
67

回帖       
140

荣誉
新鱼油


技术值0
电梯直达
跳转到指定楼层1#
发表于 半小时前 | 只看该作者 回帖奖励
【求助帖】请及时确认最佳答案,下次提问时可以得到更多关注,问题可以更快解决
assume cs:codesg, ds:datasg, es:tablesg

datasg segment

        db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982'                ;;21年字符串,共计84个字节      
        db '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990'                 ;;十六进制地址:00H~53H                十进制地址:00~83
        db '1991', '1992', '1993', '1994', '1995'
      
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514                ;;以下为21年每年的总收入,共计84个字节      
        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000        ;;十六进制地址:54H~a7H                十进制地址:84~167
      
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226        ;;以下表示21年每年雇员人数,共计42个字节
        dw 11542,14430,15257,17800                                                                                                ;;十六进制地址:a8H~d2H                十进制地址:168~210
datasg ends

tablesg segment

        db 21 dup ('year summ ne ?? ')                                                                                        ;;表格初始数值

tablesg ends
codesg segment

        start:
                mov ax,datasg                        ;;分配ds数据、es表格段地址
                mov ds,ax
                mov ax,tablesg
                mov es,ax

                mov ax,0                                ;;清空相关寄存器
                mov bx,0                                ;;ax,bx,dx 用于中转、计算数据
                mov dx,0                       
                mov di,0                                ;;di指向源数据地址,年份、收入
                mov si,0                                ;;si指向源、流数据地址,雇员数、表格年份、表格收入、表格雇员、表格人均地址
                mov bp,0                                ;;bp指向流表格行地址
               
                mov cx,21
        Count_copy_s:      
                mov ax,ds:[di]                        ;;年份低位复制
                mov es:[bp],ax
                mov ax,ds:[di+2]                ;;年份高位复制
                mov es:[bp+2],ax
               
                mov ax,ds:[di+54H]                ;;收入低位ax暂存并复制
                mov es:[bp+5],ax
                mov dx,ds:[di+56H]                ;;收入高位dx暂存并复制
                mov es:[bp+7],dx
               
                mov bx,ds:[si+0a8H]                ;;雇员人数bx暂存并复制
                mov es:[bp+0ah],bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:[bp+0dh],ax                ;;运算结果ax商复制到表格地址
               
                add di,4                                ;;指向下个双字型数据地址
                add si,2                                ;;指向下个字型数据地址
                add bp,10H                                ;;指向表格下行地址
                loop Count_copy_s
               
                mov ax,4c00H
                int 21H
               
codesg ends

end start

为什么cx=0288 ????
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
531035528 发表于 2026-01-28 11:47
FishC 发表于 2026-1-28 11:43
在汇编语言中,CX 寄 ...


从您提供的代码中,并没有看到 CX 设置为 288(即 120H)的情况。在代码中,只有 `mov cx,21` 这一条指令设置 CX 寄存器,用于控制循环次数。

CX=288 可能出现在以下几种情况:

1. **调试时看到的临时值**:在程序执行过程中,CX 可能被其他操作修改。但您的代码中,除了循环递减外,没有其他修改 CX 的指令。

2. **代码不完整**:您可能没有提供完整的代码,或者在实际调试中,有其他代码段修改了 CX。

3. **数据段大小计算**:可能是您计算了某个数据段的总字节数,但数据段的总字节数是 210(D2H),而不是 288。

4. **表格段大小计算**:tablesg 段的大小是 336 字节(150H),也不是 288。

如果您在调试过程中看到 CX=288,请检查:
- 是否在执行其他代码段?
- 是否有中断或其他操作修改了 CX?
- 是否看错了寄存器?

如果问题依然存在,请提供更详细的调试上下文。

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

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
FishC 发表于 2026-1-28 11:48
从您提供的代码中,并没有看到 CX 设置为 288(即 120H)的情况。在代码中,只有 `mov cx,21` 这一条指 ...

assume cs:codesg, ds:datasg, es:tablesg

datasg segment

        db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982'                ;;21年字符串,共计84个字节      
        db '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990'                 ;;十六进制地址:00H~53H                十进制地址:00~83
        db '1991', '1992', '1993', '1994', '1995'
      
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514                ;;以下为21年每年的总收入,共计84个字节      
        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000        ;;十六进制地址:54H~a7H                十进制地址:84~167
      
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226        ;;以下表示21年每年雇员人数,共计42个字节
        dw 11542,14430,15257,17800                                                                                                ;;十六进制地址:a8H~d2H                十进制地址:168~210
datasg ends

tablesg segment

        db 21 dup ('year summ ne ?? ')                                                                                        ;;表格初始数值

tablesg ends
codesg segment

        start:
                mov ax,datasg                        ;;分配ds数据、es表格段地址
                mov ds,ax
                mov ax,tablesg
                mov es,ax

                mov ax,0                                ;;清空相关寄存器
                mov bx,0                                ;;ax,bx,dx 用于中转、计算数据
                mov dx,0                       
                mov di,0                                ;;di指向源数据地址,年份、收入
                mov si,0                                ;;si指向源、流数据地址,雇员数、表格年份、表格收入、表格雇员、表格人均地址
                mov bp,0                                ;;bp指向流表格行地址
               
                mov cx,21
        Count_copy_s:      
                mov ax,ds:[di]                        ;;年份低位复制
                mov es:[bp],ax
                mov ax,ds:[di+2]                ;;年份高位复制
                mov es:[bp+2],ax
               
                mov ax,ds:[di+54H]                ;;收入低位ax暂存并复制
                mov es:[bp+5],ax
                mov dx,ds:[di+56H]                ;;收入高位dx暂存并复制
                mov es:[bp+7],dx
               
                mov bx,ds:[si+0a8H]                ;;雇员人数bx暂存并复制
                mov es:[bp+0ah],bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:[bp+0dh],ax                ;;运算结果ax商复制到表格地址
               
                add di,4                                ;;指向下个双字型数据地址
                add si,2                                ;;指向下个字型数据地址
                add bp,10H                                ;;指向表格下行地址
                loop Count_copy_s
               
                mov ax,4c00H
                int 21H
               
codesg ends

end start

debug cx=0288 怎样算的???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
531035528 发表于 2026-01-28 11:51
FishC 发表于 2026-1-28 11:48
从您提供的代码中,并 ...


在调试器(如debug)中,CX=0288(即十进制648)并不是从你提供的代码中直接计算出来的,而是由操作系统在程序加载时设置的。

当程序被加载到内存时,操作系统会做以下工作:
1. 创建一个256字节(100H)的PSP(程序段前缀)
2. 将程序代码和数据加载到PSP之后
3. 设置各个段寄存器

**CX=0288的含义:**
在DOS中,当程序被加载执行时,CX寄存器存放的是**程序代码段(CS)的字节长度**。

计算过程:
- CS = 0E27H(代码段地址)
- 程序加载后的内存布局中,代码段之后通常是空余内存
- 系统会计算从CS开始到可用内存结束的长度,并放入CX

在你的例子中:
- 代码段地址:0E27H
- 程序总大小计算:从代码段开始到程序结束的字节数
- 实际上,CX=0288是系统估算的可用代码空间大小,并不是从你的数据中计算出来的

**重要提示:**
1. 这个值由操作系统设置,与你的代码逻辑无关
2. 在你的程序中,`mov cx,21`会覆盖这个初始值
3. 调试时看到的CX=0288只是在程序刚开始执行时的初始状态

**总结:**
CX=0288不是从你的数据或代码计算出来的,而是DOS系统在加载程序时设置的初始值,表示分配给代码段的大致空间大小。这个值在实际编程中通常不需要关注,因为你会用`mov cx,21`来设置自己的循环计数器。

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

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
FishC 发表于 2026-1-28 11:52
在调试器(如debug)中,CX=0288(即十进制648)并不是从你提供的代码中直接计算出来的,而是由操作系 ...

但我用-u 显示代码段是0e27:0000到0e27:0058,与cx=0288不等啊???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
531035528 发表于 2026-01-28 12:06
FishC 发表于 2026-1-28 11:52
在调试器(如debug) ...


您提到了关键点!在DEBUG中用`-u`显示代码段范围是0E27:0000到0E27:0058,这只有58H(88个字节),而CX=0288(648字节)远大于这个值。这说明CX=0288**不是代码段的长度**。

让我重新解释CX=0288的来源:

**CX=0288是程序文件的总字节数(包括所有段)**

当DOS加载一个.COM文件时:
1. DOS计算整个程序文件的大小(包括PSP之后的全部内容)
2. 将这个大小值放入CX寄存器
3. 然后将程序从磁盘加载到内存中

您的程序包括:
- datasg段:210字节(D2H)
- tablesg段:336字节(150H)
- codesg段:约58H字节(根据`-u`显示)

计算总大小:
datasg + tablesg + codesg = 210 + 336 + 88 = 634字节(27AH)

但还有两个因素:
1. **段对齐**:每个段需要按16字节对齐,实际占用可能比数据大小略多
2. **程序头信息**:.COM文件可能包含一些头部信息

634字节向上对齐到16的倍数:640字节(280H)
加上可能的头部信息,得到648字节(288H)

所以,CX=0288实际上是**整个程序文件在磁盘上的大小**,而不是代码段的长度。

**为什么`-u`只显示到0E27:0058?**
因为DEBUG的`-u`命令默认只反汇编一小段代码(通常是128字节左右),要看到全部代码需要用`-u`连续反汇编,或者指定范围如`-u 0 100`。

**总结:**
- CX=0288是程序文件的总大小,约648字节
- 代码段实际从0E27:0000开始,长度约88字节(根据`-u`显示)
- 要查看完整的代码段,请使用`-u 0`然后连续按`-u`,或使用`-d`查看数据段

如果您想确认代码段的实际长度,可以使用DEBUG的`-d`命令查看内存内容,或者用`-u`从0开始连续反汇编。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-1-28 15:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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