▲汇编语言经典教材,《汇编语言》,王爽著,清华大学出版社。后续关于汇编语言的所有讲解都是基于这本教材。
全文共2306字,阅读大约需要6分钟。
汇编语言的重要性不言而喻,如果读者想从事计算机科学方面的工作的话,汇编语言的基础是必不可少的。
汇编语言是人和计算机沟通的最简单的方式,它描述的是人和计算机沟通的最简单的方式。汇编语言不容易学习,就连简明扼要的介绍都很难找到。
那么最近一段时间,就请大家跟着我一起慢慢学习汇编语言。
本文首发于 秦巴布衣清风徐来未经授权 不得转载
大多数有用的程序,都需要处理数据,使用栈空间,当然也都必须有指令,为了程序设计上的清晰和方便,我们一般也定义不同的段来存放它们。
1
在代码段中使用数据
任务1:编程计算以下8个数据的和:
0123h,0456h,0789H,0abch,0fedH,0cbah,0987h
结果存在ax寄存器中
我们当然可以将这些数据一个个加到寄存器中,但在这里,我们希望可以用循环的方法进行累加。
所以在累加前,我们要把这些数据存到一段地址连续的内存单元中。
上一讲中,我们提到有一段安全的内存空间,但这段空间毕竟只有256个字节,如果我们需要的空间超过256个字节呢?具体做法如下:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0fedh,0cbah,0987h
mov cx,8
mov ax,0
mov bx,0
s: add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end
首先需要解释的是dw,dw即define word。在这里我们用dw定义了8个字型数据,它们所占的存储空间为16个字节。
进而你也许会问,这8个数据存在哪儿?
由于它们在代码段中,所以它们的段地址为CS。又因为dw定义的数据在代码段的最开始,因此偏移地址为0。每个数据占用1个字,因此bx每次加2。
让我们尝试着在DOS中将程序编译一下,结果如下图所示。
我们可以看到,CS:IP=2B28:0000,因此程序应该是从2B28:0开始执行的。然而,执行的第一条指令不是“mov cx,8”,而是一条让人看不懂的指令“and ax,[bx+di]”。
其实,因为我们在2B28:0~2B28:F中存储了dw定义的数据,因此,从2B28:10开始,才是我们真正希望执行的程序。
我们可以先用d命令来查看一下2B28:0开始的内存单元中都有什么数据。再用u命令,从2B28:10开始查看要执行的指令,结果和我们预想的一致。
可是这样就出现了一个问题,程序是从2B28:0开始执行的,而因为里面存储了一些数据,于是编译器认为这些数据是新的指令,就会造成误操作。
我们当然可以把IP设成10h,使程序从0B28:10开始执行,但这样每次都得在debug模式下执行程序,很不方便。那么有更好的解决方案么?
具体做法如下:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0fedh,0cbah,0987h
start: mov cx,8
mov ax,0
mov bx,0
s: add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
在上述程序中,我们加入了一个标号start。在编译连接后,由“end start”指明程序的入口,并把它转化为入口地址“10H”,也就是说,加载者知道了“mov cx,8”是程序的第一条指令。
再来看一下,程序就直接从2B28:10开始执行了。
2
在代码段中使用栈
任务2:利用栈,将任务1中的数据逆序存放。实现过程如下:
上述这段程序的思想大致如下:
首先,我们把数据定义在cs:0~cs:15中,再开辟一段内存空间cs:16~cs:31为栈。设置栈顶ss:sp=cs:32,我们先把数据挨个入栈,然后再依次出栈,把数据存放到cs:0~cs:15中,从而实现数据的逆序存放。
至于对设置栈顶为cs:32存在疑惑的同学,建议复习一下第一讲《寄存器》。
3
将数据、代码、栈放入不同的段
在前面的编程中,我们只有一个代码段。我们把数据、栈和代码都放在了一个段里,这样做会使程序比较混乱。
更合适的做法是,我们用多个段来存放数据、代码和栈。程序如下:
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h,0789h,0abch,0fedh,0cbah,0987h
data ends
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:mov cx,8
mov ax,cs
mov ss,ax
mov sp,32
mov bx,0
s: push cs:[bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop cs:[bx]
add bx,2
loop s0
mov ax,4c00h
int 21h
code ends
end start
通过第一条伪指令,我们段寄存器cs、ds、ss与code、data、stack段相连。而程序的入口,通过“end start”,定位到了“mov cx,8”这一句指令处。
那么怎样才能找到一段安全的内存空间呢?在一般的PC机中,0:200~0:300的256个字节是安全的,所以当我们需要直接向内存中写入数据时,可以直接使用这段空间。
拜托了,诸位,关注一下,让我冲一冲流量主(5000人)。只要有人头数就好,觉得内容不好可以后台留言,可以不看,甚至可以屏蔽。再一次感谢!
领取专属 10元无门槛券
私享最新 技术干货