汇编
看懂这个笔记应付CSU的汇编期末考试完全没有问题
概念
数的存储
有符号数在8086中,正数的最高位是0,复数是最高位为1,后面按位取反加一。
[
−
1
]
机器码
=
1111
1111
[-1]_{机器码}=1111\ 1111
[−1]机器码=1111 1111
寄存器
通用寄存器
16位通用寄存器:AX、BX、CX、DX
AX (Accumulator):累加寄存器
BX (Base):基地址寄存器,经常存地址
CX (Count):计数器寄存器;常用来循环
DX (Data):数据寄存器,DIV时候会用到
以上四个寄存器都可以分为两个8位寄存器来使用AH、AL...
其他寄存器均不可以分为两个独立的 8 位寄存器
字节:byte 8个bit组成,可以存在8位寄存器中
字:word 2个字节组成,可以存在16位寄存器中
偏移地址寄存器
**BX, BP,SP, SI, DI **:只有这五种寄存器可以通过[BX]
这种方式进行寻址
BP和SP寄存器称为指针寄存器,与SS联用,为访问现行堆栈段提供方便。通常BP寄存器在间接寻址中使用,操作数在堆栈段中,由SS段寄存器与BP组合形成操作数地址即BP中存放现行堆栈段中一个数据区的“基址”的偏移量,所以称BP寄存器为基址指针。
寄存器SI和DI称为变址寄存器,通常与DS一起使用,为访问现行数据段提供段内地址偏移量。在串指令中,其中源操作数的偏移量存放在SI中,目的操作数的偏移量存放在DI中,SI和DI的作用不能互换,否则传送地址相反。在串指令中,SI、DI均为隐含寻址,此时,SI和DS联用,Dl和ES联用。
段寄存器:CS、DS、SS、ES
不可以直接将数字mov过去,只能通过寄存器mov
CS和IP
最关键的寄存器,指示了CPU当前要读取的指令的地址
8086中,任意时刻,CPU将CS:IP
指向的内容当作指令执行
8086中的大部分寄存器都可以通过mov
指令修改,但是CS,IP
不可以通过mov
改变
如果想要修改CS、IP的内容,可以使用jmp 段地址:偏移地址
实现
如果只想修改IP,可以使用jmp 某一合法容器
比如jmp ax
DS和[address]
将内存中的数据存到寄存器中
可以使用
mov AX,2000H
mov ds,ax
mov al,[0]
SS和SP
pop ax
push ax //以字为单位
任意时刻,SS:SP指向栈顶元素
压入元素时,sp减小,先压入栈的在高地址
标志寄存器(FLAG):
前面所有的寄存器是作为一个整体使用,但是标志寄存器的每一位都有自己的作用
CF**(Carry FLag)**:进位标志位,产生了进位或者借位时会改变
PF(Parity FLag):奇偶校验位,结果的1为偶数时为1
AF(Auxiliary Carry FLag) - 辅助进位标志(第 4 位):
**ZF(Zero FLag) – 零标志(第 6 位):**记录的是相关的指令执行完毕后,其执行的结果是否为 0 。
SF(Sign FLag) - 符号标志(第 7 位): 符号标志,其记录相关指令执行完以后,其结果是否为负数 。
DF(Direction FLag) - 方向标志(第 10 位):
DF: 方向标志,其用于在串处理指令中,用来控制每次操作后 SI 和 DI 是自增还是自减 。
OF(OverFlow FLag) - 溢出标志(第 11 位):
OF: 溢出标志,其通常记录了有符号数运算的结果是否发生了溢出 。
给出物理地址方法
将两个16位的地址合成一个20位地址
将段地址和偏移地址送入地址加法器
物理地址=段地址*16+偏移地址1
dw 数据可以在内存中定义数据
start
end start 指明程序开始的地方
mov ax,4cooh
int 21h
多个段的程序
assume
只是将有联系的段地址和段链接起来,但是并没有在cpu中联系,所以还需要对段寄存器赋值
[bx+idata]意思是偏移地址是(bx)+idata
数据段定义
dd定义双字型数
dup是定义重复字节
定义200次0:
db 200 dup(0)
DOS终端指令 21H
指令功能号放置在AH
01H 输入字符到AL(回显
0AH 输入字符串到缓冲区
LEA DX,buffer1
mov ah,0Ah
int 21h
02H 输出字符DL
09H 输出字符串
LEA DX,sen1
mov ah,09h
int 21h
结束程序
mov ax,4c00h
int 21h
ASCII
41H->a
61H->b
30H->0
指令
数据传送指令
XCHG
:交换字或字节
LEA
:把地址装入
算数运算指令
乘法
MUL 无符号乘法
IMUL 有符号乘法
执行的操作:
字节:(AX)<-(AL)
字:(DX,AX)<-(AX)*(SRC)
除法
DIV: 无符号除法
IDIV: 无符号除法
格式:DIV SRC
执行的操作:
字节操作:16位除8位,16位在AX中
8位商在AL中
8位余数在AH中
字操作:32位除16位,32位在DX AX中
16位商在AX中
16位余数在DX中
CBW,CWD
CBW
字节转换为字。 (把AL中字节的符号扩展到AH中去)
CWD
字转换为双字。 (把AX中的字的符号扩展到DX中去)
-
字节扩展指令格式:CBW (隐含的操作数为AL)
执行的操作 :
当AL的最高位为0时(D7=0)——>AH=00H
当AL的最高位为1时(D7=1)——>AH=FFH -
字扩展指令格式: CWD (隐含的操作数为AX)
执行的操作 :
当AX的最高位为0时(D15=0)——>DX=0000H
当AX的最高位为1时(D15=1)——>DX=FFFFH
逻辑运算
AND和OR
and与指令 按位进行与运算
or或指令 按位进行或运算
XOR:
按位异或
NEG:
把操作数按位取反加一 (可以用来求一个数的相反数)
NOT:
把操作数按位取反
TEST
test
:Test命令将两个操作数进行逻辑与运算,并根据运算结果设置相关的标志位。但是,Test命令的两个操作数不会被改变。
TEST AX,BX
与AND AX,BX
命令有相同效果,只是Test指令不改变AX和BX的内容,而AND指令会把结果保存到AX中。
作用详细说明
将两个操作数进行按位AND,设结果是TEMP
- SF = 将结果的最高位赋给SF标志位,例如结果最高位是1,SF就是1
- 看TEMP是不是0,如果TEMP是0,ZF位置1;如果TEMP不是0,ZF位置0
- PF是奇偶校验位,偶数个1的时候为1
位移指令
SHL 逻辑左移。
SAL 算术左移。(=SHL)
SHR 逻辑右移。
SAR 算术右移。(=SHR)
格式:指令 操作数,操作次数
移位一次时, 可直接用操作码。 如 SHL AX,1。
移位>1次时, 则由寄存器CL给出移位次数。
如 MOV CL,04
SHL AX,CL
算数左移右移不改变符号位
ROL 循环左移。
ROR 循环右移。
RCL 通过进位的循环左移。 整体左移,最高位移入CF,CF原有位置放到最低位
RCR 通过进位的循环右移。 整体右移…
以上八种移位指令,其移位次数可达255次。
串指令
CX
重复次数计数器.
DF标志 0表示重复中SI和DI应自动增1; 1表示应自动减1
DF标志位决定了下列MOVS和CMPS代码的正向读取还是负向读取
MOVS 串传送.
( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.
( CMPSB 比较字符. CMPSW 比较字. )
以上指令常与下列重复连用,MOXS和REP连用,CMPS常和REPZ连用
REP 当CX>0时重复
REPE/REPZ 当ZF=1或比较结果相等,且CX>0时重复
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX>0时重复
REPC 当CF=1且CX>0时重复. CF是进位借位置1
REPNC 当CF=0且CX>0时重复.
程序转移指令
无条件转移
JMP
:无条件转移
CALL 过程调用
RET/RETF过程返回.
条件转移
CMP
:隐含减法,相等时CF为1
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志CF和ZF).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 “1” 时转移.
怎么记???
记英文
JAE = jump if above or equal 大于等于跳转
JNA = jump if not above 不大于跳转
循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志ZF=1时循环.
LOOPNE/LOOPNZ CX不为零且标志ZF=0时循环.
JCXZ CX为零时转移.
处理器控制:
CLC 清进位标志位.
STD 置方向标志位DF1 si,di递减
CLD 清方向标志位DF为0 si,di递增
伪指令:
define 定义一个标识符来表示变量
DW 定义字(2字节)
PROC 定义过程
ENDP 过程结束
SEGMENT 定义段
ASSUME:将段寄存器和段代码链接ENDS 段结束
END 程序结束
OFFECT:偏移地址,实现和lea一样的功能
程序段
字符串缓冲区:
buffer1 LABEL BYTE ;LABEL只是一个标号,不占空间
max db 80 ;最大值
act db ? ;实际值,一般由中断指令填写
string1 db 80 dup(?) ;真正存储字符串的地方
函数命名:
crlf proc near
...
ret
crlf endp
以二进制输出:
function proc near ;假设数据在BL
mov cx,8H
a10:
rol bx,1 ;循环移位一位,将最大的放下来
mov al,bl
and al,01h ;让al除了最后一位都置0
add al,30h
cmp al,3Ah
mov dl,al
mov ah,02h ;打印字符输出
int 21h
loop a10
ret
function endp
以十进制输出:
function proc near ;假设数据在BL
mov al,bl
mov cx,0
a10:
mov ah,0
mul 0Ah
push AX
cmp al,0
je a20
inc cx
jmp a10
a20:
pop ax
mov dl,ah
add dl,30h
mov ah,02h
int 21h
loop a20
ret
function endp
以十六进制输出:
function proc near ;假设现在要输出的16位数存在bx中
mov cx,04h ;循环次数
a10:
mov al,04h
rol bx,al ;循环移位四位,将最大的放下来
mov al,bl
and al,0fh ;让al的高四位置0
add al,30h
cmp al,3Ah
jb a20
add al,7h
a20:
mov dl,al
mov ah,02h ;打印字符输出
int 21h
loop a10
ret
function endp
以下可以自己联系: