汇编语言学习(二)

今天学习了王爽《汇编语言》第5、6章。
我感觉这两章主要加深了对于这个概念的理解。

第5章[Bx]和loop指令,重点在于段地址和偏移地址的理解,段前缀的应用。
第6章包含多个段的程序,重点在于理解为什么要分段,掌握分段汇编程序的写法,搞清楚段在内存当中的存储。

1.loop指令[bx]的应用

1.1 计算ffff:0~ffff:b单元中数据的和,并将结果保存在dx中?

存在的问题:8位的内存单元累加之和放到16位的寄存器中

解决的方法:ax为中介,其中ah设为0,al为内存单元的值。

mov ax,0ffffh里面,0h一个都不能少。

assume cs:code
code segmentmov ax,0ffffhmov ds,axmov ax,0mov dx,0mov bx,0mov cx,12s:mov al,[bx]add dx,axinc bxloop s  mov ax,4c00hint 21h 
code ends
end
1.2 将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b中?

段前缀的应用ds、cs、ss、es都可以使用,很灵活。

注意题目是,将内存ffff:0~ffff:b单元中的数据复制到0:200~0:20b单元中。将段前缀设置为0020h0要方便。

   mov ax,0ffffhmov ds,axmov ax,0020hmov es,axmov bx,0mov cx,12
s: mov dl,[bx]mov es:[bx],dlinc bxloop s

2.包含多个段的程序

2.1 如何对数据进行累加?

即一些数据常量应该如何声明,如何引用?

采用dw 0123h,0456h,0789h进行声明。

通过cs:[bx]进行定位,bx每次增加2个字节。

但是仅仅只做这些改变,在运行时就会出现问题。先看一下程序的内存:

这里写图片描述

可以看出前6个字节存储的三个字的值,为避免将数据当作指令,程序应该从0C53:0006开始执行。

所以需要在源程序中用end标号,标记程序的入口地址。

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

首先,提前声明一块空间,供栈使用。

另外,设置好栈的段地址和偏移地址。

示例程序如下:

assume cs:code
code segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdd 0,0,0,0,0,0,0,0start:mov ax,csmov ss,axmov sp,30hmov bx,0mov cx,8s: push cs:[bx]add bx,2loop smov bx,0mov cx,8s1:pop cs:[bx]add bx,2loop s1mov ax,4c00hint 21hcode ends
end start
2.3 结构更清晰——将代码分多个段

下面是之前提及的例子,不过分了数据、栈和代码三段。

需要注意的是:

1.在assume之后,CPU不会将CS指向code,不会将DS指向data,不会将SS指向stack。

2.end指明了程序的入口,这个入口将被写入可执行文件的描述信息。可执行文件中的程序被加载到内存之后,CPU的CS:IP被设置指向这个入口,开始执行程序中的第一条指令。

所以,CS的值不用在代码中设定,但是DS和SS的值需要在代码中进行说明。

3.对于一个段,如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为:

(N/256+1)*256

其中除法取整。

assume cs:code,ds:data,ss:stackdata segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data endsstack segmentdw 0,0,0,0,0,0,0,0
stack endscode segment
start:  mov ax,stackmov ss,axmov sp,20h       mov ax,datamov ds,axmov bx,0mov cx,8   
s:       push [bx]add bx,2loop smov bx,0mov cx,8
s1:      pop [bx]add bx,2loop s1mov ax,4c00hint 21h
code ends
end start

自己通过调试,发现段在内存中的存储方式,是很有意思的一件事情。
不过更有意思的永远都在后面(手动滑稽)

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注