汇编语言学习笔记

1、debug 调试工具

参数:

-r    显示所有寄存器状态,可以修改寄存器内容(形如-r ax)

-d    显示从当前cs:ip位置之后的128个字节,可以指定地址打印(形如: -d 段地址:偏移地址)

-u    将cs:ip位置后续的字节翻译成汇编指令,可以制定地址翻译(形如: -u 段地址:偏移地址)

-a    在当前cs:ip位置处写指令,可以制定地址(形如: -a 段地址:偏移地址)

-t    执行当前cs:ip所指向的指令

-p    将当前循环体执行结束

-e    段地址:偏移地址 修改指定位置处开始后续的字节

-g    偏移地址 从cs:ip位置处开始,执行指令到指定位置处

2、

Byte = 8bit (字节型数据) =>  一个内存地址就能保存一个字节

Word = 2Byte = 16bit (字型数据) =>  一个字需要2个连续的内存单元来存放 高位地址存放高位字节 低位地址存放低位字节

3、寄存器

段地址 : 偏移地址
ds   si
es   di
ss   bp
cs   ip
    sp
    bx

cs:ip      所指向的内容为指令
ds:[0]    所指向的内容为数据(也可以为采用显式的表达方式: ds:[bx]等)
ds:[si]    数据从哪里来,一般的默认组合,也可以是ds:[bx+si+2]、ds:[bx+di]等
es:[di]    数据放到哪里去,同上
ss:sp      指向栈的栈顶数据,栈是以字为单位存放数据的

bx默认和ds是一对,ds:[bx]
bp默认是和ss是一对,ss:[bp]

4、指令执行的过程

<1> CPU从cs:ip所组成的地址中读取指令,将这个指令放到指令缓存器中
<2> IP = IP + 所读指令的字节数
<3> 执行指令缓存器中的内容,回到<1>继续执行

5、push、pop

push   sp - 2,将指定的数据放到ss:sp所指向的内存空间
pop    将ss:sp处的数据弹出到指定位置,pop + 2

6、loop

loop s    s 位标号

loop 条件转移指令(短转移),运行到loop指令时,cx -= 1,如果 cx == 0 循环结束,否则跳转到标号处继续执行
cx   存放循环的次数

7、数据不能以字母开头,如:FFFFH需要写成0FFFFH

8、安全的内存

0:200H ~ 0:2FFH 256个字节
0:7E00H之后

9、内存的分配是按16字节的倍数分配的

10、

db(define byte)   定义字节型数据,占1个字节
dw(define word)    定义字型数据,占2个字节
dd(define double)    定义双字型数据,占4个字节

11、定义data segment和stack segment后,数据和栈存放的内存与指令存放的内存相邻(不足16字节要补齐),即与cs:ip位置相邻,但是ds和ss还需要人为设置

12、大小写转换问题

字符   ASCII码  二进制形式
A    41H    0100 0001B
B    42H    0100 0010B
C    43H    0100 0011B

a    61H    0110 0001B
b    62H    0110 0010B
c    63H    0110 0011B

大写 –> 小写  or 0010 0000B
小写 –> 大写  and 1101 1111B

小写 or 0010 0000B  =  小写
大写 and 1101 1111B  =  大写

13、

//以字的形式处理数据
mov word ptr ds:[0],1

//以字节的形式处理数据
mov byte ptr ds:[0],1

//以双字型的形式处理数据
mov dword ptr ds:[0],1

14、div

<1>除数 8bit或者16bit,存放在内存单元或者寄存器(一般bl/bx)中

<2>被除数 AX或者 AX和DX中
如果除数为8bit,被除数则为16bit,存放在AX中
如果除数为16bit,被除数则为32bit,AX存放低16bit,DX存放高16bit

<3>结果 如果除数为8bit,则AL存放商,AH存放余数
如果除数为16bit,则AX存放商,DX存放余数

语法:

div bl(bx)    ;即根据除数存放在哪里来决定被除数存放的位置

15、dup  重复指令

db 256 dup (0) 重复0这个字节256次

16、地址标号和数据标号

<1>地址标号

形如

s:  db '1234'

表示了内存单元的地址

mov ax,OFFSET s   得到标号s位置处的偏移地址

<2>数据标号

形如

s   db '1234'

不但表示了内存单元的地址,还表示了内存单元的长度

mov ds:[0],s    将字符'1'存放到指定位置,不需要特别指定长度

17、JMP   无条件转移指令

jmp word ptr ds:[0]   短转移: 修改ip
jmp dword ptr ds:[0]   段间转移: 修改cs:ip,cs存放高位数据,ip存放低位数据

18、转移指令

