汇编学习2

摘要

通过编写一个分解整数并显示的一个程序,来学习一些汇编的基础指令和语法

主引导扇区

处理器在加电或者复位以后,如果硬盘是首选的启动设备,那么ROM-BIOS将试图读取硬盘的0面0道1扇区。这就是主引导扇区,会先把主引导扇区的代码(指令集)加载到内存,然后处理器来执行,一般主引导扇区是用来启动操作系统的。但此次,我们把编写的程序加载到主引导扇区,让它被处理器执行。

程序的基本思想

怎么让屏幕上显示字符

为了显示文字,主要是依靠显示器和显卡,显卡里面有一个存储器,通常称为显存。显存是用来告诉显示器应该显示什么字符。显示器的最小单位是像素。
一开始想的是将显存里面的二进制数和像素对应起来,比如1对应亮,0对应不亮(也就是黑),但这只能黑白形式,现在都是彩色的了,所以就用到了3个字节来表示颜色。
另一个问题是,将二进制数和像素一 一 对应起来,是很麻烦的,这里引入了ASCII码,我们不需要想显存里面存的数怎么和像素联系起来,只需要在显存里面写入这个字符的ASCII码,就可以在屏幕上显示出来了(这中间的一些技术细节,就是字符发生器和控制电路的事情了)
我们知道,显存是在显卡上面的,处理器需要访问显卡,才能让字符显示出来,这个过程有点麻烦了,效率不高,所以想到直接让显存映射到内存里面,内存里面专门划出一片空间来和显存映射。一般0xB8000-0XBFFFF这段物理空间是留给显卡的。

怎么保存分解的那些数

直接用寄存器来保存分解的数显然是不太好的,一个是寄存器的数量有限,另一个是寄存器还有它别的任务得做,所以想到直接在内存里面开辟出一段连续的空间,这些空间来放被分解的数。

怎么显示那些被分解的数位

很简单,因为0X8000-0XBFFFF是和显存形成映射的,直接把那些分解的数用mov指令移到那片内存地址就OK了。

贴上最终代码及解释

