前言
- x86
x86的起点是Intel 8086处理器
8086是16位处理器
一个字节八位
- 寄存器
14个寄存器
AX,BX,CX,DX,SP,BP,SI,DI,IP,FLAG,CS,DS,SS,ES
八个通用寄存器
AX,BX,CX,DX,SP,BP,SI,DI
通用寄存器
数据寄存器
数据寄存器AX,BX,CX,DX
AX (Accumulator):累加寄存器,也称之为累加器;
BX (Base):基地址寄存器;
CX (Count):计数器寄存器;
DX (Data):数据寄存器;
指针寄存器SP,BP
SP (Stack Pointer):堆栈指针寄存器;
BP (Base Pointer):基指针寄存器;
变址寄存器SI,DI
SI (Source Index):源变址寄存器;
DI (Destination Index):目的变址寄存器
控制寄存器
IP (Instruction Pointer):指令指针寄存器;
FLAG:标志寄存器;
段寄存器
CS (Code Segment):代码段寄存器;
DS (Data Segment):数据段寄存器;
SS (Stack Segment):堆栈段寄存器;
ES (Extra Segment):附加段寄存器
AX可以拆分两个寄存器,高八位AH,低八位AL
AX=AH,AL BX=BH,BL CX=CH,CL DX=DH,DL
- 8086有20根地址线,寻址范围2的20次方,等于1MB,转成16进制为0x00000-0xfffff
16位数值范围
进制 | 范围 | 数值 | 备注 |
---|---|---|---|
二进制 | 0000 0000 0000 0000 - 1111 1111 1111 1111 | ||
十六进制 | 0000 - FFFF | 十六进制一位表示二进制四位 | |
十进制 | 0 - 65535 | 65536 = 64KB |
20位总线寻址范围
进制 | 范围 | 数值 | 备注 |
---|---|---|---|
二进制 | 0000 0000 0000 0000 0000 - 1111 1111 1111 1111 1111 | 根据上面来说在加四位 | |
十六进制 | 00000 - FFFFF | ||
十进制 | 0 - 1048575 | 1048576 = 1MB |
- FAQ:寄存器是16位,但是数据总线是20位,那16位寄存器如何使用20位地址总线,并寻址到1MB呢?
16位实模式下,寄存器需要段地址结合偏移地址来让寻址1MB,使用两个寄存器来出来,段寄存器,偏移寄存器
物理地址=段地址*16(段地址<<4) + 偏移地址
段的意思是1MB分16个64KB的段
在通过偏移地址寻址64KB,0x0000-0xffff就是偏移地址的范围
举个例子
段地址0xffff,偏移地址0xffff,物理地址等于多少?
0x1000 << 4(0x10000*16) = 0x10000
0x1000 + 0xffff = 1ffff < 0xfffff是有效物理内存地址
如果段0xffff << 4 + 0xffff = 0x10ffef > 0xfffff 无效地址,在8026中是一个异常,并且执行0x00000处
参考:
http://www.cppblog.com/mydriverc/articles/30719.html
- 1MB寻址范围分配
CPU寻址范围内的地址分配给其他设备
地址范围 | 大小 | 分配对象 | 细分 |
---|---|---|---|
0x00000-0x9ffff | 640KB | 内存 | 0x07c00-ox07DFF 512B为BootLoader |
0xaffff-0xBFFFF | 128KB | 文字图像 | 0xA0000-0xAFFFF 64KB EGA/VGA/XGA/XVGA彩色模式 0xb0000-0xb7fff 32KB 黑白文本 0xB80000-0xBffff 32KB 为彩色文本 这些地址映射为显卡显存,写入相当于写入显存 |
0xCFFFF-0xFFFFF | 256KB | BIOS |
安装相应的软件
- 安装Vscode编辑器,并安装打开二进制文件的插件
Hex editer
- 安装Nasm,nasm-2.15.05-installer-x64.exe,记得加入环境变量
- 安装virtualbox,VirtualBox-6.1.22-144080-Win.exe
- FixVhdw 把文件写入硬盘
- WinHex 读取写入裸盘,把程序写入U盘
软件打包下载地址,链接: https://pan.baidu.com/s/1YN7mB5uPuIzcacS-Q-YCmg 提取码: 5ua2
开发一段测试代码
第一个汇编程序start.asm
mov ax, 0b800h # 显卡彩色文字模式起始位
mov ds,ax
mov byte [0x00],'2'
mov byte [0x02],'0'
mov byte [0x04],'2'
mov byte [0x06],'1'
mov byte [0x08],','
mov byte [0x0a],'H'
mov byte [0x0c],'a'
mov byte [0x0e],'p'
mov byte [0x10],'p'
mov byte [0x12],'y'
mov byte [0x14],' '
mov byte [0x16],'N'
mov byte [0x18],'i'
mov byte [0x1a],'u'
mov byte [0x1c],' '
mov byte [0x1e],'Y'
mov byte [0x20],'e'
mov byte [0x22],'a'
mov byte [0x24],'r'
mov byte [0x26],'!'
jmp $ #
times 510-($-$$) db 0 # 补0,$$起始位置,$表示jmp所在位置,$-$$从开头到jmp一共多少个字节,512减去两个标志位55 aa得到510,510减去($-$$)中间填充0
db 0x55,0xaa # MBR分区最后的标志位
使用Nasm编译为二进制文件,生成start.bin
nasm -f bin start.asm -o start.bin
然后新建other类型dos版本的虚拟机
- 硬盘类型vhd
- 固定硬盘16MB
- 其余选项默认
使用FixVhdw把程序写入硬盘
- 选择虚拟硬盘Vhd文件
- 数据文件选择1为start.bin文件
- 起始LBA扇区号为0
- 写入
软件写入U盘真机运行
- u盘使用fet32格式
- 打开WinHex,然后tool-> open disk -> 选择U盘(physical storages devices,不要选择logical)
- file-> open file -> 打开start.bin文件,
- 在start.bin标签页,选择所有的0之前的数据,不是全部数据,点击Copy All小图标
- 在u盘标签页,点击write clipboard小图标,写入最上面的数据,后面的数据不能破坏!
- 在u盘标签页,点击save小图标