通用寄存器:AX,BX,CX,DX,为16位寄存器,都可分为两个八位寄存器(A,B,C,D)H,(A,B,C,D)L
汇编指令格式:[指令][目的地][出发地] 如:mov ax,18
mov:给寄存器赋值
add:将寄存器内值加上一个值,如果溢出了就会把多的直接舍弃,注意操作如AL时是把AL当成单独的寄存器使用的,溢出部分会直接舍弃而不是放到AH里面。sub与add类似,另外,如果减出了负值,就会按照0-1=ffff,然后继续减(2-5=(0-1)-2=ffff-2=fffd)。也可以给内存单元加减值。
地址偏移:8086cpu寄存器为16位,而地址总线有20位,为了使用16位来寻址20位而搞出来的东西。
物理地址=段地址*10H+偏移地址
这导致了物理地址不会唯一对应一个段地址和偏移地址,理论上只要保证物理地址相同即可。
代码段寄存器CS:记录当前要读取的指令的段地址
指令指针寄存器IP:记录当前要读取的指令的偏移地址
jmp [段地址]:[偏移地址]:修改CS,IP为指定内容
jmp [寄存器]:将IP修改为该寄存器的内容
debug
-r 查看寄存器内容
-r [寄存器] 修改该寄存器的内容
-d [段地址]:[偏移地址],-d[偏移地址]:查看该位起的一段内存内容
使用了上面的指令后再输入-d会继续显示接下来的一段内存内容
-d [段地址]:[起始偏移地址] [结束偏移地址]:查看起始到结束这段内存的内容
-e [段地址]:[偏移地址] [数据] [数据] [数据] [数据] [数据] [数据] [数据] [数据]...:修改这段内存
-e [段地址]:[偏移地址] :进入逐个修改模式,按空格表示不修改这个单元的内容,回车结束。还可以直接输入字符串
-u [段地址]:[偏移地址]:将该段位起的内存当做指令来看
-t执行指令
-a[段地址]:[偏移地址]:从该位置起开始输入指令
段寄存器DS:记录接下来读取内存的段地址,这个寄存器只能由其他寄存器赋值,不能直接赋值,也不能直接加
所以想要读一个内存就得把这个段地址放到一个寄存器里面,再捣到ds里面,然后才能读
mov al,[0]:以ds内容为段地址,[]里的内容为偏移地址,把这里的内存读进寄存器
mov [0],al:把寄存器的内容读进内存
另外,可以有[ax]这样的操作
栈
push [寄存器/内存单元/值/段寄存器]:将这个数据压栈
pop [寄存器/内存单元/段寄存器]:出栈并将这个数据送到指定位置
SS,SP:栈顶寄存器,SS记录段,SP记录偏移。8086没有提供记录栈底的寄存器,也没有提供防止栈上下溢出的措施,甩锅给程序猿 另外,只有SP会随push,pop改变,SS不会因为这些操作改变,所以栈其实只有0000-ffff这么屁大点
xjb写了几行以后发现栈顶是会被记录的,当执行mov sp,30h这样的指令时,会发现之前空的位置变成了这样就是说栈顶被一坨东西糊住了,在教材里面没看见这是坨啥。入栈一个8,变成了这样
发现这一坨东西就这么往前移了。等以后知道了是啥再补上。
编程
xxx segment
...
xxx ends
为成对的伪代码,
定义一个段,中间放代码,一个程序可以有多个段
...
end
表示整个程序的结束
assume [段寄存器]:xxx
将段寄存器和某个段链接
inc [寄存器]:与高级语言里面的i++一个意思