1 ;代码清单5-1 “;”代表注释符
2 ;文件名:c05_mbr.asm
3 ;文件说明:硬盘主引导扇区代码
4 ;创建日期:2011-3-31 21:15
5
6 mov ax,0xB800
7 mov es,ax
6.7行执行后,es段寄存器指向了内存地址0xB800,也就是用来显示字符的那一片地址区域
8
9 ;以下显示字符串"Label offset:"
10 mov byte [es:0x00],‘L’ 这里的’L’也可以换成对应的ASCII 0X4c;[ ]代表是内存地址
11 mov byte [es:0x01],0x07
12 mov byte [es:0x02],‘a’
13 mov byte [es:0x03],0x07
14 mov byte [es:0x04],‘b’
15 mov byte [es:0x05],0x07
16 mov byte [es:0x06],‘e’
17 mov byte [es:0x07],0x07
18 mov byte [es:0x08],‘l’
19 mov byte [es:0x09],0x07
20 mov byte [es:0x0a],’ ’
21 mov byte [es:0x0b],0x07
22 mov byte [es:0x0c],“o”
23 mov byte [es:0x0d],0x07
24 mov byte [es:0x0e],‘f’
25 mov byte [es:0x0f],0x07
26 mov byte [es:0x10],‘f’
27 mov byte [es:0x11],0x07
28 mov byte [es:0x12],‘s’
29 mov byte [es:0x13],0x07
30 mov byte [es:0x14],‘e’
31 mov byte [es:0x15],0x07
32 mov byte [es:0x16],‘t’
33 mov byte [es:0x17],0x07
34 mov byte [es:0x18],’:’
35 mov byte [es:0x19],0x07
36
37 mov ax,number ;取得标号number的汇编地址(也可以说偏移地址)
38 mov bx,10 ;因为分解数要不断除以10,这里10放到了bx寄存器里面作除数用的
39
40 ;设置数据段的基地址
41 mov cx,cs ;41.42作用是让数据段寄存器和代码段寄存器指向同一个段地址
42 mov ds,cx
43
44 ;求个位上的数字
45 mov dx,0
46 div bx
47 mov [0x7c00+number+0x00],dl ;保存个位上的数字,主引导扇区的代码是从0x7C00开始加载的,所以需要加上。
48
49 ;求十位上的数字
50 xor dx,dx ;这里直接把dx,dx归0了,因为是异或运算,而且效率要比mov dx ,0高
51 div bx
52 mov [0x7c00+number+0x01],dl ;保存十位上的数字
53
54 ;求百位上的数字
55 xor dx,dx
56 div bx
57 mov [0x7c00+number+0x02],dl;保存百位上的数字
58
59 ;求千位上的数字
60 xor dx,dx
61 div bx
62 mov [0x7c00+number+0x03],dl ;保存千位上的数字
63
64 ;求万位上的数字
65 xor dx,dx
66 div bx
67 mov [0x7c00+number+0x04],dl ;保存万位上的数字
68
69 ;以下用十进制显示标号的偏移地址
70 mov al,[0x7c00+number+0x04]
71 add al,0x30
72 mov [es:0x1a],al
73 mov byte [es:0x1b],0x04
74
75 mov al,[0x7c00+number+0x03]
76 add al,0x30
77 mov [es:0x1c],al
78 mov byte [es:0x1d],0x04
79
80 mov al,[0x7c00+number+0x02]
81 add al,0x30
82 mov [es:0x1e],al
83 mov byte [es:0x1f],0x04
84
85 mov al,[0x7c00+number+0x01]
86 add al,0x30
87 mov [es:0x20],al
88 mov byte [es:0x21],0x04
89
90 mov al,[0x7c00+number+0x00]
91 add al,0x30
92 mov [es:0x22],al
93 mov byte [es:0x23],0x04
94
95 mov byte [es:0x24],‘D’
96 mov byte [es:0x25],0x07
97
98 infi: jmp near infi ;无限循环
99
100 number db 0,0,0,0,0 ;db是一个伪指令,不会被编译成机器码,用来声明,这里相当于开辟了5个字节的内存空间,然后都初始化为0了方便存储分解之后的数位。然后number是一个标号,可以代表该处的汇编地址,一般被用来引用
101
102 times 203 db 0 ;重复执行203次db 0 命令,相当于开辟了连续的203字节的内存空间且置于0
103 db 0x55,0xaa ;保证主引导扇区的结尾格式

一些指令

mov指令

mov指令用于数据传送
1.mov指令的目的操作数不能是立即数
2.目的操作数和源操作数不允许同时为内存单元
3.目的操作数必须是通用寄存器或者内存单元
传送指令只影响目的操作数的内容,不改变源操作数的内容
比如 mov ah,bh 指令执行后,ah和bh的内容相同

div指令

div是除法指令
第一种类型是 16位的二进制数除以8位二进制数
这种情况下,被除数必须在寄存器AX中,必须事先传到AX里,除数可以由8位通用寄存器或者内存单元提供。指令执行后,商在寄存器AL中,余数在AH中
第二种类型是用32位的二进制数除以16位的二进制数,因为16位寄存器只能放16位的,所以要拆开放,高16位放在DX中,低16位放在AX中,除数可以由16位通用寄存器或者内存单元提供,指令执行 后,商在AX中,余数在DX中

汇编地址

一般是编译时,编译器生成的地址,每个指令都对应一个,是从0开始的,第一个指令对应的汇编地址是0

标号

标号可以代表该指令处对应的汇编地址,一般是在汇编程序里面被引用的。

伪指令

像db dw 这些都是伪指令,也就是说不能被编译成机器码的,编译完成后,自动消失,只在编译时起作用。
DB是用来声明的,DB是声明字节,跟在后面的数都占一个字节。
DW是声明字数据
DD是声明双字数据
DQ是声明四字数据

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值