汇编语言c equ a-b,汇编语言学习笔记(全)

汇编语言分位数和标准,位数是根据cpu寄存器的位数发展而变化,而标准主要有两类:

AT&T 标准, 主要用于UNIX和 类UNIX系统

Intel 标准

本文是基于16位因特尔标准

汇编语言基础

三种基本的汇编语言成员:

指令:

[name:] mnemonic [[dest][,src]][;comment]

伪指令

[name] directive [[operand][,operand,...]][;comment]

macros 宏

命名规则和基本的c/c++命名规则差不多,主要关注以下可以使用哪些符号

? _ @ $ 可以使用

长度不要超过31个字符。 第一个字符不能是数字。

数据类型:

类型

简写

大小

BYTE

DB

1B

WORD

DW

2B

DWORD

DD

4B

FWORD

DF

6B

QWORD

DQ

8B

TBYTE

DT

10B

REAL4

DD

4B

REAL8

DQ

8B

REAL10

DT

10B

汇编语言编译过程

src.asm ---(汇编器)---- c.obj ---(连接器)--- xx.exe

伪指令

变量声明

label WORD [值,‘?’]

算了,还是直接举例子把:

a BYTE 'A'

b WORD 1111H

C BYTE 128

D BYTE 1,2,3,4,5 ; 数组

E BYTE "i LOVE U",'$' ;字符串结尾必须有'$'

F BYTE 'I LOVE "U..zcdsadfasdft" '

DUP

a BYTE 30 DUP(5) ;重复 30个5

OFFSET 和 SEG

这是两个比较常用的,

MOV AX, OFFSET VAR1

MOV BX, SEG VAR1

一个是取偏移地址,一个是取段地址。

算数运算

+,-,*,/ 。。。 比较弱的功能,好像只支持 常数之间的运算和变量之间的地址运算,如:

MOV DX, BLOCK +(6-1)*2

MOV CX, (VAR1-VAR2)/2

PTR

常用,用于类型转换

MOV AL, BYTE PTR var

MOV BYTE PTR [BX],10

SHORT

后面跳转会用到,不常用

EQU 和 =

都是复制,只不过EQU 类似于 c系语言的宏定义,不可改变, =类似于=,可以改变。

ORG

常用,用于将当前程序指针指向某一个位置,与$搭配使用。

ORG expression

ORG $ + expression ; $ 代表当前地址,

ORG $+1 ; 意味着跳转到下一行, 常用于 对齐存储方式。。。。。

汇编代码框架

.8086

.model small

.stack

.data

;你的变量声明

.code

main:

;...

end main

.Other 段

汇编指令

转移指令

MOV 指令

MOV DST, SRC

将数据从 SRC 拷贝到 DST。MOV的使用有以下限制:

SRC 和 DST 不能都在主存或者都是段寄存器。

不能将立即数移动到段寄存器(可以用通用寄存器间接来)

不能对 FLAG 寄存器做此操作。

不能将任何数据移动到CS和IP寄存器。

不能再不同位长的寄存器之间移动。

PUSH 和 POP

PUSH SRC

将数据压入栈,操作步骤一般为:

SP上移,即 SP ← SP -2

((SP)+1,(SP) ) ← (SRC) 这里是小端对齐, 高位存在高地址。

另外,不要忘记, 可以将 PUSH 的对象可以为: 立即数,内存数,寄存器数(包括FLAG寄存器)都可以。

POP DST

将栈顶元素弹出到DST。操作顺序:

DST ← ((SP+1),(SP))

SP ← (SP) + 2

需要注意的是,DST不可以是CS寄存器。

加载地址指令

加载有效地址

LEA reg16/32, mem8/16/32

LEA: load effective address 加载有效地址到 寄存器。 有效地址就是偏移地址。例如:

if (DS) = 2000H, (BX) = 1234H. 则 LEA DI, [BX] 的执行结果为:

DI ← 1234H

if Symbol variable BUFFER is in 2000H:1234H. 则 LEA DI, BUFFER 的执行结果为:

DI ← 1234H

加载段地址 + 有效地址

LDS reg, mem

LES reg, mem

LFS reg, mem

LGS reg, mem

LSS reg, mem

