鱼C论坛

 找回密码
 立即注册
查看: 128|回复: 1

[学习笔记] 汇编实验七

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

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

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

x
追了小甲鱼10多年前的视频到现在,留一点学习笔记。
关于汇编实验七--具有里程碑意义的编程,也是花了3天时间从0思考,排查,调试和回看知识点。
【基本思路】
题目给出了4个源数据段,分别是年份、年收入、人数、人均。其中前3个字段是提前定义好的,人均这个字段可以根据年收入除以人数通过循环逐个写入table段;
ds段地址寄存器指向data段,es段地址寄存器指向table目标数据段。
通过4段循环,分别从data数据段按照一定格式导入table数据段。
【问题拆分】
1. 源数据段在哪里?
  -A. 年份段:db类型,每1个年份是4个字节(4个单字节字符串),21年就是84个字节。即ds:0~ds:53H;
  -B. 年收入段:dd类型,每1个双字类型占用4个字节,21个就是84个字节,继续在54H地址上加。即ds:54H~ds:0A7H;
  -C. 人数段:dw类型,每1个字型数据占用2个字节,21个就是42个字节。即ds:0A8H~ds:0D2H;
2. 目标数据段怎么存放?
  题目给出了定义21段'year summ ne sr ',这里数了一下,正好是16个字节;
  以第一行数据为例:
        年份存在es:[0]~es:[3];
        年收入存在es:[05H]~es:[08H],其中05H、06H存低位数据,07H、08H存高位数据,分别用ax,dx存储低位、高位数据;
        人数存在es:[0AH]~es:[0BH],这里由于是1个字型数据,直接用ax mov过去就行;
        人均存在es:[0DH]~es:[0EH]
3. 循环变量:
  利用3个计数偏移寄存器bx、di、si来实现:
        年份段:2重循环,内循环bx变量每次+1,外循环si变量+4取到每个年份的第一个字段,di变量+16定位es段的第一位
        年收入段:1层循环,每次si+4指向下一个double word数据,di变量+16定位es段,加上[05H]和[07H]低位、高位数据段地址
        人数:1层循环,每次si+2指向下一个字型数据,di变量+16定位es段,加上[0AH]偏移量
        人均:1层循环,仅用di变量+16定位,每一次将es:[05H+di]和es:[07H+di]地址值分别给ax, dx,做除法后商被写入ax,最后mov es:[di+13], ax
【源码】
assume cs:code,ds:data,es:table,ss:stack
data segment
        db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
        db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
        db '1993','1994','1995'
       
        dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
        dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
       
        dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
        dw 11542,14430,15257,17800
data ends

table segment
        db 21 dup ('year summ ne sr ')
table ends

stack segment
        db 0,0
stack ends

code segment
start:  mov ax,data
        mov ds,ax
        mov ax,table
        mov es,ax
        mov si,0       ; 年份数据偏移
        mov di,0       ; table段偏移
        mov cx,20      ; 处理21个年份,这里我用了栈段,第一次push cx没走到loop,cx不会-1,因此初始值设定20

; 复制年份到table段
year_loop:
        push cx
        mov cx,4
        mov bx,0       ; 每次内循环重置bx,这也是我之前排查好久的点,debug一看数据怎么老错位
copy_year:
        mov al,[si+bx]
        mov es:[di+bx],al
        inc bx
        loop copy_year
        add si,4       ; 下一个年份
        add di,16       ; table下一行
        pop cx
        loop year_loop

; 处理summ(总收入)
        mov si,84      ; summ数据起始偏移(21*4=84)
        mov di,0
        mov cx,21
summ_loop:
        mov ax,[si]     ; 低16位
        mov dx,[si+2]   ; 高16位
        mov es:[di+5],ax
        mov es:[di+7],dx
        add si,4        ; 下一个dd
        add di,16
        loop summ_loop

; 处理ne(雇员数)
        mov si,168     ; ne数据起始偏移(84+84=168)
        mov di,0
        mov cx,21
ne_loop:
        mov ax,[si]
        mov es:[di+10],ax ; ne字段偏移0AH
        add si,2
        add di,16
        loop ne_loop

; 计算sr(人均收入)
        mov di,0
        mov cx,21
sr_loop:
        mov ax,es:[di+5]  ; 总和的低16位
        mov dx,es:[di+7]  ; 总和的高16位
        div word ptr es:[di+10] ; 正确除数:ne字段值
        mov es:[di+13],ax ; sr字段偏移0DH
        add di,16
        loop sr_loop

        mov ax,4C00H
        int 21H
code ends
end start
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2025-3-13 19:46:40 | 显示全部楼层
:汇编实验七.asm
startLine: 36
endLine: 108

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-3-31 09:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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