使用kvmtool运行程序
- 直接使用二进制编程,然后使用kvmtool运行程序
- 二进制编程需要查看X86指令集文档,找到每条指令对应的二进制
- kvmtool是一个轻量级的KVM用户态管理程序,它可以提供一个虚拟机
- CPU –> Intel、AMD
- 操作系统 –> Linux
- 如果使用虚拟机的嵌套(比如VMware Workstation运行kvmtool),那么需要打开Intel VT-x、AMD-V
- 虚拟机串口循环打印字符A的程序
- 虚拟机
- 程序 –> 虚拟机内存
- 虚拟机运行程序
- 虚拟机串口 –> 屏幕
- 程序
- 寄存器AL写入字符A
- 寄存器DX写入串口的I/O端口地址0x03F8
- 串口打印
- 跳转到开始
- 我们使用vim -b编辑一个二进制,使用xxd -p -r将十六进制转换为二进制
// ----- Assembly -----
// mov r8, imm8 --> B0+r8 imm8
* r8 = 0 (AL)
* imm8 = 0x41 ('A')
mov AL, 'A' --> B0 41
// mov r16, imm16 --> B8+r16 imm16
* r16 = 2 (DX)
* imm16 = 0x03F8 (Little Endian)
mov DX, 0x03F8 --> BA F8 03
// out DX, AL --> EE
out DX, AL --> EE
// jmp rel8 --> EB rel8
* B0(-8) 41(-7) BA(-6) F8(-5) 03(-4) EE(-3) EB(-2) F8(-1) Instruction Pointer(0)
* rel8 = 0xF8 (-8)
jmp 0xF8 --> EB F8
// ----- Binary -----
// Hexadecimal --> Binary
B 0 4 1 B A F 8 0 3 E E E B F 8
1011000001000001101110101111100000000011111011101110101111111000
// Save as kernel.bin (using vim, xxd)
$ vim -b kernel.bin
b041baf803eeebf8
:%! xxd -p -r
:wq
// ----- Run Program -----
// Run kvmtool, cpu number = 1, kernel = kernel.bin
$ ./kvmtool/lkvm run -c 1 -k kernel.bin
AAAAAAA...
GNU工具链
- GNU工具链
- 汇编器 –> as
- 链接器 –> ld
- 二进制的复制 –> objcopy
- 二进制的反汇编 –> objdump
- 从汇编指令到二进制
- 汇编器(as)
- 链接器(ld)
- 二进制的复制(objcopy)
- 可执行文件(.elf) –> 二进制(.bin)
- 去掉ELF文件的头部等信息,提取出代码、数据
- 在汇编文件中,我们使用Intel句法;在GNU工具链中,默认使用AT&T句法
- 在汇编文件中,添加.intel_syntax noprefix,不使用前缀(比如%)
- 在汇编器中,添加-msyntax=intel,使用Intel句法
- 如果用objdump -d来反汇编,那么可以得到AT&T句法
- X86指令集源于Intel 8086,它是16位的。之后,X86指令集扩展到32位、64位
- 在汇编文件中,添加.code16
- 在反汇编中,添加-m i8086
- X86指令集的寄存器从16位到64位是兼容的,比如AL(低8位)、AX(16位)、EAX(32位)、RAX(64位)
- 如果用xxd来查看二进制,那么结果和上面一样
// ----- kernel.s -----
.intel_syntax noprefix
.text
.code16
start:
mov AL, 'A'
mov DX, 0x03F8
out DX, AL
hlt
// ----- kernel.bin -----
// Assemble
$ as kernel.s -msyntax=intel -o kernel.o
// Link
$ ld kernel.o -Ttext=0 -o kernel.elf
// Copy binary
$ objcopy kernel.elf -O binary kernel.bin
// Disassemble
$ objdump -d -m i8086 kernel.elf
b0 41 mov $0x41,%al
ba f8 03 mov $0x3f8,%dx
ee out %al,(%dx)
f4 hlt
// Binary
$ xxd kernel.bin
b041 baf8 03ee f4
// ----- Run Program -----
// Run kvmtool, cpu number = 1, kernel = kernel.bin
$ ./kvmtool/lkvm run -c 1 -k kernel.bin
A