16位
# PE结构
# 1字{word}=2B
# 段地址(CS) * 16 + 偏移地址(IP) = 实际内存地址
# 段寄存器不能直接赋值,需要用通用寄存器
# 栈push,pop只是改变sp,范围0~FFFFH,最大64kB
# 程序内存位置ds:0,开始是PSP:大小256字节,程序用来与dos通信的端口
# debug时,执行到int 21H用p命令
# bx可以作为数据段偏移地址
# cs一开始作为程序机器码的字节长度,可以作为loop循环条件
# 安全空间:0:200~0:2FF
# 用栈暂时存储数据
# 立即数在指令缓冲器里面
# 栈只对字操作
# 结构体:bx定位结构体位置,idata定位某一个数据项,si定位数据项中的元素位置:ds:bx.idata[si]
# 不能直接修该cs的值,要用jump
# mov不能进行存储器->存储器
##### 显存
# B8000H~BFFFFH共32KB,显存(row)25x(col)80,每屏可显示4000B,每行160B,每列25B
# 偶地址存放字符,奇地址存放颜色属性
# 7 6 5 4 3 2 1 0
# BL(闪烁) (R G B)背景 I(高亮) (R G B)前景
# nop:占用一个字节位置
# 123H,111B
# BX与BP是基址,DI与SI是变址
# 不会溢出的除法
# inc,loop,not不会影响CF的值
# 无符号数比较大小考虑:ZF{零标志位},CF{进位(借位)标志位}
# 有符号数比较大小考虑:ZF{零标志位},OF{进位(借位)标志位},SF(符号标志位)
# ss与sp的设置不会被中断
# 端口:寄存器
寄存器
# 通用寄存器:
- AX{accumulator}:累加寄存器
- BX{base}:基址寄存器
- CX{count}:计数寄存器
- DX{data}:数据寄存器
# AX,BX,CX,DX(16位寄存器)
* AH{high}(高8位寄存器)
* AL{low}(低8位寄存器)
# 与BX同作用
- DI
- SI
# 段寄存器:
- CS{code segment}:代码段寄存器
- DS{data segment}:数据段寄存器
- SS{stack segment}:栈段寄存器
- ES{extra segment}:附加段寄存器
# 偏移地址
- IP{instruction pointer}:CS的偏移地址
- SP{stack pointer}:SS的偏移地址
- BP{base pointer}:栈基址寄存器
- 只有四个寄存机可以内存单元寻址:DS:[BX],SS:[BP],DI,SI
- BX与BP,DI与SI不能同时出现
# 标志寄存器
- FLAG[运算时修改]
- 1,3,5,12,13,14,15位没有被使用
- 0{carry flag}(CF):进位(借位)标志位[无符号数是否进位(借位)]
- 2{parity flag}(PF):奇偶标志位[是否有偶数个1]
- 4(auxiliary carry flag)(AF):辅助进位标志[4位是否进位(借位)]
- 6{zero flag}(ZF):零标志位[是否为0]
- 7{sign flag}(SF):符号标志位[是否为负数]
- 8{trap flag}(TF):跟踪标志位[是否是单步状态]
- 9{interrupt enable flag}(IF):中断允许标志位[中断是否被允许]
- 10{direction flag}(DF):方向标志位[是否递增] // DF=0,++SI,++DI;DF=1,--SI,--DI;
- 11{overflow flag}(OF):溢出标志位[有符号数是否溢出]
注意点
########## MASM中
# 不能直接将立即数赋值给段寄存器
mov ax,1000H
mov ds,ax
----------
# 不能直接[1]获取数据内存位置,[0]可以
mov bx,1H
mov ds,[bx]
# 或直接
mov ax ds:[1]
----------
# cs:[0];ds:[0];ss:[0];es:[0];
----------
# 立即数不能以字母开头
mov ax,0FFFFH
----------
汇编指令
# adc ax, bx
# sbb ax, bx
# cmp ax, bx
# cmps
# scas
# lods
# stos
-- -- -- -- -- 无符号数
# below 在. . . 之下; above在. . . 之上; equal与. . . 相等; 与cmp共用
# je relative_flag;
# jne relative_flag
# jb relative_flag;
# jnb relative_flag
# ja relative_flag;
# jna relative_flag
-- -- -- -- --
# rep
# repe
# repne
# rep movsb
# rep movsw
# cld
# std
# sti
# cli
# clc
# stc
# stc
# hlt
# wait
# esc
# lock 前缀
-- -- -- -- --
# add ax, 0001 H < -- > ax += 0001 H
# sub ax, 0001 H
# mul byte ptr ds: [ 0 ]
# mul word ptr ds: [ 0 ]
# imul
# div byte ptr ds: [ 0 ]
# div word ptr ds: [ 0 ]
# idiv
# test
-- -- -- -- --
# mov ax, 0001 H < -- > ax = 0001 H
# mov ax, ds < -- > ax = ds{ 数据段}
# mov ax, [ 0 ] < -- > ax = [ DS: 0 ] { 数据段地址: 偏移地址}
# mov ax, [ bx+ 200 ]
# mov ax, 200 [ bx]
# mov ax, [ bx] .200
# mov ax, [ bx] [ di]
# mov ax, 200 [ bx+ di]
# mov byte ptr ds: [ 0 ] , 1
# mov word ptr ds: [ 0 ] , 1
-- -- -- -- --
# jmp 2000 : 0000 < -- > 段地址( CS) : 偏移地址( IP)
# jmp ax < -- > ip = ax
# jmp relative_flag
# jmp word ptr [ 0 ]
# jmp dword ptr [ 0 ]
# jmp short relative_flag
# jmp near relative_flag
# jmp far ptr relative_flag
-- -- -- -- --
# push ax < -- > sp -= 2 ; ss: sp = ax;
# push ds
# push [ 0 ] < -- > push ds: 0
# pop ax < -- > ax = ss: sp; sp += 2 ;
# pop ds
# pushf
# popf
# iret
# int 21 H
-- -- -- -- --
# inc ax
# dec ax
# loop relative_flag
# mov ax, offset start
# jcxz relative_flag
-- -- -- -- --
# db 12 H, 34 H < -- > { define byte} : 定义字节数据
# db 'abcd' < -- > 定义字符串
# dw 1234 H, 0923 H < -- > { define work} : 定义字型数据
# dd 00000001 H < -- > { define dwork} : 定义双字型数据
# db 3 dup ( 'a' , 'bc' ) < -- > db 'abcabcabc'
-- -- -- -- --
# and ax, 0123 H < -- > 按位与
# or ax, 0123 H < -- > 按位或
# xor ax, ax
-- -- -- -- --
# ret
# retf
# call relative_flag
# call far relative_flag
# call ax
# call word ptr [ bx]
# call dword ptr [ bx]
-- -- -- -- --
# in al, 60 H
# out 60 H, al
-- -- -- -- --
# shl al, 1
# shr al, 1
# sal
# sar
# rol
# ror
# rcl
# rcr
# xchg ax, bx
伪指令
shell # 控制操作系统的命令集合
assume cs:xxx1 # 假设代码段xxx (就可以用数据标号访问数据)
assume ds:xxx1 # 假设数据段xxx (就可以用数据标号访问数据)
string db 'aaa' # 定义string
string[0] # 获取字符
str dw string # string(偏移地址)翻译为一个数
str dd string # string(段地址+偏移地址)翻译为一个数
----------
xxx segment # xxx段的开始
XXX: # 程序入口
xxx ends # xxx段的结束
# 程序返回(执行21H号中端,第4cH个子程序)
mov ah,4cH
int 21H
end XXX # 程序结束
debug指令
r # 查看寄存器内容
r ax # 修改寄存器内容
t # 执行一条机器指令
d 2000:0000 # {段地址:偏移地址}查看内存中的内容
e # 改写内存中的内容
u 2000:0000 # {段地址:偏移地址}将内存中的机器指令翻译成汇编指令
a # 以汇编指令的格式写入一条机器指令
q # 退出
p # 停止,跳出循环
g # 直接运行到某个位置等待执行(跳转断点)
###
B810:0 # 显卡位置
中断
# push flag;TF=0,IF=0;push cs;push ip;
# IF=0
# 中断向量表(8位索引),共256项
# 在内存0000:0000~0000:03FF共1024个单元
# 数据应放到代码段
mov cx,offset do0end - offset do0
do0:
// ...
mov ax,4c00H
int 21H
do0end:
nop
# ----------
push bp
mov bp,sp
// ...
pop bp
# 不可屏蔽终端类型码都是2
# 0040:17(键盘状态字节)
# ----------
# 键盘按下(通码)与松开(断码)都会产生一个扫描码
# 断码 = 通码 + 80H
# 按状态键不会存储到键盘缓冲区,只会改变键盘状态字节
int al,60H # 读出键盘输入扫描码
int 9 # 从端口60H读取扫描码,得出对应字符Ascii码,键盘缓冲存储或键盘状态改变
int 16 # 读取键盘缓冲区(ah=0) ==> ah(扫描码),al(字符Ascii码)
int 13 # 对磁盘进行读写(读:ah=2),al:读取扇区数,ch:磁道号,cl:扇区号,dh:磁头好,dl:驱动号
COMS RAM
# 70H为地址端口,71H为数据端口
# 秒:00H;分:02H;时:04H;日:07H;月:08H;年:09H;BCD码(4位1个十进制数)存放