微机原理学习笔记

汇编语言程序设计

这篇文章是一年之前学微机原理时写的,现在改一下格式重发到CSDN博客上。主要内容是汇编语言。

1 汇编语言程序及其开发

源程序经过汇编成为目标程序,再将目标程序连接成为exe程序,最后进行执行和调试。

2 汇编语言源程序的结构

(1)执行性语句和说明性语句。

汇编语句分为执行性语句说明性语句

执行语句最后会转变为机器码,即01数据存储在内存中;
说明性语句由编译器处理,不会生成机器码。

执行性语句格式:

a:mov ax,0;将ax寄存器置0

说明性语句格式:

a dw 3;在内存中申请一个字的空间,在里面放入0003,这段空间的起始地址为a

(2)定义段

比如:

stacksg segment  para   stack 'stack'
段名     定位类型 连接方式     类别名

段名:stacksg即此段的起始地址 。

定位类型:有四种定位类型:
para类型:表示此段的起始地址的最低四位必须是0;
page类型:表示此段的起始地址的最低八位必须是0;
word类型:表示此段的地址必须为偶数;
byte类型:表示此段可以从任何地址开始。
默认的缺省定位类型为para类型。

连接方式:如果我们有多个目标程序,我们对他们进行连接的时候就要使用连接方式。现在我们只需要学习at连接方式,at后面加一个地址,表示这个段的段地址,at连接方式不能用于代码段。

类别名:也是在连接时使用的。

常见的定义段的方式:datasg segment at 1000h

(3)equ伪指令

equ是等价的意思,相当于c++中的引用。

比如:

const equ 10h

这里我们定义了一个const,它等价于10h。
需要注意的是,用equ定义的符号名在同一程序只能定义一次,不许重复定义

(4)=伪指令

比如:

const   =   10h

这里的const允许在后面再进行更改,也就是说可以重复定义。

(5)数据标号

比如:

a   dw   0,0,0,0

这句话在内存中分配4个字的空间,都赋值成0。
这里a就是数据标号,它同时描述了内存地址和单元长度。从今以后,a就是这四个零的地址,并且说到a必须是字,把它赋给字节或者双字都不行。

一种特殊的数据标号指令:

a   dw   ?

这里在内存中费配了一个字的空间。使用?的意思是只开辟空间而不进行初始化。

(6)dup伪指令

比如:

a   db   100   dup   (00h)

表示开辟一百个字节空间,并全都赋值成00h

(7)ret和retf

ret指令用栈中的数据,修改ip的内容,从而实现近转移。
retf指令用栈中的数据,修改cs和ip的内容,从而实现远转移。

CPU执行ret指令时,相当于执行pop IP
CPU执行retf指令时,相当于执行pop IP pop CS

(8)过程定义伪指令proc和endp

过程就是子程序。一般会使用call指令调用子程序,子程序的最后一条指令一般是ret,用于返回shell。
比如:

delay proc near        
      push cx    ;将cx的值入栈,以免丢失,等子程序运行完,返
                 ;回原程序时再出栈
      mov cx,30h ;通过设置cx的值改变延时的时间
wait:loop wait
      pop cx     ;cx出栈
      ret        ;返回原程序
delay endp

其中的near表示是段内转移,如果是段间转移的话要换成far。
delay 和endp必须成对出现。

(9)org指令

用来设置偏移地址。
比如:

data segment
     a db 23,56
     org 2000h
data ends

表示a的偏移地址为2000h

3 常数、变量及标号

一个字符对应一个字节。
比如:‘a’对应41h

4 表达式和运算符

(1)算数运算符

+-*/:加减乘除

mod:取余

shl和shr:shl和shr是逻辑移位指令。
shl是逻辑左移指令,它的功能为:
①将一个寄存器或内存单元中的数据向左移位;
②将最后移出的一位写入CF中;
③最低位用0补充。
比如:

mov al,01001000b
shl al,1 ;将al中数据左移一位

执行后(al)=10010000b,CF=0。
注意:
如果移动位数大于1时,必须将移动位数放在cl中。
比如:

mov al,01010001b
mov cl,3
shl al,cl

执行后(al)=10001000b,因为最后移出的一位是0,所以CF=0。
shr是逻辑右移指令,它和shl所进行的操作刚好相反。

(2)逻辑运算符

and:与
or:或
xor:异或
not:非

(3)关系运算符

使用关系运算符进行逻辑判定,如果判定结果是真返回全1(0FFFFH),否则返回0。

