汇编基础知识

一、计算机体系

 

总线分为:地址总线,数据总线,控制总线

地址总线宽度数据总线宽度
808620(寻址空间2^20)16
802862416
803863232

在16位cpu体系:

物理地址=基础地址+偏移地址=段地址*16+偏移地址

段基础地址=段地址*16

偏移地址=16位=2^16=[0000, FFFF]

段寄存器:用于保存段地址,CS,DS,SS,ES

IP:指令指针寄存器=偏移地址

在8086机下,物理地址=指令地址=CS*16+IP

x86通用寄存器:eax,ebx,ecx,edx,esi,edi,ebp,esp。e代表extend,扩展到32位

二、指令寄存器cs、ip

修改cs,ip寄存器只能用,jmp指令,不能用mov指令,格式:jmp 段地址:偏移地址,段地址用于cs,偏移地址用于ip。

若只修改ip的内容,可以通过 "jmp 某一合法寄存器",例如: jmp ax,jmp bx

三、数据寄存器ds & bx

在8086下,物理地址=段地址*16+偏移量,数据的段地址保存在ds寄存器中,bx保存偏移地址

比如访问物理地址10000H,应该执行如下命令

mov bx, 1000H

mov ds, bx

mov al, [0]

说明:

1) 物理地址10000H = 1000H*16 + 0 ==> 段地址是1000H,偏移地址是0

2) ds是段寄存器,必须通过一个通用寄存器周转一下才可以,写入1000H

3) [0],表示偏移量,mov al [0] 会默认从ds寄存器中取出段地址,因此在执行此步骤之前必须讲ds寄存器设置正确

如果寄存器值写回内存地址,应该是mov [0] al

三、栈寄存器ss sp

ss:栈基址,栈底地址=ss*16

sp:偏移量,栈顶

在一个栈空间,ss是不变的,只有sp在改变。入栈,sp是从高地址向低地址改变。

【问题】

如果将10000H~1FFFFH这段空间当作栈段,初始状态栈是空的,此时,SS = 1000H, SP = ?

这个题非常好,说一下我解题思路。

1)首先入栈是从高地址向低地址改变(反之,是出栈)。也就是说栈基址就是10000H,那么用栈寄存器保存就应该是1000H (1000H*16 = 10000H),所以ss=1000H,是没有问题的。那么sp是多少呢?

2)题目中1FFFFH是边界,而且我们知道栈操作是按照字为单位的(也就是两个字节),那么第一个入栈元素占用的空间地址就是  1FFFEH 1FFFFH,如下图所示:

 也就是说SP指向1FFFEH时栈中有一个元素,那么当栈中没有元素,应该指向20000H。但是,SP寄存器是16位的,只能保存0000,所以这道题SP=0

引伸题:当栈空的时候sp=0,当栈满的时候sp=?

我们知道sp和ss指向同一个地址的时候代表栈满,所以根据公式,物理地址=SS*16+SP=10000H 且SS=1000H,最终SP=0。也就是说当栈满的时候sp=0。那么问题就来了,sp=0的时候,是栈空还是栈满呢?这个需要根据上下文才能确定,sp指向的实际地址,或者说需要程序员来保证。

四、中断

中断分为内中断和外中断

内中断:是由cpu内部抛出来的中断,例如除以0,int指令

外中断:是外部设备(比如网卡)发出的中断

发生中断后,需要将当前的标志寄存器、cs、ip压入栈中进行保存,然后根据中断码,从中断向量表中获取,中断处理程序的入口,即重新设置cs,ip

在8086cpu机器下,中断向量表起始地址是0000:0000 ~ 0000:03FF(256个),一个中断向量表中的一个表项大小是两个字(4个字节),高地址字存放的段地址,低地址字存放的偏移地址,所以cs = 4*N+2,ip = 4*N

我们单步追踪程序,是由cpu提供了单步中断功能实现的(本质是,标志寄存器TF标志控制)

五、寄存器列表

寄存器解释备注
通用寄存器AH&AL=AX(accumulator)累加寄存器
BH&BL=BX(base)基址寄存器用于寻址
CH&CL=CX(count)计数寄存器
DH&DL=DX(data)数据寄存器
DI目的变址寄存器bi,si的功能和bx类似,但是bi,si不能拆成8位寄存器
SI源变址寄存器
段寄存器CS(Code Segment)代码段寄存器(指令寄存器)
DS(Data Segment)数据段寄存器
SS(Stack Segment)堆栈段寄存器
ES附加段寄存器

地址偏移

寄存器

SP(Stack Pointer)堆栈指针寄存器,与SS配合
BP(Base Pointer)基址指针寄存器
IP(Instruction Pointer)指令指针寄存器,与CS配合

六、常用指令

指令形式举例
movmov 寄存器, 数据mov ax 0123H ==> ax = 0123H
mov 寄存器, 寄存器
mov 寄存器, 内存单元

该形式使用的时候需要注意:

在window debug模式下,是可以直接

mov ax [x]

但是在编码的时候不可以,因为编译器会把[x],当成数字x使用

在编码的时候需要,有两种方式:

1)将地址数字先存到寄存器中,

mov bx 1000H

mov ax  [bx]

2)在地址前面写上ds

mov ax ds:[x]

mov 内存单元, 寄存器

mov 段寄存器, 寄存器
mov 寄存器, 段寄存器
mov 内存单元, 段寄存器

