文章目录
环境
1、Bochs虚拟机
代码调试
2、VirtualBox
BIOS运行
工具
1、notepad++
编写代码
2、nasm
编译工具
思路
第一步:
定义将要输出的十进制数据
第二步:
创建存储分解位数的空间,并填入-16,后面-16在输出到显存上的时候会加上0x30,变为空格所对应的ASCII码
此时实际内存情况:
第三步:
对122进行分解,并将分解结果存储到第二步创建的空间
此时实际内存情况:
第四步:
对45536进行分解,并将分解结果存储到第二步创建的空间
此时实际内存情况:
第五步:
对195535进行分解,并将分解结果存储到第二步创建的空间
此时实际内存情况:
第六步:
将分解结果输出到显存上,输出到显存的代码解析
此时实际显存情况:
前4行就是我们输出到显存上的数据
举例说明:
0x31就是十进制的48,48作为ASCII码对应的字符就是1,0x07就是它的属性(前后背景及其颜色)
0x39就是十进制的56,56作为ASCII码对应的字符就是9,0x07就是它的属性(前后背景及其颜色)
屏幕输出:
……
第七步:
$获取当前偏移地址,jmp指令跳转至当前偏移地址,形成死循环
解析
1、第二行中jmp code
是为了跳过数据段,执行代码
2、计算字符串长度
标号data_res与标号code表示偏移,所以相减能够得到字符串长度
3、ds为何为0x07c0
因为BIOS程序会被加载到0x0000 : 0x7c00,所以该程序的起始段地址就是0x07c0
5、loop s解释
loop与cx配合能够起到for循环的效果
当cx不为零,程序跳转至s执行
当cx为零时,则按照顺序执行
6、第111行加上0x30的原因
第二步创建的空间存储的是一个个数字,需要转换为其对应的ASCII码,加上0x30,就能进行转换
7、除法指令解析
8、数字分解原理
122 / 10 =12…2
12 / 10 = 1…2
1 /10 =0…1
9、为何屏幕显示的数字是逆序的
实际内存:
数字分解时是逆序分解,各个数字填入第二步创建的空间时,应该是221 63554 535591
为了正常看到数字,我在输出到显存的时候是倒着输出的
就变成了 195535 45536 122
但是也可以将它们按照正常的顺序输出到显存,不过取数据的时候就得跳来跳去的取数据,索性就倒着输出
10、结尾的字符填充
我写的是BIOS程序,计算机对BIOS程序的要求就是512字节,且以0x55,0xAA结尾
效果
1、要求
将数字122,45536,195535输出到屏幕上
2、virtualbox
3、bochs
代码
1、汇编代码
start:
jmp code
data: db 122 ;1byte
dw 45536 ;2byte
dd 195535 ;4byte
data_res:
db 0,0,0,-16
db 0,0,0,0,0,-16
db 0,0,0,0,0,0
code:
;指向数据地址 ds:si
mov ax,0x07c0
mov ds,ax
mov si,data
;指向存储数据地址 es:di
mov es,ax
mov di,data_res
;分解开始:16位除法 ax存被除数,bl存除数,al存商,ah存余
;被除数设置
xor ax,ax
mov al,[ds:si]
inc si
;除数设置
xor bx,bx
mov bl,10
mov cx,3
l0:
;结果计算
div bl
mov [es:di],ah
inc di
xor ah,ah
loop l0
inc di;留给空格
;分解开始:32位除法 ax存被除数低2字节,dx存被除数高2字节,bx存除数,ax存商,dx存余
;被除数设置
xor ax,ax
xor dx,dx
mov ax,[ds:si]
inc si
inc si
;除数设置
xor bx,bx
mov bl,10
mov cx,5
l1:
;结果计算
div bx
mov [es:di],dl
inc di
xor dx,dx
loop l1
inc di;留给空格
;分解开始:32位除法 ax存被除数低2字节,dx存被除数高2字节,bx存除数,ax存商,dx存余
;被除数设置
xor ax,ax
xor dx,dx
mov ax,[ds:si]
inc si
inc si
mov dx,[ds:si]
inc si
inc si
;除数设置
xor bx,bx
mov bl,10
mov cx,6
l2:
;结果计算
div bx
mov [es:di],dl
inc di
xor dx,dx
loop l2
code1:
;es指向显存,di做指针
mov ax,0xB800
mov es,ax
mov di,0x0
;ds指向待写入数据,si做指针
mov ax,0x07c0
mov ds,ax
mov ax,code
mov si,ax
;循环计数器
mov cx,code-data_res
l3:
;写显存
;al做中转站
dec si
mov al,[ds:si]
add al,0x30;数字转字符串
mov byte [es:di],al
inc di
mov byte [es:di],0x07
inc di
loop l3
jmp $
current:
times (510-(current-start)) db 0
db 0x55,0xAA
2、机器码 对照 汇编代码
1 start:
2 00000000 EB17 jmp code
3
4 00000002 7A data: db 122 ;1byte
5 00000003 E0B1 dw 45536 ;2byte
6 00000005 CFFB0200 dd 195535 ;4byte
7 data_res:
8 00000009 000000F0 db 0,0,0,-16
9 0000000D 0000000000F0 db 0,0,0,0,0,-16
10 00000013 000000000000 db 0,0,0,0,0,0
11
12 code:
13 ;指向数据地址 ds:si
14 00000019 B8C007 mov ax,0x07c0
15 0000001C 8ED8 mov ds,ax
16 0000001E BE[0200] mov si,data
17
18 ;指向存储数据地址 es:di
19 00000021 8EC0 mov es,ax
20 00000023 BF[0900] mov di,data_res
21
22 ;分解开始:16位除法 ax存被除数,bl存除数,al存商,ah存余
23 ;被除数设置
24 00000026 31C0 xor ax,ax
25 00000028 3E8A04 mov al,[ds:si]
26 0000002B 46 inc si
27
28 ;除数设置
29 0000002C 31DB xor bx,bx
30 0000002E B30A mov bl,10
31
32 00000030 B90300 mov cx,3
33 l0:
34 ;结果计算
35 00000033 F6F3 div bl
36 00000035 268825 mov [es:di],ah
37 00000038 47 inc di
38 00000039 30E4 xor ah,ah
39 0000003B E2F6 loop l0
40
41 0000003D 47 inc di;留给空格
42
43 ;分解开始:32位除法 ax存被除数低2字节,dx存被除数高2字节,bx存除数,ax存商,dx存余
44 ;被除数设置
45 0000003E 31C0 xor ax,ax
46 00000040 31D2 xor dx,dx
47 00000042 3E8B04 mov ax,[ds:si]
48 00000045 46 inc si
49 00000046 46 inc si
50
51 ;除数设置
52 00000047 31DB xor bx,bx
53 00000049 B30A mov bl,10
54
55 0000004B B90500 mov cx,5
56 l1:
57 ;结果计算
58 0000004E F7F3 div bx
59 00000050 268815 mov [es:di],dl
60 00000053 47 inc di
61 00000054 31D2 xor dx,dx
62 00000056 E2F6 loop l1
63
64 00000058 47 inc di;留给空格
65
66 ;分解开始:32位除法 ax存被除数低2字节,dx存被除数高2字节,bx存除数,ax存商,dx存余
67 ;被除数设置
68 00000059 31C0 xor ax,ax
69 0000005B 31D2 xor dx,dx
70 0000005D 3E8B04 mov ax,[ds:si]
71 00000060 46 inc si
72 00000061 46 inc si
73 00000062 3E8B14 mov dx,[ds:si]
74 00000065 46 inc si
75 00000066 46 inc si
76
77 ;除数设置
78 00000067 31DB xor bx,bx
79 00000069 B30A mov bl,10
80
81 0000006B B90600 mov cx,6
82 l2:
83 ;结果计算
84 0000006E F7F3 div bx
85 00000070 268815 mov [es:di],dl
86 00000073 47 inc di
87 00000074 31D2 xor dx,dx
88 00000076 E2F6 loop l2
89
90
91 code1:
92 ;es指向显存,di做指针
93 00000078 B800B8 mov ax,0xB800
94 0000007B 8EC0 mov es,ax
95 0000007D BF0000 mov di,0x0
96
97 ;ds指向待写入数据,si做指针
98 00000080 B8C007 mov ax,0x07c0
99 00000083 8ED8 mov ds,ax
100 00000085 B8[1900] mov ax,code
101 00000088 89C6 mov si,ax
102
103 ;循环计数器
104 0000008A B91000 mov cx,code-data_res
105
106 l3:
107 ;写显存
108 ;al做中转站
109 0000008D 4E dec si
110 0000008E 3E8A04 mov al,[ds:si]
111 00000091 0430 add al,0x30;数字转字符串
112 00000093 268805 mov byte [es:di],al
113
114 00000096 47 inc di
115 00000097 26C60507 mov byte [es:di],0x07
116
117 0000009B 47 inc di
118 0000009C E2EF loop l3
119
120 0000009E EBFE jmp $
121 current:
122 000000A0 00<rep 15Eh> times (510-(current-start)) db 0
123 000001FE 55AA db 0x55,0xAA