这是 LEA 的 升级版本,但是, 千万要注意的是, 这些指令不会做像 LEA 一样的翻译的效果,而是直接将 mem内的数据载入 段寄存器和reg。例如:

if (DS) = 2000H, (BX) = 1000H。 内存中 (21000H,21001H,21002H,21003H)= (45H,D6H,00H,50H)

那么, LDS DI,[BX] 的效果为:

DI ← D645H

DS ← 5000H

交换指令

XCHG A , B

交换两者内部的值,值得注意的是:

两者长度要一致。

两者不能同时是段寄存器或者同时为内存数。

LAHF 和 SAHF

LAHF

Transfers Flag寄存器最右面的8位到AH寄存器。

SAHF

Transfers AH寄存器到Flag寄存器的最右面8位。

查表指令

XLAT

将AL 寄存器的值转换成 一个表里面的值。

表的偏移地址必须事先存在 BX 寄存器中。并且表元素的类型是byte。例如:

MOV BX, OFFSET TABLE

MOV AL, 4

XLAT

执行结果: AL ← 34H 34H 是表中第四个元素,表从0开始计数。

I/O 指令

IN AL/AX , I/O DEV

OUT I/O DEV, AL/AX

与I/O 设备的交互。 IO设备的寻址有两种方式存在:

固定端口寻址。 有的IO端口有固定的8bits的 端口地址。例如 IN AL, 52H

变动端口寻址。 端口地址存在DX。 例如 OUT DX, AL

算数指令

加法指令

ADD DST, SRC

DST ← (DST) + (SRC) 需要注意的是:

两个操作数位数要相同。

可以两个寄存器,也可以是寄存器和立即数,寄存器和内存数,内存数和立即数。 但不能是两个内存数。

更值得注意的是: 它的执行会影响:CF, SF, OF, PF ,ZF 和 AF。

ADC DST, SRC

DST ← (DST) + (SRC) + Carry。 考虑进位的加法。 同样会影响FLAG寄存器。

INC DST

DST ← (DST) + 1

需要注意:

也可以是内存数。

会对FLAG产生影响,但是! 不会对CF产生影响!!!!!!!!

减法指令

SUB DST, SRC

DST ← (DST) - (SRC) 需要注意的和 ADD 相同。

SBB DST, SRC

DST ← (DST) - (SRC) - Carry。

DEC DST

自减。 不会对CF产生影响。

NEG DST

DST ← 0 - (DST) 效果, 取反并加一。 对于负数来说, 就是求补。

CMP DST, SRC

通过 (DST) - (SRC) 来比较 两个操作数。 但是, DST 不会被改变!!!!!!!!! 通过对FLAG的影响来得到结果。

无符号数结果的判断:

ZF = 1. 相等。

CF = 0. DST 大于等于 SRC。

CF = 1. DST 小于 SRC。

有符号数结果的判断:

ZF = 1. 相等。

SF = OF, DST 大于等于 SRC。

SF != OF, DST < SRC。

乘除法指令

MUL SRC ; 无符号数

IMUL SRC ; 有符号数

SRC 可以是 寄存器数也可以是内存数。 被乘数存在 AX/AL寄存器当中。

对于8位数。 AX ← AL * SRC

对于16位数。DX : AX ← AX * SRC

需要注意的是:

结果的位数总是操作数的两倍

这个指令对 CF 和 OF 有影响。

CF = OF = 1. 表明 结果的 高一半不是0

CF = OF = 0. 表明 结果的 高一半 是 0

不会改变其他寄存器。

IMUL REG, SRC

IMUL REG, SRC, IMM

REG ← (REG) * (SRC) - (IMM) 注意, 在这里, 它们的尺寸是相同的。 16/32

DIV SRC

IDIV SRC

同MUL。被除数在AX里面。需要注意:

不要除0

商太大放不下。

会改变FLAG的值

商的位数是被除数位数的一半。 商存在低一半。 余数存在高一半。

还有就是不能乘除立即数。可以加减立即数。

符号扩展指令

CBW ; AL to AX

CWD ; AX to DX:AX

CWDE ; AX to EAX

CDQ ; EAX to EDX : EAX

BCD 码的调节