jmp、jcxz、loop、call等

标号处的地址 - 转移指令后的第一个字节的地址 = 位移

转移指令记录的不是目标地址,而是需要跳转的字节数

19、jcxz 条件转移指令(短转移)

jcxz s  s 位标号

jcx(j => jmp  cx => cx寄存器   z => zero)

当 cx == 0 时才进行跳转

20、inc、dec

inc ax      ;ax = ax + 1
dec bx      ;bx = bx - 1

21、nop  

cpu什么都不做,占用一个字节

22、屏幕显示

在显存中(B800:0开始),偶数地址存放的是ascii码,奇数地址存放的是前面字符的颜色

一行可以存放80个字符,占用160个字节
一共有25行
所以可以存放的字符数为 80 * 25
占用的字节数为 160 * 25

颜色编码
7 6 5 4 3 2 1 0
0 1 0 0 0 0 0 1 ===> 红底蓝字

7号位置  =>  闪烁
6号位置  =>  R red 背景
5号位置  =>  G green 背景
4号位置  =>  B blue 背景

3号位置  =>  高亮
2号位置  =>  R red 前景
1号位置  =>  G green 前景
0号位置  =>  B blue 前景

23、ret、retf

ret 近转移 pop栈中的元素给 ip
retf 段间转移 pop栈中的两个元素分别给 ip 和 cs

24、call  转移指令

将当前ip(ip = ip + ip所读字节数) push 入栈,然后跳转到标号地址

call s   s为标号,与ret配合使用,push ip
call far ptr s  与retf配合使用,push cs, push ip

注意:
call s  指令记录的是位移,不是目标地址
call far ptr s  指令记录的是目标地址,不再是位移

25、mul  乘法指令

<1> 8bit乘法
一个数存放在al中,另一个数存放在其他8bit寄存器或内存中,结果存放在ax中

<2> 16bit乘法
一个数存放在ax中,另一个数存放在其他16bit寄存器或内存中,结果的高16bit存放在dx中,低16bit存放在ax中

语法:

mul byte ptr ds:[0]
mul word ptr ds:[0]

26、标志位寄存器/程序状态字(PSW)

和运算指令有关,移动指令等不影响标志位

15   14   13   12   11   10   9   8   7   6   5   4   3   2   1   0
                    OF   DF   IF  TF  SF  ZF      AF      PF      CF

标志 真  假
OF   OV   NV    O = overflow,OV = overflow,NV = not overflow
          判断运算过程中是不是溢出,有符号运算

DF   DN   UP    DN = down,UP = up
          与串传送指令配合使用

IF

TF

SF   NG   PL     S = sign,NG = negative,PL = positive ?
          判断运算结果是不是负数,mul不影响标志位

ZF   ZR   NZ     Z = zero,ZR = zero,NZ = not zero
          判断运算结果是不是0,mul、div不影响标志位

AF

PF   PE   PO     P = parity,PE = parity even,PO = parity odd
          判断运算结果中1的个数是不是偶数

CF   CY   NC     C = carry,CY = carry yes,NC = not carry
          判断运算结果是不是有进位,无符号运算

27、adc、sbb

adc ax,bx ax == ax + bx + carry

sbb ax,bx ax == ax - bx - carry

28、cmp

cmp ax,bx   两数相减,修改标志位,不记录结果

如果ax == bx   zf = 1
如果ax != bx   zf = 0
如果ax < bx   cf = 1
如果ax >= bx   cf = 0
如果ax > bx   cf = 0 && zf = 0
如果ax <= bx   cf = 1 || zf = 1

无符号比较,一般配合如下短转移指令使用

je 标号  ==>  jmp equal
jne 标号  ==>  jmp not equal
jb 标号  ==>  jmp below
jnb 标号  ==>  jmp not below
ja 标号  ==>  jmp above
jna 标号  ==>   jmp not above

有符号比较,结论如下

cmp al,bl
;SF = 1  OF = 0
;al < bl

;SF = 1  OF = 1
;al > bl

;SF = 0  OF = 0
;al > bl

;SF = 0 OF = 1
;al < bl

如果因为溢出导致实际结果为负,那么逻辑上真正的结果必然为正
如果因为溢出导致实际结果为正,那么逻辑上真正的结果必然为负

29、串传送指令

rep movsb   字节传送
rep movsw   字传送

mov cx,**
mov ds,**
mov si,**
mov es,**
mov di,**
cld     //设置DF = UP(0),相当于执行inc si, inc di
rep movsb   //将ds:[si]处的数据以字节为单位复制到es:[di]位置处
          复制次数由cx决定

