王爽 实验7

本文通过两种方法(直接MOV指令与栈操作)实现了对年份、收入及雇员数量的数据处理与计算,重点在于理解内存布局与数据类型转换。
摘要由CSDN通过智能技术生成

搞懂这个题目的意思就花了我半天,只怪本人理解能力太差。

题目意思:题目定义了21个'year summ ne ?? ‘,正好是16个字节,与table中的相对应。首先我还纳闷,1995放到4个字节中还好说,可是5937000如何放到4个字节中呢?5a9786H要如何放到4个字节中呢?原来是这样,00 5a 97 86,恍然大悟,都怪自己一直对啥bit,byte,字,字节等等搞不清楚。然后我又以为要跟书上的表一模一样,百思不得其解,难道我现在的水平还能做出这么高超的表来吗?第二天再看这个题目,突然一下明白过来,原来db 21 dup('year summ ne ?? ')只是开辟了21个16字节的空间,然后将之前定义的种种mov或找个栈做中介push进去就OK了。啊,原来如此。分析的时候大家可以画一个长条图,分成一个一个小块,就像地址图那样,每个小块中写上几个象征性的数字,譬如1975.。。。。。。10000000.。。。。0300.。。。,然后可能会更加明白些吧,我这里就不传图片了,CSDN不知道发什么疯,图片审核N久。声明一下,那个1975并不是真的存在内存中就是那样的数字,我是为了方便才那样写。

为便于理解,大家可以去这里看下结果图:http://download.csdn.net/source/2011848

我也不想这么麻烦,可是CSDN不可以传图片了。

第一种方法:mov(我自己写的哈)

assume cs:codesg,ds:data
  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'                         ;每个年份占4个字节,一共4*21=54h个字节

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000    ;每个收入占4个字节,dd嘛,一共4*21=54h

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,15257,17800        ;每个雇员数占2个字节,dw嘛,一共2*21=2ah
  data ends

  table segment
   db 21 dup('year summ ne ?? ')        ;16个字节一排,如果你用命令d查看时,会发现有一排一排的year summ ne ??,本程序运行完后就会变成(举一个例子)类似这样:1995 h-Z- -E M- ,看左边就会发现时这样的:31 39 39 35 20 68 97 5a-00 20 88 45 20 4d 01 20 其中31 39 39 35就是1990,20是空格,005a9768就是593700的16进制了,后面的自己推吧
  table ends

  codesg segment
  start: mov ax,data
         mov ds,ax
         mov ax,table
         mov es,ax
        
         mov bx,0
         mov si,0
         mov di,0

         mov cx,21
       s:
         mov ax,ds:[di]
         mov es:[bx],ax
         mov ax,ds:[di][2]
         mov es:[bx][2],ax
         
         mov ax,ds:[di+54h]
         mov es:[bx].5,ax
         mov ax,ds:[di+54h][2]
         mov es:[bx].5[2],ax

         mov ax,ds:[si+0a8h]
         mov es:[bx].10,ax
        
         mov dx,[di+54h][2]
         mov ax,[di+54h]
         div word ptr ds:[si+0a8h]
         mov es:[bx].13,ax

         add bx,16
         add di,4
         add si,2
         loop s
  mov ax,4c00h
  int 21h
  codesg ends
  end start

 

昨天百思不得其解的时候上网看到了一个网友极力推荐的用栈的方法写的一个程序,发现与我的这个思想差不多,不过也复制过来供大家参考。

第二种方法:栈

DATAS  SEGMENT
              DB        '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982'
              DB        '1983', '1984', '1985', '1986', '1987', '1988', '1989', '1990'
              DB        '1991', '1992', '1993', '1994', '1995'
    
              DD        16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
              DD        345980, 590827, 803530, 118300, 184300, 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
       DATAS  ENDS

       TABLE  SEGMENT
              DB        21 DUP ('year summ ne ?? ')
       TABLE  ENDS

      STACKS  SEGMENT
              DB 16 DUP (0)
      STACKS  ENDS

