参考文档:INTEL-8086-processor
使用工具:msys2+nasm+npp
目前需要使用的命令:
nasm example.asm -f bin -o example.bin #将asm编译为bin nasm example.asm -l example.lst -o example.bin #产生lst,当然也有编译出bin
寄存器
8086处理器中的寄存器及相关功能如下:
8086的通用寄存器有ax、cx、dx、bx、sp、bp、si、di,它们都是16位的寄存器,一共八个、它们的编号就可以用3位的二进制数表示;而ax到bx都可以再分解成高一字节和低一字节的8位寄存器,分别是al、cl、dl、bl与ah、ch、dh、bh,同样使用3位的二进制数来进行表示。
段寄存器有四个:ES、CS、SS、DS,用2位的二进制数来表示。
即如下:w代表word,当w为1时,说明传输的是一个字的数据,使用16位的寄存器;w为0时,传输的是一个字节的数据,使用8位的寄存器。
16-Bit(w=1) | 8-Bit(w=0) | Segment(16-Bit) |
---|---|---|
000 AX | 000 AL | 00 ES |
001 CX | 001 CL | 01 CS |
010 DX | 010 DL | 10 SS |
011 BX | 011 BL | 11 DS |
100 SP | 100 AH | |
101 BP | 101 CH | |
110 SI | 110 DH | |
111 DI | 111 BH |
这些寄存器中,有一些有特殊作用:
al:8位的累加器
ax:16位的累加器
cx:程序计数器
ds:数据段寄存器
es:附加段寄存器
对机器码中一些位的说明:
1.机器码中,如果代表d的位为1时,说明这条指令是写到寄存器的,反之就是从寄存器读取;
2.如果代表w的位为1时,说明当前操作的数据单位是字,即word,反之则是字节;
3.如果代表mod的位为11时,则r/m位将会表示为寄存器;
4.如果代表mod的位为00时,则DISP=0*,disp-low和disp-high将不存在(disp是什么不清楚)
5.如果代表mod的位为01时,则DISP=disp-low,符号扩展到16位,disp-high不存在
6.如果代表mod的位为10时,则DISP=disp-high;disp-low
7.如果代表r/m的位为000时,则EA=(BX)+(SI)+DISP
8.如果代表r/m的位为001时,则EA=(BX)+(DI)+DISP
9.如果代表r/m的位为010时,则EA=(BP)+(SI)+DISP
10.如果代表r/m的位为011时,则EA=(BP)+(DI)+DISP
11.如果代表r/m的位为100时,则EA=(SI)+DISP
12.如果代表r/m的位为101时,则EA=(DI)+DISP
13.如果代表r/m的位为110时,则EA=(BP)+DISP*
14.如果代表r/m的位为111时,则EA=(BX)+DISP
15.DISP在两字节的指令之后,(有必要的话在数据前);除非mod=00,并且r/m=110,否则EA=disp-high;disp-low
16.若s w=01 ,16位的立即数就直接构成操作数
17.若s w=11,立即数字节就作为16位操作数的符号扩展
18.若v=0,则count=1,若v=1,则count在CL寄存器中,x不用管。
19.z是用来进行ZF和Flag进行比较的一串原语
凭我的英文水准和现在对文档的了解,只读懂到第三条说明,DISP不知道是什么;
汇编指令
tip:需要注意的是不论是数据还是内存地址,只要是16位的,都是低字节在前,高字节在后,比如0xb923,在机器码中就变成了23B9。
MOV
mov指令可以实现的操作如下:
寄存器与寄存器之间或者寄存器与内存单元之间的数据存取。
这个指令有两个字节(试了一下内存到寄存器的指令是4个字节(不包含ax,al寄存器,这两个代表累加器,归下面管),可能是我看的文档比较老,又或者我不会看文档吧