加法结束后,1010B ~ 1111B 对于BCD码来说是没有意义的。因此需要调节。 即进位。

AAA

例子:

MOV AL, 9H

MOV BL, 4H

ADD AL, BL ; overflow

AAA ; adjust to AH

所以最后, 整个结果扩展到 AH:AL。 并且改变 CF 和 AF 【= 1】(adjust flag 第三位有无进位)的值。

减法结束后,的调节。

AAS

同上, AF = CF = 1. 且 将正确结果整合到了AL。

BCD 乘法结束后的调节

AAM ; 和AAA 差不多

除法结束后调节

AAD ; 和 AAM 差不多

以上都是unpacked BCD 码的调节。 packed BCD 码如有需要,自查资料。

逻辑指令

与或非

AND DST,SRC

OR DST,SRC

XOR DST,SRC ; 异或

需要注意如下:

结果存在DST当中

DST和SRC 都可以是MEM, 但不可同时是MEM。

它们的使用技巧:

AND 转换 ASCII 到 digit integer

OR 转换 digit integer 到 ASCII

XOR 某一位取反 例如 : XOR CL, 00100000B . 因为0/1 与0异或不会改变。 0/1 异或会取反。

TEST 指令

和 AND 的效果一样,但是不会改变 DST 的值。

注意:

AND, OR , XOR, TEST 会改变 FLAG 的值。

CF = 0

OF = 0

AF undefined

PF, SF, ZF 和结果有关。

NOT 指令

求反指令

MOV AL, 1

NOT AL 各个位 取反

INC AL ; 取反加一?? 还记不记得 NEG

SHIFT 和 ROTATE

SHL DST, CNT ; 逻辑左移

SHR DST, CNT

SAL DST, CNT ; 算数左移

SAR DST, CNT

值得注意的是:

逻辑左移和算数左移没有什么区别

逻辑右移左面补0,算数右移左面补符(最高位)。

DST 可以是MEM数或者寄存器。 CNT 是8位立即数,1,或者CL

SHIFT 操作将会改变 CF, OF ZF ,PF, AF。 注意OF, 当shift 一位的时候,如果结果的符号和原来一样,OF = 0. 否则为1.

ROL DST, CNT

ROR DST, CNT

RCL DST, CNT ; 通过 CF 来移位

RCR DST, CNT

注意:

ROL, ROR 只是将出的位,保留到CF一份, CF不会对结果产生影响

RCL, RCR 是移动到CF, 在将原来CF的值填到另一端。

只会影响CF, OF(至对于一位ROTATE,如果符号变化,OF=1)

跳转指令

无条件跳转

JMP SHORT OPR ; OPR 可以是一个label 例如

JMP SHORT ADDT

.....

ADDT: MOV AL , AH

SHORT 的范围是同一个段的8位, +127 ~ -128

JMP OPR ; 16位。 +32767~-32768 当前段

JMP FAR PTR OPR ; can be another 段 32bits

SO....

JMP WORD PTR OPR ; 16 near jmp

JMP DWORD PTR OPR ; 32 FAR JMP

JMP REG16/32

条件跳转

跳转指令

跳转条件

JE / JNE

是否相等(其实考察的是ZF)

JAE/ JGE

A

JBE/ JLE

A <= B

JC/JZ/JS/JO/JP

当相应的CF, ZF, SF, OF, PF 寄存器为1时跳转

跳转表

传言,switch 于 else if 的区别就是, switch 会被编译器编译成跳转表。跳转表的概念比较好理解但难解释,直接上实例吧!

.8086⇠

.MODEL small⇠

.STACK⇠

.DATA⇠

TABLE DW DAY_1⇠

DW DAY_2⇠

DW DAY_3⇠

DW DAY_4⇠

DW DAY_5⇠

DW DAY_6⇠

DW DAY_7⇠ ; 请忽略, 是vim 特效

.CODE

....

....

DAY_1:⇠

MOV AX, OFFSET MONDAY⇠

PUSH AX⇠

CALL PRINT⇠

JMP EXIT⇠

DAY_2:⇠

MOV AX, OFFSET TUESDAY⇠

PUSH AX⇠

CALL PRINT⇠

JMP EXIT⇠

DAY_3:⇠

MOV AX, OFFSET WEDNESDAY⇠