ASSUME    CS:CODES,DS:DATAS,SS:STACKS

       CODES  SEGMENT
      START:
              ;相关寄存器初始化
              MOV       AX,DATAS
              MOV       DS,AX
              MOV       AX,TABLE
              MOV       ES,AX
              MOV       AX,STACKS
              MOV       SS,AX
              MOV       SP,16
    
              MOV       BX,0
              MOV       BP,0
              MOV       DI,0
              MOV       SI,0

              MOV       CX,21

      cycle:  ;使用栈复制年份
              PUSH      [DI].0
              PUSH      [DI].2
              POP       ES:[BP].2
              POP       ES:[BP].0
              
              ;使用栈复制收入
              PUSH      54H.[DI].0
              PUSH      54H.[DI].2
              POP       ES:[BP].7
              POP       ES:[BP].5

              ;使用栈复制雇员数
              PUSH      0A8H.[SI]
              POP       ES:[BP].0AH

              ;计算人均收入
              MOV       AX,ES:[BP].5
              MOV       DX,ES:[BP].7
              DIV WORD PTR ES:[BP].0AH
              MOV       ES:[BP].0DH,AX

              ADD       SI,2H
              ADD       DI,4H
              ADD       BP,10H

              loop cycle
                   

              MOV       AH,4CH
              INT       21H
       CODES  ENDS
END       START

<think>嗯,用户想找老师的汇编语言实验10的教程或资料。首先,我需要回想一下老师的《汇编语言》这本书的结构。记得这本书每个章节后面都有实验实验10可能涉及到子程序或者更复杂的内容,比如显示字符串或者数值转换之类的。 用户提到的其他实验,比如实验八、实验九和实验一,引用了显存地址、代码段初始值等问题。这说明实验10可能也会涉及类似的底层操作,比如直接操作显存或者编写中断处理程序。例如,实验九是关于在屏幕上显示彩色字符,而实验十可能在此基础上进一步扩展。 根据已有的引用内容,显存地址空间是A0000到BFFFF,特别是0B800H段,这可能和实验10的内容相关。用户可能在实验10中需要处理字符串显示、端口读写或者更复杂的子程序结构。比如,将十进制数转换为二进制显示,或者处理键盘输入中断。 接下来,我应该检查是否有现成的实验10资料。不过用户提供的引用中没有直接提到实验10,所以可能需要根据已知信息推断。可能需要指导用户如何通过调试工具如Debug或masm来逐步完成实验,观察寄存器和内存的变化,确保正确使用显存地址,并注意代码段的初始值设置。 此外,用户可能需要关注子程序的设计、参数传递方式(栈或寄存器)、以及如何正确设置段寄存器和偏移地址。比如,在显示字符串时,可能需要计算显存中的位置,处理颜色属性,并循环写入字符数据。 最后,应该提醒用户查阅书籍相关章节,特别是实验说明部分,并建议他们结合调试工具实践,同时注意常见的错误点,比如段地址的正确书写(0B800H而非B800H),以及确保数据被正确加载到内存中。</think>关于《汇编语言》实验10的相关资料,目前站内引用中未直接提供该实验的完整教程,但根据已有引用和知识体系,可以整理以下关键要点帮助完成实验: ### 一、实验10核心知识点 1. **子程序调用与参数传递** 实验中需设计带参数的子程序,参数传递通常通过寄存器或内存实现。例如: ```assembly ; 示例:通过栈传递参数 mov ax, offset msg push ax ; 字符串偏移地址入栈 call show_str ; 调用显示子程序 ``` 2. **显存操作原理** 显存地址空间为$A0000-BFFFF$,其中$0B800H$段用于文本模式显示[^3]。每个字符占用2字节:ASCII码(低位)+ 颜色属性(高位)。例如: ```assembly mov ax, 0B800H mov es, ax ; 设置显存段地址 mov byte ptr es:[160*12+40*2], 'A' ; 屏幕第13行第41列显示'A' ``` 3. **代码段与数据段分离** 需注意IP初始值可能与代码段起始位置不同,需用`start`标签明确入口[^1]。例如: ```assembly assume cs:code code segment start: ; 程序入口 mov ax, data mov ds, ax ; 初始化数据段 ... code ends ``` ### 二、实验10常见问题解决 1. **显存地址错误** 显存段地址必须写为`0B800H`而非`B800H`,否则汇编器会报错[^2]。 2. **字符串存储问题** 需明确为字符串分配内存空间: ```assembly data segment db 'Hello World!', 0 ; 字符串以0结尾 data ends ``` 3. **颜色属性设置** 颜色属性字节格式:背景色(高4位) + 前景色(低4位)。例如`00000111B`表示黑底白字。 ### 三、推荐实践步骤 1. 使用Debug工具单步调试,观察IP和CS寄存器变化 2. 通过`d 0B800:0`命令查看显存内容 3. 编写子程序时先绘制流程图,明确参数传递方式 4. 验证代码段与数据段地址是否正确对齐
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值