eq:等于
ne:不等于
lt:小于
le:小于等于
gt:大于
ge:大于等于

关系运算符一般不单独使用,常与其他运算符结合使用
比如:

mov   al,((a gt 60) and 50) or ((a le 60) and 70)      
;a大于60时,给al赋值50a小于等于60时,给al赋值70

(4)seg和offset

seg给出段地址,offset给出偏移地址。

(5)type

type操作符返回一个表示操作数的类型的数值。
字节类型返回1,字类型返回2,双字类型返回4,near标号返回-1(0FFFFH),对于far标号返回-2(0FFFEH)。

(6)length和size

一般与dup连用。
比如定义

a   dw   50   dup(0000)

则:length(a)=50 size(a)=100
其中size = length*type
另外对于用非dup定义的length返回1。

(7)high和low

high和low分别返回字的高字节和低字节。
比如:

a = 2050h
mov al,low a    ;al = 50h
mov ah,high a   ;ah = 20h

(8)$运算符

$是汇编语言中的一个预定义符号,等价于当前正汇编到的段的当前偏移值。

比如最常用的JMP $就是指转移到当前执行语句的地址,在这的效果就是原地跳转,不再向后执行了。
指令“jmp $+3”中的“$”表示当前这条指令在代码段中的偏移量。
指令“jmp $+3”表示要向前跳转到距离这条指令3个字节的地方。
若是“jmp $-3”,则表示要向后跳转到距离这条指令3个字节的地方。

$常见于动态定义数据长度,例如:

MyData       db   '123456789abcdefgh'
DataLength   EQU   $  -  MyData

(9)ptr

指明是字单元还是字节单元
比如:

mov   word  ptr  ds:[0],12h

5 8086/8088CPU汇编程序的输入与输出

使用DOS的功能通常要进行如下4个步骤
①在AH中设置功能号
②在指定寄存器中设置入口参数
③int 21h
④得到出口参数,可以用来分析执行的情况

(1)输入单个字符

功能号:01h
入口参数:用户从键盘输入
出口参数:al = 所输入字符的ASCII码
功能:用户从键盘输入一个字符,输入字符后返回,同时在屏幕上显示所输入的字符。ctrl+c退出。

比如:

mov   ah,1
int   21h

(2)输入字符串

功能号:0ah
入口参数:ds:dx指向字符串缓冲区的首地址,缓冲区的第一个字节存放最多接收的字符个数(包括回车)。入口参数由用户输入。
出口参数:ds:dx指向的第二字符存放实际输入的字符个数(不包括回车),从第三个字符开始存放输入的字符串。若实际输入的字符数比最大字符数多,多出来的字符会被丢弃并响铃。

比如:

buffer db 81        ;定义缓冲区,最多允许输入81个字符(包括回车)
db 0                ;定义实际存放的字符数
db 81 dup (0)       ;存放输入的字符串
mov dx,seg buffer   ;取得buffer的段地址
mov ds,dx                             
mov dx,offset buffer;取得buffer的偏移地址
mov ah,0ah
int 21h

(3)显示单个字符

功能号:02h
入口参数:dl=要显示的字符的ASCII码
功能:在显示器当前光标出显示单个字符,然后光标右移一个位置。ctrl+c退出。

比如:

mov   ah,02h
mov   dl,41h
int      21h

(4)显示字符串

功能号:09h
入口参数:ds:dx指向字符串的首地址,注意字符串必须以$结束。
功能:在显示器上输出指定的字符串。

比如:

string   db 'hello$'
mov      dx,seg string
mov      ds,dx
mov      dx,offset string
mov      ah,09h
int      21h

(5)磁盘输入输出


说明:
①文件名字符串以0作为结束标志。
②cx中的文件属性有:00(标准文件)、01(只读文件)、02(隐含文件)、04(系统文件)。
③ax中的错误码有:1(无效功能号)、2(文件没找到)、3(路径未找到或文件不存在)、4(打开文件太多)、5(拒绝存取)。

6 高级汇编技术

(1)宏汇编

宏是为了减轻程序猿的负担,它有点像高级语言中的函数。
我们先会定义一个宏,然后在需要它的时候使用它。编译器看到我们使用宏,会在这个地方把代码补全。

定义宏:

a   macro   x,y,z              ;;a是宏名,xyz都是形参
    mov     ax,0
    endm                       ;;宏以endm结束

宏定义一般出现在程序的开头。
宏定义中的注释要以;;开始

调用宏:

a   4,al,al

猜你喜欢

转载自blog.csdn.net/dreamiond/article/details/73038550