王爽 汇编语言个人疑问汇总第二篇(5-6章)

第五章

实验4 [bx]和loop的使用

  • (1)编程,向内存0:200 ~ 0:23F依次传送数据0 ~ 63(3FH)。
  • (2)编程,向内存0:200 ~ 0:23F依次传送数据0 ~ 63(3FH),程序中只能使用9条指令,9条指令包括 “mov ax,4c00h”和“int 21h”
    • (1)和(2)的代码
assume cs:code 
 code segment
  mov ax,020H ; (ax)=020H
  mov ds,ax  ; (ds)=020H
  
  mov bx,0    ; 初始化bx,(bx)=0
  mov cx,63   ; (cx)=63 ,表示循环63次
  
  s:mov [bx],bx  ; ((ds) * 10H + (bx)) = (bx) , 将bx中的数据送入020H:bx中
  inc bx      ; (bx) = (bx) + 1
  loop s      ; 循环
  
  mov ax,4c00H ; 固定的结束代码
  int 21H       ; 固定的结束代码
 code ends
end
  • (3)下面的程序的功能是将"mov ax,4c00h"之前的指令复制到内容0:200处,补全程序。上机调试,跟踪运行结果。

什么叫做 mov ax,4c00H 之前的指令 ?
指令也是数据,CS:IP 指向的就是指令,因此,mov ax,_____ 这里必然是填上 CS 的,也就是 mov ax,cs
寄存器 CX 控制的是循环次数,那么 mov cx,____ 这里必然要填上一个数字,代表循环次数
程序的功能是复制一系列指令,那么cx寄存器后面需要填上的数字必然与这一系列指令的个数相关

  • mov ax,cs确定了, mov cx,____未确定,我随便写了个11,编译后debug,结果如下图。
    在这里插入图片描述
  • mov ax,4C00h的起始地址是0017H,直接与第一条指令的0000H相减,马上就可以得到17H
  • 完整代码
assume cs:code
code segment
	mov ax,cs          ;需要把ds数据段指向指令段
	mov ds,ax
	mov ax,0020h
	mov es,ax
	mov bx,0
	mov cx,17H         ;通过debug -u命令可以查看
					   ;mov ax,4c00h 的IP为 0017h
					   ;也就是程序长度17h
	s:mov al,[bx]
	  mov es:[bx],al
	  inc bx
	  loop s
	  
	mov ax,4c00h
	int 21h
code ends
end

参考大佬的文章: [023][汇编语言]实验4 [bx]和loop的使用(复制指令)

第六章

检测点6.1

(1)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,完成程序:

assume cs:codesg

codesg segment 
	dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

start:	mov ax,0	
		mov ds,ax		;初始化数据段地址指向段地址0的位置
		mov bx,0

		mov cx,8		;寄存器是16位结构的,刚好8个字型数据所以循环8次
	s:	mov ax,[bx]		
	
;----------------------------------------------------------------		
		mov cs:[bx],ax	; 程序启动cs自动定位到程序的地址,所以修改cs段寄存器就好了
;-----------------------------------------------------------------						

		add bx,2 		;一个字型数据占两个内存单元,每次偏移2
		loop s

		mov ax,4c00h
		int 21h

codesg ends
end start

(2)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:

  • 这里要注意下1个字型数据等于2个字节;
  • 第一个dw关键词开辟了8个字的空间,并且存入了数据
  • 第二个dw关键词开辟了10个字的空间,用作栈空间
  • 可以计算出栈顶的偏移地址 SP = (8+10)x2= 36 =24H ;十六进制为24H,十进制为36。
assume cs:codesg
codesg segment

    dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h  ;定义数据
    dw 0,0,0,0,0,0,0,0,0,0   ; 10个字单元用作栈空间
      -------------------------------------
start: mov ax,cs         ; 定义代码段
      -------------------------------------
       mov ss,ax         ; 定义栈段
       -------------------------------------
       mov sp,24H        ; 定义栈底为36 (8*2 + 10*2)
       -------------------------------------
       
       mov ax,0
       mov ds,ax         ; 定义内存起始段
       mov bx,0          ; 定义内存偏移
       mov cx,8          ; 定义循环次数
       
    s: push [bx]         ; 将ds:[bx]内存单元中的数据写入栈单元ss:sp(sp=24h) -> sp=24h - 2h = 22h
       -------------------------------------
      pop cs:[bx]        ; 将ss:sp(sp=22h)为栈顶的字单元中的数据写入cs:[bx]-> sp=22h + 2h = 24h
      --------------------------------------
       add bx,2          ; 相邻两个字节单元为一个字单元,因此偏移2
       loop s

       mov ax,4c00h
       int 21h

codesg ends
end start    

参考大佬的文章 [024][汇编语言]检测点6.1 在同一个代码段里使用数据和栈

