汇编复习笔记(也可作为进阶篇)
本文最后更新于:2021年1月1日 晚上
计算机中的数
二进制的补码
对于8位的二进制来说,+0和-0的补码都是00000000(只有一种表示)
但是按道理来说10000000是表示-0的,这个二进制就用来表示-128。同理100000000用来表示-256
所以对于8位的补码表示的数的范围为-128 ~ +127
补码的符号扩展
比如16位补码(一字节)扩展为32位补码(双字):正数高位补零,负数高位补一
字节,节,页
256个字节 = 16个节 = 1个页
存储数据
存储器
我们除了数据存入寄存器中,其他的数据就是存在内存中的,内存中以字节为单位存储信息。内存中的数据存入方式是由低地址到高地址。
但是当要存储的数据由多个字节组成(如双字数据)时,我们要遵守大大小小原则,即低位字节存入低地址,高位字节存入高地址
地址的分段
80的地址总线宽度是20位,也就是说寻址空间正好是2²⁰ = 1M的空间大小。
于是我们用实模式的两种地址来表示实际的逻辑地址:段地址左移一位 + 偏移地址(正好就是5位的16进制数)
部分指令详解
在指令部分,我其实已经有写过(其实是搬运)一篇文章来记录所有基本的指令,这里我只是挑一些进行详细解读
类型转换指令
cbw(convert byte to word)———- 字节转字
cwd(convert word to double word)———- 字转双字
ps:
cbw较为常用,其中前者默认是将AL中内容扩展到AX,后者默认是AX扩展到DX : AX中的双字(所以有DX代表双字的说法)
加减1指令
这俩指令用的很多,平时却有点记不住,特在此记下:
inc(increment)——— 加一操作
dec(decrement)———- 减一操作
因为neg(求补)和dec是在一起的,也在此说明一下:
neg(negate)——— 单纯就是将操作数按位求反后加一
逻辑指令
and ——— 逻辑与
or ———— 逻辑或
not ———- 逻辑非
xor(exclusive or)——— 异或
test ——— 测试
这些指令都是后接两个操作数,结果保存到前一个操作数,除了test
test两个操作数相与的结果不保存,只根据其特征置条件码:利用ZF改变,存放结果
移位指令
shl(shift logical left)——- 逻辑左移
sal(shift arithmetic left)—— 算术左移
shr(shift logical right)—— 逻辑右移
sar(shift arithmetic right)—— 算术右移
rol(rotate left)———— 循环左移
ror(rotate right)————- 循环右移
rcl(rotate left through carry)——- 带进位循环左移
rcr(rotate right through carry)——- 带进位循环右移
逻辑和算术移位都是缺位补零,进位送CF。(算术右移是将其自身填入空缺位)
循环移位是循环移位一次,进位给CF。
方向标志改变指令
CLD(clear direction flag)——- 使DF = 0
STD(set derection flag)———- 使DF = 1
汇编程序基本格式
datas SEGMENT
...
datas ENDS
stacks SEGMENT
db 100 dup(0)
stacks ENDS
codes SEGMENT
assume cs:codes,ds:datas,ss:stacks
start:
mov ax,datas
mov ds,ax
...
mov ah,4ch
int 21h
codes ENDS
end start
伪操作
assume
用来明确段和段寄存器之间的关系,我们通常会这么写:
assume cs:codes,ds:datas,ss:stacks
但是如果我们要取消前面的指定可以用:
assume nothing
类型转换
同一个变量可以具有不同的类型属性
eg:
oper1 db 1,2
mov ax,oper1+1
显然这个表达是错的(会报错),oper1的类型是字节,而ax的类型是字,类型不匹配。
ptr
我们用ptr可以把oper1的类型转换成字:
mov ax,word ptr oper1+1
这样就不会有类型的报错了,同时word
这里还可以是byte
,dword
等多个类型
label
除了
ptr
的转换,我们还可以用label
(相当于是取别名)
对于oper1数据我们可以在定义时:
oper1_word label word
oper1 db 1,2
这样我们用oper1_word
进行字的操作,用oper1
来进行字节的操作。但是它们指向的是同一个内存空间。
EQU
可以用EQU(equal?)来给一个表达式赋予一个名字(这是一个赋值伪操作),eg:
data equ var+2
ps:equ
不允许重复定义,同时equ
伪操作不占用内存空间
warning:=
也可以错位赋值伪操作使用(=
可以重复使用),但是两者不能同时使用
地址计数器
在汇编中表示当前指令的地址(偏移地址)。
每处理一条指令,地址计数器就增加一个值。
org伪操作
此伪操作用来设置当前地址计数器的值,eg:
org 10 ;此时偏移地址为10
基数控制伪操作
warning:汇编程序默认的数为十进制数
.radix
伪操作可以把默认的基数改变成2 ~ 16的任何基数,eg:
.radix 16
mov bx,0ff ;16进制就不用写h
mov bx,178d ;10进制就要写d
数值回送操作符
type
如果之后的表达式是一个变量,则汇编程序返回该变量的以字节数表示的类型:db为1,dw为2,dd为4。
array dw 1,2,3
mov si,type array ;等同于mov si,2
length
- 对于变量使用
dup
的情况,程序返回分配该变量的单元数(只看第一个dup
) - 对于其他情况一概返回1
fee dw 100 dup(0)
mov cx,length fee ;等同于mov cx,100
size
程序返回伪操作之后变量的type值与length值的乘积,比如之前的fee变量:
mov cx,size fee
;相当于mov cx,200
seg
程序会返回变量或者标号的段地址值
比如如果datas
是地址为05000h的数据段段名,oper1是该段中第一个变量名:
mov bx,seg oper1
;相当于是mov bx,05000h
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!