汇编语言(王爽)第六章

第六章

6.1 在代码段中使用数据

编程以下8个数据的和,结果存在ax寄存器中,用循环累加的方式

想用循环,就需要把这些数据存储在一组地址连续的内存单元中,之前提到过应该让系统来分配空间,因此我们在程序中定义希望处理的数据,这些数据最终会成为程序的一部分写到可执行文件中,可执行文件加载到内存中后,这些数据便自然获得了存储空间

assume cs:code

code segment
	
	dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
	
	mov bx,0
	mov ax,0
	
	mov cx,8
  s:add ax,cx:[bx]
  	add bx,2
  	loop s
  	
  	mov ax,4c00H
  	int 21H
  	
code ends

end

dw的含义是定义字型数据,这段代码中定义了8个字型数据,占16个字节的内存单元,由于在代码段中,且定义在代码段最开始,所以地址为CS:0,CS:2.CS:4……以此类推

在Debug中使用U命令,这些数据会被翻译为汇编指令,如果想要执行第一条真正的指令,就需要更改IP的值,这样一来,直接编译、连接而后执行的话会出现问题,因为IP初始为0,因此代码需要更改

assume cs:code

code segment
	
	dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
	
    start:  mov bx,0
            mov ax,0

            mov cx,8
          s:add ax,cx:[bx]
            add bx,2
            loop s

            mov ax,4c00H
            int 21H
  	
code ends

end start

伪指令end除了通知编译器程序结束外,还可以通知编译器程序的入口在哪

如何设置CPU中CS:IP指向第一条要执行的指令,这一点由可执行文件中的描述信息指明,上面的程序中end start指明入口地址的偏移地址为10H,这个信息被存放在可执行文件中,加载者会根据该信息设置CS:IP

6.2 在代码段中使用栈

利用栈,将程序中定义的数据逆序存放

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,0,0,0,0,0,0	;再定义16个字型数据,程序加载后
										;取得16个字的内存空间
										;后面的程序将这段空间当作栈来使用

    start:	mov ax,cs
            mov ss,ax
            mov sp,30H	;将cs:10~cs:2F的内存空间当作栈
            			;注意栈顶的设置方法
            
            mov bx,0
            mov cx,8
          s:push cs:[bx]
            add bx,2
            loop s	;将代码段0~15单元8个字型数据入栈
            
            mov bx,0
            mov cx,8
         s0:pop cs:[bx]
            add bx,2
            loop s0	;依次出栈8个字型数据,达到逆序存放的目的
            
            mov ax,4c00H
            int 21H
            
codesg ends

end start

我们在描述dw的作用时,既可以说是用来定义数据,也可以说是用来开辟内存空间,最终效果是一样的,定义8个字型数据,也可以说开辟了8个字的内存空间

练习:

依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行,栈空间设置在程序内

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
			
			mov ax,0
			mov ds,ax
			mov bx,0
			
			mov cx,8
		  s:push [bx]	;先把0:[bx]处的数据入栈
		    pop cs:[bx]	;入栈后立刻弹出存到原有数据处cs:0 cs:2等
		    add bx,2
		    loop s
		    
		    mov ax,4c00H
		    int 21H
		  
codesg ends

end start

6.3 将数据、代码、栈放入不同的段

在前面的内容里我们把数据、栈、代码等放到同一个段里,这样显得混乱,如果数据、栈、代码需要的空间超过64KB,就超出了一个段的最大容量(8086模式下)

因此考虑用多个段分别存放

assume cs:code,ds:data,ss:tack

data sgement
	dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
data ends

stack segment
	dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment
	 start:	mov ax,stack
            mov ss,ax
            mov sp,20H	;设置栈顶ss:sp指向stack:20
            
            mov ax,data
            mov ds,ax	;ds指向data段
            
            mov bx,0	;ds:bx指向data段中的第一个单元
            
            mov cx,8
          s:push [bx]
            add bx,2
            loop s	;将data段0~15单元8个字型数据入栈
            
            mov bx,0
            
            mov cx,8
         s0:pop [bx]
            add bx,2
            loop s0	;依次出栈8个字型数据到data段中的0~15单元中
            		;达到逆序存放的目的
            
            mov ax,4c00H
            int 21H
            
codesg ends

end start

程序中,段名相当于一个标号,代表了段地址,mov ax,data的含义就是将名称为data段的段地址送入ax,不能使用mov ds,data,因为8086CPU不允许将一个数值直接送入段寄存器中,data和stack都被编译器处理为一个表示段地址的数值

这里命名的stcak,data,code只是我们的命名,CPU并不会因此就去把stack段当作栈,data段存放数据,即使assume cs:code,ds:data,ss:tack,CPU也不会使cs指向code,ds指向data,这些都只是标号,仅存在于源程序中

想要CPU按照我们的安排操作,需要用机器指令控制,源程序中的汇编指令是CPU需要执行的内容,我们用end start使得CPU得知第一条指令的位置

通过

mov ax,stack
mov ss,ax
mov sp,20H

设置ss:sp指向stack:20,所以把stack段当作栈空间使用

总之,CPU如何处理我们定义段的内容,当作数据还是段,完全靠汇编指令以及汇编指令对具体寄存器的设置来决定的,将源程序中code改为a,data改为b,stack改为c,start改为d也是可以的

发布了84 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43569916/article/details/104547264
今日推荐