chap1.2_数据和指令

1 指令执行

1.1 指令寻址

cs寄存器,ip寄存器

每次从 [cs,ip] 指向的内存位置取一条指令执行,执行后ip值增加,指向下一条指令的内存位置

CPU执行时,会一直的从内存单元中读取指令,坊到指令缓冲器执行。而取指令时,是根据CS寄存器和IP寄存器来获取一个地址[CS:IP]。这个地址指向内存单元中的代码段。CPU从中读取一条指令执行,然后IP指向下一条指令,继续读取执行。如此循环。

[CS+IP]:CS=段地址,IP=偏移地址。CPU一直从[CS+IP]指向的内存单元处读取指令。

1.2 访问数据
当CPU需要获取一个数据时,这时候代码段中能够获得的是DS寄存器和一个偏移地址。
[DS*0x10 + 偏移地址],指定地址时候可以不显示的写出DS。
这个地址指向内存单元中的数据。CPU根据这个地址获取到需要的数据。
基本地址:DS存储的是基本地址,但是在程序中段寄存器DS一般可以不显示说明。只用 [偏移地址] 来表示内存单元的地址。
偏移地址:是一个常数,可以直接使用数字来表示,比如:[553]。也可以使用BX,BP,SI,DI(其他的寄存器不能表示内存地址)中的值来表示。比如[BX]
[DS+BX]:DS=段地址,BX=偏移地址,内存单元地址为DS*0x10+BX。计算其寻址能力根据可指定的内存范围大概为0-1M之间。

2.3 指令跳转

当CPU执行完一块内存中的代码段时,使用JMP命令来修改CS寄存器和IP寄存器的值。从而控制计算机指令执行的跳转。

jmp:jmp指令转移就是修改cs,ip寄存器的指向。来完成跳转的功能。JMP导致[CS:IP]指向新的内存单元,CPU从新的内存单元读取指令。

汇编指令

以nasm为例

1. 赋值操作

  • mov

mov ax, 0x1

1)将值赋给寄存器:mov 寄存器,寄存器|内存单元|立即数

1
2
3
mov ax,0x0018H  		;ax = 0x0018H
mov ax,[0x0c200H] ;ax = [ds:0x0c200H]
mov ax,bx ;ax = bx

1)将值赋给内存单元:mov 内存单元,寄存器|内存单元|立即数

1
2
3
mov [0x0a200H],0x0018H   	;ax = 0x0018H
mov [0x0a200H],[0x0c200H] ;ax = [ds:0x0c200H]
mov [0x0a200H],bx ;ax = bx

2. 算术操作

下面是算术操作指令的简单列表:

指令 说明
add 整数加
sub 减法
mul 乘法(无符号)
IMUL 乘法(有符号)
DIV 除法(无符号)
IDIV 除法(有符号)
INC 自增
DEC 自减
NEG 取反
CMP 比较大小

1)加法: add 寄存器,寄存器|立即数

add ax,0x0017H 	;ax=ax+0x0017H
add ax,bx			;ax=ax+bx

2)减法: sub 寄存器,寄存器|立即数

sub ax,0x0017H ;ax=ax-0x0017H
sub ax,bx ;ax=ax-bx

3)乘法(无符号): mul 寄存器.

使用寄存器: AX存放目标操作数,操作后AX和DX存放结果。

    mov eax 0x0100H
    mul 寄存器

4) 除法: div 寄存器|内存单元(除数).

使用寄存器: AX和DX存放被除数,操作后AX和DX存放商和余数。
​ div 寄存器|内存单元

5)自增1:inc 寄存器

inc ax

6) 自减1:dec 寄存器

dec ax

7)取补码:nec

3. 转移操作

指令 说明
JE 如果相等则跳转
JNE 如果不相等则跳转
JZ 如果为 0 则跳转
JNZ 如果不为 0 则跳转
JC 如果进位 则跳转
JNC 如果不进位 则跳转
JG 如果第一个操作数比第二个大则跳转
JGE 如果第一个操作数比第二个大或者相等则跳转
JA 与 JG 指令相同,只不过比较的是无符号数则跳转
JAE 与 JGE 指令相同,只不过比较的是无符号数则跳转

4. 跳转指令

jmp指令

cs寄存器,ip寄存器

通过修改 [cs,ip] 内容,达到跳转效果。

  • jmp near 短转移 : [ ip <- new ip val]
  • jmp far 远转移 : [ cs<- new cs val, ip <- new ip val]
  • jmp word 段间转移,可从32位跳转64位指令

call指令

cs寄存器,ip寄存器,栈寄存器

1)压栈当前指令位置 [ss, sp] <- [cs, ip]

  1. 跳转到函数执行

3)返回,出栈当前指令位置 [cs, ip] <- [ss, sp]

4)继续执行指令

  • call
  • call far
  • call world

ret指令

cs寄存器,ip寄存器,栈寄存器

3)返回,出栈当前指令位置 [cs, ip] <- [ss, sp]

4)继续执行指令

loop指令

cx寄存器

判断 [cs] 寄存器值是否为0,为0停止循环,不为0继续循环。

每次执行 [cs内容]=cx-1

5. 栈操作

栈寄存器

首先CPU进行出栈入栈操作时,需要先分配一段栈空间的内存,来存储数据使用。

这段内存的位置由栈段寄存器SS和栈指针寄存器SP来指定。

1
栈顶地址 = 栈段寄存器SS << 4 + 栈指针寄存器SP

每次进行出栈入栈操作时,SS和SP会更新得到新的栈顶位置。

我们可以通过指定 栈段寄存器SS和栈指针寄存器SP的值来初始化栈空间分配。

栈顶地址: [ss:sp] (默认 [ss:0xf] )

栈空间 : [ss:0] -> [ss:0xf]

push指令

push:入栈,将寄存器的数据入栈

ss寄存器,sp寄存器

通过修改 [ss,sp] 内容,改变栈顶位置

[cs, sp] <- 栈顶位置

执行后, 栈值增加,指向新的地址

[cs,sp+2] <- 栈顶位置

pop指令

pop: 出栈,数据存储到寄存器中

ss寄存器,sp寄存器

通过修改 [ss,sp] 内容,改变栈顶位置

执行后, 栈值减少,指向上一个地址

[cs,sp-2] <- 栈顶位置

其他指令

CLI : Clear Interupt

STI :Set Interupt

CLD : Clear Director

STD :Set Director

REP:Repeat

MOVSB: Move String Byte