汇编语言学习笔记(全)

汇编语言分位数和标准,位数是根据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+1,SP)
SP <--- SP+2
SP <--- SP + EXP

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  <--- SP
;REG2  
...
;原来BP内容    <--- BP
;IP                BP+2
;PARAM2            BP+4
;PARAM1            BP+6

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

总结

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,835评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,900评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,481评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,303评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,375评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,729评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,877评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,633评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,088评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,443评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,563评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,251评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,827评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,712评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,943评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,240评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,435评论 2 348

推荐阅读更多精彩内容

  • 计算机通过执行指令序列来使机器得以工作,所以对于每一系列的计算机都有指定的一组指令集供计算机使用,这组指令...
    未来科技工作室阅读 7,935评论 1 10
  • 指令是使计算机执行某种特定操作的二进制编码。8086 CPU指令系统有133条指令,通常分为数据寻址方式和程序寻址...
    刀月水阅读 1,621评论 0 1
  • 8086汇编 本笔记是笔者观看小甲鱼老师(鱼C论坛)《零基础入门学习汇编语言》系列视频的笔记,在此感谢他和像他一样...
    Gibbs基阅读 37,131评论 8 114
  • 小凡觉得自己一无是处。 甚至他都开始怨他的名字,小凡。注定是个平凡的人。 但他真的不甘心。 很不甘心。 他...
    爱美丽大妞爱思考阅读 306评论 2 1
  • 我叫白杨,年龄:一百三十九岁,职业:见习死神。在死神职业学院里大大小小每次考试的成绩都使我深深背负着学渣的称号,但...
    复明的瞎子阅读 427评论 2 3