实验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
  • debug运行,如下图所示。

注意:所有DS与源程序代码之间的段地址都是相差10h,。最开始DS的值为075A,则PSP的地址为075AH:0,程序的地址为076AH:0(075AH+10H)
在这里插入图片描述

  • (1)CPU执行程序,程序返回前,data段中的数据为多少?

0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H

  • (2)CPU执行程序,程序返回前,cs=,ss=,ds=_。
    由上图可知道,在执行int 12h之前:

CS = 076C
SS = 076B
DS = 076A

  • (3)设程序加载后,code段的段地址为X,则data段的段地址为_,stack段的段地址为_。

code(代码)段是指向CS,data(数据)段指向DS,stack(栈)段指向SS。从第(2)题答案我们已经知道CS 、SS 、DS ,可以观察出其中规律,相邻之间相差1H。
所以:
data段地址为 X - 2H
stack段地址为 X - 1H

(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
  • (1)CPU执行程序,程序返回前,data段中的数据为多少?

0123H, 0456H, 0,0,0,0,0,0

  • (2)CPU执行程序,程序返回前,cs=,ss=,ds=_。
    由上图可知道,在执行int 12h之前:

CS = 076C
SS = 076B
DS = 076A

  • (3)设程序加载后,code段的段地址为X,则data段的段地址为_,stack段的段地址为_。

code(代码)段是指向CS,data(数据)段指向DS,stack(栈)段指向SS。从第(2)题答案我们已经知道CS 、SS 、DS ,可以观察出其中规律,相邻之间相差1H。
所以:
data段地址为 X - 2H
stack段地址为 X - 1H

  • (4)对于如下定义的段:

name segment

name ends

如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为_。

如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为: 16 * [(N-1)/16 + 1],此处实际字节数是4
N/16:取整
即使name段中只包含一个字节,也要占一个段(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

在这里插入图片描述

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

0123H, 0456H, 0,0,0,0,0,0

  • CPU 执行程序,程序返回前

CS = 076AH,SS = 076EH,DS = 076DH

  • 设程序加载后,code段的段地址为X

则data段的段地址为 X + 3, stack段的段地址为 X + 4

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

实验中(3)的程序可以正确执行,如果程序的位置发生了变化,并且将程序入口标识start去掉,程序就会从上往下执行

(5)编写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并不需要声明a、b、c;操作的是字节,inc bx累加1即可。

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:
    mov ax,a
    mov ds,ax ; 先把a段=ds段寄存器
    
    mov ax,c
    mov es,ax ; c段=es段寄存器
    
    mov cx,8 ;  复制8个单字节,循环8次即可
    mov bx,0  ; bx清零
s:	
    mov ah,0 ; 因为是单字节所以ax寄存器高位不需要,置为0即可
    mov al,ds:[bx] ; ax的低位al = ds:[bx]
    mov es:[bx],al    ;mov es:[bx],ax也可以
    inc bx    ;单字节,自增1
    loop s ; 循环
	
    mov cx,8
    mov bx,0
	
    mov ax,b
    mov ds,ax ; 把b=ds段寄存器
s0:
    mov ah,0 ; 不需要高位,置为0
    mov al,ds:[bx] ; 低位al = ds:[bx]
    add es:[bx],al ; es:[bx]相当于取的是a数据段的值 al (ds:[bx])是b数据段的值,两者累加
    inc bx ; 加1
    loop s0 ; 循环
	
    mov ax,4c00h 
    int 21h
code ends
 
end start
  • 执行结果
    在这里插入图片描述

(6)程序如下,编写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    ;16字,32字节
a ends
 
b segment
    dw 0,0,0,0,0,0,0,0
b ends
 
code segment
start:
    ?
 
code ends
end start
  • 修改后

本题操作是是字,占用2个字节,所以循环累加2。
逆序,结合前面的知识栈有这个特性。

assume cs:code
 
a segment
    dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh    ;16字,32字节
a ends
 
b segment
    dw 0,0,0,0,0,0,0,0
b ends
 
code segment
start:
    mov ax,a
	mov ds,ax ; 希望用ds:bx访问a段的数据,ds指向a段
 
    mov ax,b
	mov ss,ax
	mov sp,16   ; 希望b作为栈空间,设置ss:sp指向b:16
	
	mov bx,0    ;段地址偏移字节数
	mov cx,16    ;循环次数
	
s:  
	push [bx]  ; 意为 ds:[bx] ,把数据放入栈中
	add bx,2    ;字型数据占两个字节 ,或者  inc bx  inc bx 累加 2次
	loop s  ; 循环
	
	mov ax,4c00h
	int 21h
code ends
end start
  • 结果
    在这里插入图片描述

posted on 2021-10-25 10:43  愤怒的苹果ext  阅读(98)  评论(0编辑  收藏  举报

导航