531035528 发表于 4 天前

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

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:                        ;;年份低位复制
                mov es:,ax
                mov ax,ds:                ;;年份高位复制
                mov es:,ax
               
                mov ax,ds:                ;;收入低位ax暂存并复制
                mov es:,ax
                mov dx,ds:                ;;收入高位dx暂存并复制
                mov es:,dx
               
                mov bx,ds:                ;;雇员人数bx暂存并复制
                mov es:,bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:,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???

FishC 发表于 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 小助理,如未能正确解答您的问题,请继续追问。

531035528 发表于 4 天前

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

0eo4+150H=0f54才对,为什么是0e27???

FishC 发表于 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

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

DS = 0E04H
tablesg 段地址 = 0E04H + ceil(210/16) = 0E04H + 14 = 0E12H
CS = 0E12H + ceil(336/16) = 0E12H + 21 = 0E27H


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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

531035528 发表于 4 天前

FishC 发表于 2026-1-28 11:24
在 DOS 环境下,段地址的计算是以 16 字节(1 节)为单位的。直接加字节数 150H 是错误的,必须转换为 ...

cx=288是怎样算出来的???

FishC 发表于 4 天前

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,需要查看数据定义部分。假设有如下数据定义:

data segment
    db 288 dup(0)   ; 定义288个字节
data ends

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

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

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

531035528 发表于 4 天前

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:                        ;;年份低位复制
                mov es:,ax
                mov ax,ds:                ;;年份高位复制
                mov es:,ax
               
                mov ax,ds:                ;;收入低位ax暂存并复制
                mov es:,ax
                mov dx,ds:                ;;收入高位dx暂存并复制
                mov es:,dx
               
                mov bx,ds:                ;;雇员人数bx暂存并复制
                mov es:,bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:,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 ????

FishC 发表于 4 天前

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 小助理,如未能正确解答您的问题,请继续追问。

531035528 发表于 4 天前

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:                        ;;年份低位复制
                mov es:,ax
                mov ax,ds:                ;;年份高位复制
                mov es:,ax
               
                mov ax,ds:                ;;收入低位ax暂存并复制
                mov es:,ax
                mov dx,ds:                ;;收入高位dx暂存并复制
                mov es:,dx
               
                mov bx,ds:                ;;雇员人数bx暂存并复制
                mov es:,bx
                div bx                                        ;;16位除法运算,商存放在ax,余数存放在dx
                mov es:,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 怎样算的???

FishC 发表于 4 天前

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 小助理,如未能正确解答您的问题,请继续追问。

531035528 发表于 4 天前

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

但我用-u 显示代码段是0e27:0000到0e27:0058,与cx=0288不等啊???

FishC 发表于 4 天前

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 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: ds=0e04为什么cs=0e27???