本文是上学期学习汇编语言时候的课堂笔记。
分类索引(单击命令直接索引)
| 分类 | 命令 |
|---|---|
| 符号数相关 | JG、JL、IMUL |
| 通用数据传送指令 | MOV、POP、PUSH、XCHG、IN、OUT |
| 地址传送指令 | LEA、LDS、LES、PUSHF、POPF |
| 转换指令 | CBW、CWD、XLAT |
| 加减乘除 | ADD、INC、ADC、SUB、DEC、NEG、MUL、DIV |
| 逻辑运算 | AND、OR、XOR、NOT、TEST |
| 移位指令 | SHL、SHR、SAL、SAR、ROL、ROR、RCL、RCR |
| 字符串操作 | MOV、CMPSB、SCASB、STOSB、LODSB |
| 控制转移指令 | JMP、LOOP、CALL、RETN、RETF |
符号数相关
jg/jl大小比较
jg 符号数大于
jl 符号数小于
跳转依据:
| 符号 | 依据 |
|---|---|
| a < b | SF!=OF |
| a==b | ZF=0 |
| a > b | SF=OF且ZF=0 |
1 | ah=0FFh, bh=1 |
imul 符号数乘法
- imul eax
只寄存器, ebx寄存器或变量, 1234h只常数
eax = ebx * 1234h - imul eax, ebx
eax自乘ebx
通用数据传送指令
MOV 指令
1 | [√] mov byte ptr ds:[bx], ah |
DS/CS/IP不能被mov改变
mov 的变体
movzx: move by zero extentionmovsx: move by sign extention[rep] movsb; 以字节为单位移动CX个字符
DS : SI 指向源字符串
ES : DI 指向目标字符串
若 DF=0 即正方向则SI++,DI++,否则反之。
POP / PUSH 指令
- 不能对8位值进行push/pop:
1 | [×] push ah |
XCHG 指令
(略)
IN / OUT 指令
基本格式:1
in al, 21h
从21h号端口读取一个字节存放到AL中
- 端口地址>=100h,必须存放到DX
- 端口地址的范围是:[0000h, 0FFFFh],共65536个端口。
地址传送指令
LEA `取变量的偏移地址`
1 | lea eax, [ebp-64] |
EAX = EBP-64
- lea dx, ds:[1000h] ; DX=1000h
- 设BX=1000h, SI=2
lea ax, ds:[bx+si+3]; AX=bx+si+3=1005h
LDS `把远指针装到DS:DEST`
1 | lds dest, src |
把 src 指向的地址,高位存放在DS中,低位存放在dest中。
16位时,
比如当前DS=1000H, BX=0100H.
当前内存:
1000:0100 01
1000:0101 02
1000:0102 03
1000:0103 04
而有一条指令:LDS BX,[BX]
[BX]指向1000:0100,执行后BX存低位的内容,也就是BX=0201H,
而DS则存高位的内容,也就是[BX+2]的内容,DS=0403H
LES `把远指针装到ES:DEST`
1 | les dest, src |
PUSHF,POPF `标志寄存器传送指令`
(把FL压入/弹出ax)1
2
3
4
5pushf
pop ax ; AX=FL
or ax, 1; 第0位变1,其它位不变
push ax
popf ; FL=AX
转换指令
CBW,CWD `符号扩充指令`
CBW: convert byte to word
CWD: convert word to double word
CDQ: convert double word to quadruple word(32位扩充为64位)
1 | mov al, 7Fh |
1 | mov al, 0F9h |
1 | mov ax, 8000h |
1 | mov eax, 0FFFFFFFFh |
movzx: move by zero extentionmovsx: move by sign extention
XLAT `换码指令`
1 | ; 设 char t[]="0123456789ABCDEF"; |
加减乘除
加
| 指令 | 用法 |
|---|---|
| add | |
| inc | 不影响CF位 |
| adc | 带进位加法。当进行32位以上运算时,要求低位字节相加,而高位字节再相加时就要考虑低位相加的进位,即CF |
减
| 指令 | 用法 |
|---|---|
| sub | |
| dec | 自减 |
| neg | 求相反数 |
乘 `非符号`
1 | mul src |
src 不能是立即数,寄存器和地址均可
| src字节数 | 操作对象 | 结果存放 |
|---|---|---|
| 8字节 | al | ax |
| 16字节 | ax | dx : ax |
| 32字节 | eax | edx : eax |
即 AX = AL * src
除 `非符号`
1 | div op |
| op字节数 | 操作对象 | 结果存放 |
|---|---|---|
| 8字节 | ax | al(整除);ah(余数) |
| 16字节 | dx : ax | ax(整除);dx(余数) |
| 32字节 | edx : eax | eax(整除);edx(余数) |
语句比较
test/and(cmp/sub)
运算结果不影响操作数,只影响标志位。
影响标志: C,O,P,Z,S(其中C与O两个标志会被设为0)neg/notneg求相反数,not逐位求反inc/add
是否影响flagjc与jb指令完全等价。jz与je指令完全等价。
比较方法
- 非符号数:CF / ZF
- 符号数:SF / OF / ZF
OF=1 即结果溢出(有错),否定SF得到的符号结果
逻辑运算和移位
逻辑运算指令
AND,OR,XOR,NOT,TEST
移位指令
SHL,SHR,SAL,SAR,ROL,ROR,RCL,RCR1
shl ah, 1
**单向**
| 符号 | 含义 | 作用 |
|---|---|---|
| SHL | 逻辑左移 | 低位补0, 高位进CF |
| SHR | 逻辑右移 | 低位进CF, 高位补0 |
| SAL | 算术左移 | (同SHL) |
| SAR | 算术右移 | 每位右移, 低位进CF, 高位不变 |
它们的结果影响 OF、SF、ZF、PF、CF
**循环**
| 符号 | 含义 | 作用 |
|---|---|---|
| ROL | 循环左移 | 高位到低位并送CF |
| ROR | 循环右移 | 低位到高位并送CF |
| RCL | 带进位循环左移 | 进位值(原CF)到低位, 高位进CF |
| RCR | 带进位循环右移 | 进位值(原CF)到高位, 低位进CF |
它们的结果影响 OF、CF
8086中,当次数>=2时,移位次数应先赋值给 cl
字符串操作
MOVSB `字符串传送`
1 | [rep] movsb |
以字节为单位,从 DS:SI 到 ES:DI 移动CX个字符
- DF控制方向。若DF=0即正方向则SI++,DI++。
CMPSB `字符串比较`
1 | [repe | repne] cmpsb |
若本次比较 相等 / 不等 则继续比较下一个
SCASB `字符串查找`
1 | [repe | repne] scasb |
设ES:DI → 以’\0’结束的字符串,要求该字符串长度1
2
3
4
5
6
7
8
9mov ax, 1000h
mov es, ax
mov di, 1080h ; ES:DI → "ABC..."
mov cx, 0FFFFh ; ES:DI → "ABC",0,[]...
mov al, 0 ; AL=待查找的字符
cld
repne scasb ; 循环结束时,DI=1088h, CX=FFFF-8
inc cx
not cx ; CX=FFFF-CX=字符串长度(不含0)
STOSB `存入字符串`
1 | [repe] stosb |
stosb把AL的值保存到ES:DI所指向的内存单元中
- 当DF==0时DI++,当DF==1时DI—
设要把从地址1000:10A0开始共100h个字节内存单元全部填01
2
3
4
5
6
7mov ax, 1000h
mov es, ax; ES=1000h
mov di, 10A0h
mov cx, 100h
cld
xor al, al
rep stosb
LODSB `从字符串取字节或字`
1 | lodsb |
AL = DS : [SI], SI++
控制转移指令
JMP
1 | [√] jmp 0108h |
LOOP
CX-1
CALL,RETN,RETF `子程序调用与返回`
retn表示近返回,可简写成ret;
retf表示远返回。
call既可以表示近调用,也可以表示远调用
retn [count] ; count多出步骤:SP = SP + count
堆栈传递1
2
3
4
5
6
7
8
9
10
11
12f:
push bp
mov bp, sp
mov ax, [bp+4]; 从堆栈中取得参数
add ax, ax
pop bp
ret
main:
mov ax, 3
push ax; 参数压入到堆栈
call f
add sp, 2
C语言函数调用y=f(2,3)求两数之和转化成汇编语言1
2
3
4
5
6
7
8
9
10
11
12
13
14
15f:
push bp;(4)
mov bp, sp
mov ax, [bp+4]
add ax, [bp+6]
pop bp; (5)
ret; (6)
main:
mov ax, 3
push ax; (1)
mov ax, 2
push ax; (2)
call f; (3)
here:
add sp, 4;(7)
上述程序运行过程中的堆栈布局如下:
ss:1FF8 old bp <- bp (4)
ss:1FFA here <- (3)(5)
ss:1FFC 02 <- (2)(6)
ss:1FFE 03 <- (1)
ss:2000 ?? <- (7)
cx/dx可以随便用
ax一般用作返回值