汇编基本语法实现

第五个程序

堆栈的学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
assume cs:codesg

codesg segment

mov ax,2000h ;地址2000h赋值给ax
mov ss,ax ;ax的值传递给段寄存器ss
mov sp,0 ;堆栈指针sp赋初值0
pop ax ;出栈到ax
pop bx ;出栈到bx
push ax ;ax入栈
push bx ;bx入栈
pop ax ;出栈到ax
pop bx ;出栈到bx

mov ax,4c00h
int 21h

codesg ends

end

首先观察代码段的前256字节称为PSP的内容

通过debug观察各个寄存器的值,通过现象学习堆栈的后进先出的操作规则。

可以看到进行
出栈出栈
入栈入栈
再出栈出栈
之后
ax和bx寄存器的值进行了交换。

类似生活中的一瓶糖水,一瓶盐水,现在需要交换两个瓶子的液体。使用“堆栈”这个容器进行了一个中转。


第六个程序

程序功能把内存单元的ffff:0 ~ffff:b单元的内容复制到0:200~0:20b内存单元中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
assume cs:code 

code segment

mov ax,0ffffh ;通过ax中转给段寄存器ds赋初值FFFFH
mov ds,ax
mov ax,0020h ;通过ax中转给段寄存器es赋初值20H
mov es,ax
mov bx,0 ;bx置零
mov cx,12 ;循环12次

s: mov dl,[bx] ;循环体s 开始循环12次
mov es:[bx],dl ;通过dl中转把ds:0-ds:b中的内容复制到es:0-es:b
inc bx ;b自增一
loop ;循环

mov ax,4c00h
int 21h

code ends

end

总结:此程序类似C语言中的循环,通过段寄存器DS和ES、BX自加、 以及循环,达到复制内存的目的。其中bx的作用就相当于C语言中的自加量i的作用。C代码如下

1
2
3
4
5
6
char i;
for(i = 0; i < 12; i++)
{
ds[i] = es[i];
i++;
}


包含多个段的程序

在计算机运行程序时,程序和数据都是以二进制形式加载到内存中,实际上程序段和数据段对于计算机来说并没有任何不同。但是对于编程人员来说并不是一件好事,我们希望程序和数据以及堆栈分开存放。那么就需要对程序进行分块了。

第七个程序

交换内存中数据段前两个双字单元的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
assume cs:code,ds:data,ss:stack

data segment ;定义数据段
dw 0123h,0456h,0798h,0abch,0defh,0fdeh,0cbah,0987h
data ends

stack segment ;定义栈段
dw 0,0,0,0,0,0,0,0
stack ends

code segment ;定义代码段

start: mov ax,data ;数据段地址给到ds
mov ds,ax

mov ax,stack ;栈段地址给到ss
mov ss,ax
mov sp,16 ;栈段指针指向栈底



push ds:[0] ;把数据段的ds:[0]单元的双字内容 压入栈
push ds:[2] ;把数据段的ds:[2]单元的双字内容 压入栈
pop ds:[0] ;出栈到ds:[0]单元
pop ds:[2] ;出栈到ds:[2]单元

mov ax,4c00h
int 21h

code ends

end start

通过debug调试器可以即将运行的代码看到date段的地址为0b36h,通过d命令查看内存0b36处的内容,正是在程序中定义的数据段0123h,0456h,···,0987h
栈段地址为0b37h,在内存中0b36:0010单元处即为在程序中定义的全0的栈段。

经过两次入栈和出栈之后,可以看出date段的前两个双字节中的数据已经交换了位置。

第八个程序
使用push指令将a段中的前八个字形数据逆序存储到b段中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
assume cs:code

a segment ;a段数据
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段数据
b ends

code segment ;代码段

start: mov ax,b ;把栈段指针指向b数据段
mov ss,ax
mov sp,16

mov ax,a ;数据指针指向a段数据
mov ds,ax
mov cx,8 ;设置8次循环
mov bx,0 ;变量bx初值为0

s: push ds:[bx] ;开始8次压栈
add bx,2 ;bx自加2
loop s

mov ax,4c00h
int 21h
code ends

end start

如图执行数次循环后,a段数据已经逆序存储在b段中