# 实验5

实验5

  1. 将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题。

    assume cs:code,ds:data,ss:stack
    
    data segment
    	dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
    data ends
    
    stack segment
    	dw 0,0,0,0,0,0,0,0
    stack ends
    
    code segment
    
    start:
    	mov ax,stack
    	mov ss,ax
    	mov sp,16
    
    	mov ax,data
    	mov ds,ax
    
    	push ds:[0]
    	push ds:[2]
    	pop ds:[2]
    	pop ds:[0]
    
    	mov ax,4c00h
    	int 21h
    
    code ends
    
    end start
    

    ①CPU执行程序,程序返回前,data段的数据为多少?

    • 由于入栈和出栈顺序相反,故不发生变化
    • 需要注意的是虽然存放数据是按 0123h 存放的,但是实际在内存存储的却是 23 01
    • 此外,栈的特点之一是按字访问
      用PUSH指令和POP指令时只能按字访问堆栈,不能按字节访问堆栈。

    ②CPU执行程序,程序返回前,cs = 076e 、ss= 076d 、ds= 076c 。(每个人都不一样)

    ③设程序加载后,code段的段地址为X,则data段的段地址为 X-2 ,stack段的段地址为 X-1

    • 要注意是段地址,实际要左移一位的,data段和stack段长度都是16个字节,对应十六进制为10,右移后为1,分别减去就好了。
    • 8086处理器的内部寻址原理和汇编程序编译器共同决定了segment定义的段必须放在按16的倍数对准的段地址边界上,占用的空间也是16的倍数。
    • 在8086CPU架构上,段是以paragraph(16-byte)对齐的。程序默认以16字节为边界对齐,所以不足16字节的部分数据也要填够16字节。“对齐”是alignment,这种填充叫做padding。16字节成一小段,称为节。
  2. 将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题。

    assume cs:code,ds:data,ss:stack
    
    data segment
    	dw 0123H,0456H
    data ends
    
    stack segment
    	dw 0,0
    stack ends
    
    code segment
    
    start:
    	mov ax,stack
    	mov ss,ax
    	mov sp,16
    
    	mov ax,data
    	mov ds,ax
    
    	push ds:[0]
    	push ds:[2]
    	pop ds:[2]
    	pop ds:[0]
    
    	mov ax,4c00h
    	int 21h
    
    code ends
    
    end start
    

    ①CPU执行程序,程序返回前,data段的数据为多少?(同第一题)
    答:23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00
    ②CPU执行程序,程序返回前,cs=076E、ss=076D、ds=076C。
    ③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1
    ④对于如下定义的段:
    name segment
    ···
    name ends
    如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为⌈N/16⌉*16字节。

  3. 将下面的程序编译、连接,用Debug加载、跟踪,然后回答问题。

    assume cs:code,ds:data,ss:stack
    
    code segment
    
    start:
    	mov ax,stack
    	mov ss,ax
    	mov sp,16
    
    	mov ax,data
    	mov ds,ax
    
    	push ds:[0]
    	push ds:[2]
    	pop ds:[2]
    	pop ds:[0]
    
    	mov ax,4c00h
    	int 21h
    
    code ends
    
    data segment
    	dw 0123H,0456H
    data ends
    
    stack segment
    	dw 0,0
    stack ends
    
    end start		
    
    1. cpu 执行程序,程序返回前,cs = ,ss = ,ds =
      由 -r 的内容,直接填
      cs=076a,ss=0769,ds=075A。

    2. 设程序加载后,code段的段地址是X,则data段的地址为X+3,stack段的地址为X+4

  4. 如果将(1)、(2)、(3)题中的最后一条伪指令"end start"改为"end"(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因

    答:(3)的程序仍然可以正确执行。没有了伪指令,exe文件被加载在内存中,首先将CS:IP指向程序的首地址。而只(3)的程序中一开始定义的是代码段,所以CS:IP指向了指令的首地址。(1)、(2)的程序中一开始定义的是数据段,所以 cs:ip 指向了数据的首地址而非指令,而CPU会把数据段中的数据当中机器指令来执行。

    1. 程序如下,编写code段的代码,将a段和b段中的数据依次相加,将结果存到c段中。

      assume cs:code
      
      a segment
      	db 1,2,3,4,5,6,7,8
      a ends
      
      b segment
      	db 1,2,3,4,5,6,7,8
      b ends
      
      c segment
      	db 0,0,0,0,0,0,0,0
      c ends
      
      code segment
      
      start:
      	?	
      
      code ends
      
      end start			
      

      答:

      assume cs:code
      
      a segment
      	db 1,2,3,4,5,6,7,8
      a ends
      
      b segment
      	db 1,2,3,4,5,6,7,8
      b ends
      
      c segment
      	db 0,0,0,0,0,0,0,0 # 用c会报错,当存寄存器时
      c ends
      
      code segment
      
      start:
      	mov ax,a
      	mov ds,ax
      
      	mov ax,b
      	mov es,ax
      
      	mov cx,8
      	mov bx,0
      	mov dx,0
      
      	s:mov dl,ds:[bx]
      	add dl,es:[bx]
      	mov es:[bx+16],dl # 没有多余段寄存器来表示c段,结合段长为16倍数在原有基础上修改
      	mov dl,0
      	inc bx
      	loop s # 也可以采用多次循环,先将a段赋值到c段,再与b段相加
      
      	mov ax,4c00h
      	int 21h
      
      code ends
      
      end start		
      
    2. 程序如下,编写code段中的代码,用push指令将a段中的前8个字型数据,逆序存储到b段中。

      assume cs:code
      
      a segment
      	dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
      a ends
      
      b segment
      	dw 0,0,0,0,0,0,0,0
      b ends
      
      code segment
      
      start:
      	?
      
      code ends
      
      end start	
      

      答:

      assume cs:code
      
      a segment
      	dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
      a ends
      
      b segment
      	dw 0,0,0,0,0,0,0,0
      b ends
      
      code segment
      
      start:
      	mov ax,a
      	mov ds,ax
      	
      	mov ax,b
      	mov ss,ax
      	mov sp,16
      
      	mov bx,0
      	mov cx,8
      	s1:push ds:[bx]
      	add bx,2 # 按字传递
      	loop s1
      
      	mov ax,4c00h
      	int 21h
      
      code ends
      
      end start		
      

posted @   三年、  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示