cld     //add si,2  add di,2
rep movsw   //将ds:[si]处的数据以字为单位复制到es:[di]位置处

30、pushf、popf

push、pop标志位寄存器 f ==> flag

31、中断

中断是CPU处理外部突发事件的一个重要技术。它能使CPU在运行过程中对外部事件发出的中断请求及时地进行处理,处理完成后又逻辑返回断点,继续进行CPU原来的工作。

<一> 内部中断

不可屏蔽,硬件出错或者运算出错所引起的中断,例如:
<1> 除法错误 divide overflow
<2> 单步执行
<3> 执行into指令
<4> 执行int指令

<二> 外部中断

可以屏蔽也可以不屏蔽,一般是指由计算机外设所发出的中断请求
例如:键盘中断,打印机中断,定时器中断等

可以通过cli和sti指令修改IF标志位,屏蔽外部中断请求

cli  IF = 0,屏蔽外部中断
sti  IF = 1,不屏蔽外部中断

31、中断向量表

记录中断处理程序入口的 CS:IP

表存在的位置: 0000:0000 ~ 0000:03FFH

IP = 0000:[中断类型码] * 4
CS = 0000:[中断类型码] * 4 + 2

32、中断过程

<1> 取得中断类型码
<2> 保存标志位寄存器到栈中 pushf
<3> 将标志位寄存器的第8位 TF 和 第9位 IF 设置为0
<4> push cs
<5> push ip
<6> cs = N * 4 + 2 ip = N * 4

中断处理返回的方法: iret (完成 pop ip、 pop cs、 popf)

33、shl、shr

逻辑移动指令

shl  往左边移动一位
shr  往右边移动一位

过程:
<1> 将一个寄存器或者内存单元中的数据向 左/右 移动一位
<2> 将移出的这一位放到CF中
<3> 最 低/高 位用0补充

mov al,1
shl a,1
执行之后,al == 0000 0010B,CF == 0

mov cl,3
shr al,cl   
向右移动3位,必须使用cl寄存器来指定移动的位数

35、通码 断码

通码是键盘按键按下的状态编码
断码是键盘按键松开的状态编码

36、直接定址表

可以根据数据,直接计算出所要找的元素的位置的表,我们称其为直接定址表

37、键盘处理的过程

<1> 键盘的输入到达 60H 端口
<2> 相关芯片向CPU发出中断类型码为9的可屏蔽中断信息
<3> 如果IF = 1,那么执行 int 9 中断

38、int 9

<1> 读出 60H端口的扫描码
<2> 如果是字符键的扫描码,将这个扫描码和对应的ASCII放到BIOS中的键盘缓冲区
如果是控制键,将其转变为状态字节,记录到一个存储状态的字节单元中(0040:0017)
<3> 对键盘系统的相关控制,比如说,向相关芯片发出应答事情

键盘缓冲区
可以存放15个字型数据,高位存放扫描码,低位存放ASCII码

39、int 16H

从键盘缓存区读取数据

mov ah,0    设置功能号
int 16H

过程:

<1> 检测键盘缓冲区是否有数据
<2> 如果没有数据继续检测
<3> 读取缓存区第一个字型数据的键盘输入
<4> AH = 高位(扫描码) Al = 低位(ASCII码)
<5> 删除键盘缓存区中被读取的字型数据

40、ret、retf、iret

ret 弹出一个参数,给ip
retf 弹出两个参数,一个给ip,一个给cs
iret 弹出三个参数,一个给ip,一个给cs,一个给flag标志位

41、软盘

分为上下两面(0 ~ 1),一面有80个磁道(0 ~ 79),一个磁道有18个扇区(1 ~
18),一个扇区有512个字节

2 * 80 * 18 * 512B = 1440KB

1440KB / 1024 约等于 1.44MB

42、int 13H

;软盘 ==>> 0:200H
mov ax,0
mov es,ax
mov bx,200H ;es:[bx]

mov al,1    ;读取的扇区数
mov ch,0    ;磁道号
mov cl,1    ;扇区号
mov dl,0    ;驱动器号   软驱A: 0    软驱B: 1
mov dh,0    ;面号/磁头号
mov ah,2    ;设置状态为 读取

int 13H


;0:200H ==>> 软盘
mov ax,0
mov es,ax
mov bx,200H ;es:[bx]

mov al,1    ;读取的扇区数
mov ch,0    ;磁道号
mov cl,1    ;扇区号
mov dl,0    ;驱动器号   软驱A: 0    软驱B: 1
mov dh,0    ;面号/磁头号
mov ah,3    ;设置状态为 写入

int 13H

猜你喜欢

转载自blog.csdn.net/qq_34342154/article/details/79294512