PUSH AX⇠

CALL PRINT⇠

JMP EXIT⇠

DAY_4:⇠

MOV AX, OFFSET THURSDAY⇠

PUSH AX⇠

CALL PRINT⇠

JMP EXIT⇠

....

意思就是指,数据段把相应的cluster 的名字写入,而具体的实现写在下面,跳转的时候:

JMP TABLE[DI]⇠

就会跳转到表中该项对应的簇!

常用标志位的置位与复位

指令

作用

CLC

Let CF = 0

CMC

Let CF = ~CF

STC

Let CF = 1

CLD

Let DF = 0

STD

Let DF = 1

CLI

Let IF = 0

STI

Let IF = 1

Loop

普通Loop

MOV CX, [circles]

AGAIN:

XXXX

LOOP AGAIN

特殊Loop

当相等的时候就LOOP

LOOPZ/E

当不相等的时候就LOOP

LOOPNZ

串操作**

DI 和 SI 以及串操作思想

串操作是对一些列字节进行一次性操作,涉及到以下三个寄存器:

SI: 串操作源地址, 段地址参考 DS

DI: 串操作目的地址 , 段地址参考 ES

DF: 串操作的方向, DF = 0 , DI , SI 执行完一次会++, DF=1, DI,SI执行完会--

常用的串指令

LODS 指令, 从内存加载到寄存器AL,AX,EAX。。。 有LODSB, LODSW, LODSD, 最后一位是Byte,Word,DWord。 决定了执行完一次后,DI,SI加/减多少个Byte。

STOS 指令, 将AL,AX 存到DI 指向的内存空间。

的指令都是默认执行一次,如果要重复,就需要:

LEA DI, BUFF ; BUFF is a array

MOV CX, 1000

MOV AL, 0

REP STOSB ; init BUFF with 0

MOVS 常用,将 DS:SI 地址内容 移动(复制)到 ES:DI对应的地址, 同样需要配合 CX, 以及 REP指令

INS 与 OUTS 主要用于与IO设备的串交互,同样需要配合 CX, 以及 REP指令

SCAS 指令 串比较,将ES:DI指向的内容与AL,AX,EAX内容比较。 配合 REPNE(相等就停止) / REPE (不想等就停止),当然硬性条件是cx!=0.

CMPS 串指令, 将SI,DI指向的内容进行比较,和SCAS 类型,配合RExxP使用。

令在汇编中作用很大,妥善使用能省去很多麻烦, 实验中有一个回文串的判断,我是用循环进行判断,十分麻烦,现在看来,利用STOSB将会非常简单,具体思路可能是:

MOVSB ,DF = 1, 将内容反向复制, 在利用CMPS 进行判断即可!

汇编过程的编写

LABEL PROC [NEAR/FAR,far常用于中断处理函数]

PUSH XX

....

POP XX

RET

LABEL ENDP

....

CALL LABEL / FAR PTR LABEL

; CALL reg/mem16 间接调用,不常用/ call dword ptr mem32/48

REP 指令

所有过程都需要,一般没有参数,直接调用即可,但是当函数有返回值时,就需要了解下面的用法了:

REP EXP

这个指令做了些啥呢,

IP

SP

SP

EXP 可以自己想办法用, 反正效果就是让SP多向下移动了EXP个字节而已。

函数传参

通过寄存器传参,这个比较好弄

通过堆栈传参,这个比较常用,需要掌握以下。 假如要传递两个个参数:

PUSH AX ;PARAM1

PUSH BX ; param 2

CALL LABEL

...

LABEL PROC NEAR

PUSH BP

MOV BP, SP ; 利用BP进行临时的堆栈操作

PUSH XXXXX.... ;保留现场

MOV SI , [BP+6]; 第一个参数,想想为什么时+6呢, 因为BP下面的参数内容为:

;REG1

;REG2

...

;原来BP内容

;IP BP+2

;PARAM2 BP+4

;PARAM1 BP+6

现在明白了把, 具体情况还要根据函数类型来呀,因为有些函数可不止默认保留IP,还有CS什么的。。

总结

我所学到的有关汇编的全部内容就到这里啦, 有疑问可以联系作者zenhox@163.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值