mov 段寄存器, 内存单元

mov 寄存器, [bx]

段地址在ds中, 偏移地址在bx中,将这个内存单元存储到ax中
mov word ptr 

lea 

取源操作数地址的偏移量,并把它传送到目的操作数所在的单元

SI=1000H , DS=5000H, (51000H)=1234H
执行指令 LEA BX , [SI]后,BX=1000H
执行指令 MOV BX , [SI]后,BX=1234H

add 加法指令add 寄存器, 数据
add 寄存器, 寄存器add ax, bx ==> ax=ax+bx
add 寄存器, 内存单元
add 内存单元, 寄存器

sub 减法指令

sub 寄存器, 数据
sub 寄存器, 寄存器sub ax, bx ==> ax=ax-bx
sub 寄存器, 内存单元
sub 内存单元, 寄存器
div 除法指令

div reg

div 内存单元

除数: 有8位和16位两种,在一个寄存器或内存单元中.

被除数: 默认放在AX和DX或AX中

  除数为8位, 被除数为16位, 默认在AX中存放.

  除数为16位, 被除数为32位, 在DX或AX中存放. AX存放低16位,DX存放高16位.

结果

  除数为8位, 则AL存储除法操作的商, AH存放余数

  除数为16为, 则AX存储除法操作的商, DX存放余数

mul乘法指令

mul reg

mul 内存单元

数据:两个相乘数,要么都是8位,要么都是16位。 如果是8位,一个数字默认存放在al中,另外一个数字存放在其他8位寄存器中或者字节型内存单元中。

如果是16位,一个数字默认存放在ax中,另外一个数字存放在其他16位寄存器中或者字型内存单元中。

结果:8位乘法,得到一个16位数, 结果存放在ax中 16位乘法,得到一个32位数, 低16位存放在ax中,高16位存放在dx中

push

只能用于操作,不可以操作字节

push 寄存器
push 段寄存器
push 内存单元将某个内存单元,压入栈,

pop

只能用于操作,不可以操作字节

pop 寄存器
pop 段寄存器
pop 内存单元出栈,将数据写入内存单元
loop

循环指令,需要结合cx寄存器一起使用

incinc 寄存器用于自增
and逻辑与
or逻辑或
dup

伪指令,用于分配内存

db 3 dup (0) 等价

db 0, 0, 0

jmp可只修改ip,或者修改ip和cs

jmp short 标号 (短转移,-128~127)根据当前ip所在位置进行偏移,即ip = ip + 8bit位移

jmp near ptr 标号  段内近转移,

ip = ip + 16bit位移

jmp far ptr 标号 段间远转移,可同时修改cs和ip两种寄存器(段间转移,高地址处的字是目的段地址,低地址处的字是偏移地址)

例如:机器码=EA0B01BD0B 可得

段地址=0BBD

偏移地址=010B

jmp 16位寄存器,  转移地址在16位寄存器中,等效于ip = 寄存器值
jmp word ptr 内存单元地址 (段内转移)
jmp dword ptr 内存单元地址 (段间转移,高地址处的字是目的段地址,低地址处的字是偏移地址)
jcxz条件转移,段内短转移

jcxz 标号 (偏移 -128 ~ 127)

含义:当寄存器cx等于0,跳转,反之不跳转

与loop指令正好相反

call调用子程序,将ip 或 cs、ip入栈call 标号 (将ip入栈)
call far ptr 标号(先cs入栈、再ip入栈)
call 寄存器(16bit,将ip入栈)
call word ptr 内存单元地址(将ip入栈)
call dword ptr 内存单元地址(先cs入栈、再ip入栈)
ret

ret 用栈中数据修改ip,实现短转移

ret指令,等价

(ip) =((ss)*16 +(sp))

(sp) = (sp) + 2

retfretf用栈中数据修改cs、ip实现远转移

retf指令,等价

(ip) =((ss)*16 +(sp))

(sp) = (sp) + 2

(cs) = ((ss) * 16 + (sp))

(sp) = (sp) + 2

iret中断处理程序中必须使用此指令进行返回

该指令等价于:

pop ip

pop cs

popf

db定义一个字节
dw定义一个字(2字节)
dd定义一个双字(4字节)
movsb将ds:si指向的内存单元中字节送入es:di,然后si、di根据标志寄存器DF表示,进行递增、递减

DF=0   si、di递增1

DF=1   si、di递减1

movsw将ds:si指向的内存单元中字送入es:di,然后si、di根据标志寄存器DF表示,进行递增2、递减2

DF=0   si、di递增2

DF=1   si、di递减2

rep movsb

rep movsw

通过cx控制循环次数

rep movsb 等价

s: movsb

    loop s

cld将标志寄存器df设置为0
std将标志寄存器df设置为1

pushf

popf

将标志寄存器压/出栈
in从端口读数据in al, 60h,从端口编号60中读取数据,并保存在al中
out将数据写入端口out 20h, al  注:in out只能利用ax,al寄存器
shl、shr

左移,右移操作

移出的数据保存在CF中

mov al, 11001000b

shl al, 1  

左移1位, al = 10010000b   CF=1

注意:add ds, ax 不可以

寻址方式,如下图所示:

AT&T汇编风格:《GCC汇编器语法》

《64位寄存器-寄存器名称与数据类型》​​​​​​​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值