编写流程
-
定义一个段
-
实现处理任务
-
指出程序在何处结束
-
段与段寄存器关联
-
加上程序返回代码
-
示例如下:
assume cs:abc abc segment mov ax,2 ... mov ax,4c00h ; 此行与下一行为返回代码 int 21h abc ends end
-
栈定义
push,pop是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同之处在于,push和pop指令访问的内存单元的地址不是在指令中给出,而是由SS:SP指出。
-
执行push和pop指令时,SP中的内容会自动改变
-
push(入栈)和pop(出栈)指令
-
push ax: 将ax中的数据送入栈中
SP = SP - 2;
将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。
-
pop ax: 从栈顶取出数据送入ax
将SS:SP指向的内存单元处的数据送入ax中
SP = SP+2, SS:SP指向当前栈顶下面的单元,以当前栈顶下的单元为新的栈顶
栈寄存器
-
栈段寄存器SS – 主要存放栈顶的段地址
-
栈顶指针寄存器SP – 存放栈顶的偏移地址
任意时刻,SS:SP指向栈顶元素
注意: SS指向的是栈内存起始地址,SP指向从起始地址至偏移的地址,当添加数据时是移动SP指针进行偏移,但是SP指向的最终位置,于是栈内存的增长是由低至高。
需要特别注意栈顶指针越界的情况。
段定义
-
一个汇编程序是由多个段组成,这些段被用来存放代码,数据或当作栈空间使用。
-
一个有意义的汇编程序中至少要有一个段,该段用以存放代码。
-
定义程序中的段:每个段都需要有段名。
- 段名 segment – 程序段起始
- 段名 ends – 程序结束
示例如下:
assume cs:codesg codesg segment mov ax, 123H ..... codesg ends end
-
end:汇编程序的结束标记,若程序结尾不加end,编译器在编译程序时,无法知道程序在何处结束。
-
assume:假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联–如上,assume cs:codesg指cs寄存器与codesg关联,将定义的codesg当作程序的代码段使用。
编译文件
- 目标文件(*.OBJ) 对源程序进行编译要得到的最终结果。
- 列表文件(*.LST) 编译器将源程序编译为目标文件的过程中产生的中间结果。
- 交叉引用文件(*.CRF) 编译器将源程序编译为目标文件过程中产生的中间结果。
[]与()的约定
-
[] – 表示一个内存单元。
-
() – 表示一个内存单元或寄存器中的内容。
-
一个内存单元包含内存单元的地址和内存单元的长度(类型),内存单元的地址包含段地址和偏移地址。
-
例如:
ax中的内容为0010H,解释为(ax) = 0010H
mov ax,[2],解释为(ax) = ((ds) * 16 + 2)
Loop指令
功能:实现循环。
指令格式
- loop 标号
CPU执行loop指令时要进行的操作:
- (cx) = (cx) - 1;
- 判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
示例如下:
assume cs:code
code segment
mov ax,2
mov cx,11
s: add ax,ax ; s为标号
loop s
mov ax, 4c00h
int 21h
code ends
end
注意: cx寄存器中要存放循环次数,因为cx寄存器影响loop指令的执行结果。
编写要点:
- 在cx中存放循环次数。
- 用标号指定循环开始的位置。
- 在标号和loop指令的中间,写上要循环执行的程序段(循环体)。
段前缀异常及对策
出现在访问内存单元的指令当中,用于显式地指明内存单元的段地址的"ds:",“cs:”,“ss:”,“es:”,在汇编当中称为段前缀。
例如:
mov al,[0] ;是将DS:0的数据传递给al寄存器
mov al, 0 ; 但编译之后的可能是直接将0传递给了寄存器
以上情况需要在[idata]前显式地写上段寄存器
mov ax,2000h
mov ds,ax
mov bx,0
mov al,[ds:][bx]
汇编代码结构
assume cs:code
code segment
;....
begin: ; 标识代码开始的位置
;....
code ends
end begin ; 除了通知编译器程序结束外,还可通知编译器程序入口地址
例如:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch
start: ; 标识代码开始的位置
mov bx,0
mov ax,0
mov cx,8
s: add ax, cs:[bx]
add bx,2
loop s
mov ax, 4c00h
int 21h
code ends
end start ; 标识代码结束的位置
示例代码
循环中要访问的内存单元的偏移地址放到bx中,随循环递增,访问连续的内存单元。
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov bx,0
mov dx,0
mov cx,12
s: mov al,[bx]
mov ah,0
add dx,ax
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end
将内存ffff:0–ffff:b中的数据拷贝到0:200–0:20b中
; 采用附加寄存器
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov ax,0020h
mov es,ax ; 使用附加寄存器
mov bx,0
mov cx,12
s: mov dl,[bx]
mov es:[bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
将数据逆序存放
assume cs:codesg
codesg segment
dw 0123h,0456h,0789h,0abch,0def,0fedh,0cbah,0987h
dw 0,0,0,00,0,0,0,0,0,0,0,0,0,0,0
start: mov ax,cs
mov ss,ax
mov sp,30h
mov bx,0
mov cx,8
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
codesg ends
end start