完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
c05_mbr.asm
;代码清单5-1 ;文件名:c05_mbr.asm ;文件说明:硬盘主引导扇区代码 ;创建日期:2011-3-31 21:15 mov ax,0xb800 ;指向文本模式的显示缓冲区 mov es,ax ;以下显示字符串“Label offset:” mov byte [es:0x00],‘L’ mov byte [es:0x01],0x07 mov byte [es:0x02],‘a’ mov byte [es:0x03],0x07 mov byte [es:0x04],‘b’ mov byte [es:0x05],0x07 mov byte [es:0x06],‘e’ mov byte [es:0x07],0x07 mov byte [es:0x08],‘l’ mov byte [es:0x09],0x07 mov byte [es:0x0a],‘ ’ mov byte [es:0x0b],0x07 mov byte [es:0x0c],“o” mov byte [es:0x0d],0x07 mov byte [es:0x0e],‘f’ mov byte [es:0x0f],0x07 mov byte [es:0x10],‘f’ mov byte [es:0x11],0x07 mov byte [es:0x12],‘s’ mov byte [es:0x13],0x07 mov byte [es:0x14],‘e’ mov byte [es:0x15],0x07 mov byte [es:0x16],‘t’ mov byte [es:0x17],0x07 mov byte [es:0x18],‘:’ mov byte [es:0x19],0x07 mov ax,number ;取得标号number的偏移地址 mov bx,10 ;设置数据段的基地址 mov cx,cs mov ds,cx ;求个位上的数字 mov dx,0 div bx mov [0x7c00+number+0x00],dl ;保存个位上的数字 ;求十位上的数字 xor dx,dx div bx mov [0x7c00+number+0x01],dl ;保存十位上的数字 ;求百位上的数字 xor dx,dx div bx mov [0x7c00+number+0x02],dl ;保存百位上的数字 ;求千位上的数字 xor dx,dx div bx mov [0x7c00+number+0x03],dl ;保存千位上的数字 ;求万位上的数字 xor dx,dx div bx mov [0x7c00+number+0x04],dl ;保存万位上的数字 ;以下用十进制显示标号的偏移地址 mov al,[0x7c00+number+0x04] add al,0x30 mov [es:0x1a],al mov byte [es:0x1b],0x04 mov al,[0x7c00+number+0x03] add al,0x30 mov [es:0x1c],al mov byte [es:0x1d],0x04 mov al,[0x7c00+number+0x02] add al,0x30 mov [es:0x1e],al mov byte [es:0x1f],0x04 mov al,[0x7c00+number+0x01] add al,0x30 mov [es:0x20],al mov byte [es:0x21],0x04 mov al,[0x7c00+number+0x00] add al,0x30 mov [es:0x22],al mov byte [es:0x23],0x04 mov byte [es:0x24],‘D’ mov byte [es:0x25],0x07 infi: jmp near infi ;无限循环 number db 0,0,0,0,0 times 203 db 0 db 0x55,0xaa c06_mbr.asm ;代码清单6-1 ;文件名:c06_mbr.asm ;文件说明:硬盘主引导扇区代码 ;创建日期:2011-4-12 22:12 jmp near start mytext db ‘L’,0x07,‘a’,0x07,‘b’,0x07,‘e’,0x07,‘l’,0x07,‘ ’,0x07,‘o’,0x07, ‘f’,0x07,‘f’,0x07,‘s’,0x07,‘e’,0x07,‘t’,0x07,‘:’,0x07 number db 0,0,0,0,0 start: mov ax,0x07c0 ;设置数据段基地址 mov ds,ax ;ds寄存器一般保存数据段基地址 mov ax,0xb800 ;设置附加段基地址 mov es,ax ;这里附加段指向显存位置,存放在es寄存器中 cld ;将方向标志位DF清零,以指示传送是负方向的,与此相对应的指令是std mov si,mytext ;movsw指令原始数据串需要存放在ds:si位置,目的地址为es:di,因为ds目前指示的是当前代码段基地址地址,因此只要把偏移mytext存入si寄存器即可 mov di,0 ;当前es指示显存起始位置,因此只要把偏移0存入di即可 mov cx,(number-mytext)/2 ;实际上等于 13,cx作为计数器,每进行一次rep指令cx-1 rep movsw ;一次传送一个字(两个字节) ;得到标号所代表的偏移地址 mov ax,number ;此代码目的旨在显示number的偏移地址 ;计算各个数位 mov bx,ax ;bx指向当前number偏移地址 mov cx,5 ;循环次数 mov si,10 ;除数 digit: xor dx,dx ;dx(被除数高16位)清零 div si ;除法 mov [bx],dl ;保存数位 ;为什么这里不用加0x7c00了? inc bx ;bx自加1,指向下一个内存单元,number一共定义了5个字节内存单元 loop digit ;显示各个数位 mov bx,number mov si,4 show: mov al,[bx+si] ;从后往前显示 add al,0x30 mov ah,0x04 mov [es:di],ax add di,2 dec si jns show ;上一条指令符号位为SF=0(结果为非负)时跳转 mov word [es:di],0x0744 jmp near $ ;无限循环 times 510-($-$$) db 0 ;512字节减去之后两个db指令=510字节,$当前指令偏移,$$当前代码段起始位置,填充字节0(db 0) db 0x55,0xaa c07_mbr.asm ;代码清单7-1 ;文件名:c07_mbr.asm ;文件说明:硬盘主引导扇区代码 ;创建日期:2011-4-13 18:02 jmp near start message db ‘1+2+3+.。.+100=’ start: mov ax,0x7c0 ;设置数据段的段基地址 mov ds,ax mov ax,0xb800 ;设置附加段基址到显示缓冲区 mov es,ax ;以下显示字符串 mov si,message mov di,0 mov cx,start-message @g: mov al,[si] ;因为这是硬盘主引导扇区代码,因此被加载到0x7c00,[si]=[ds:si],就是相对于代码段开头的相对偏移,这个相对偏移就是标签message的值 mov [es:di],al inc di ;di用做显存段地址的相对偏移,字符内容信息放在低一个字节 mov byte [es:di],0x07 inc di ;字符显示信息放在高一个字节 inc si ;si用作寻址字符串相对偏移 loop @g ;以下计算1到100的和 xor ax,ax ;清空ax寄存器,存放结果 mov cx,1 @f: add ax,cx inc cx ;cx做累加器 cmp cx,100 jle @f ;小于等于时跳转 ;以下计算累加和的每个数位 xor cx,cx ;设置堆栈段的段基地址 mov ss,cx mov sp,cx ;堆栈段指针和段基址都在0x0000处,堆栈段从高地址向低地址生长 mov bx,10 xor cx,cx @d: inc cx ;压栈中用cx记录一共压入栈元素个数,以便之后出栈时能及时停止pop xor dx,dx ;被除数[dx:ax] div bx ;除数bx or dl,0x30 ;余数在dx中,但是余数最多到9,因此在dl中就够了,加0x30得到ASCII码 push dx ;dx中只有dl有意义,但是压栈的单位必须是字(两个字节) cmp ax,0 jne @d ;循环跳出时,结果5050每一位被放在栈中 ;以下显示各个数位 @a: pop dx ;出栈,栈顶元素是千位,百位,十位,个位 mov [es:di],dl inc di mov byte [es:di],0x07 inc di loop @a jmp near $ 8086寻址方式总结: 1.寄存器寻址 :mov ax,cx 2.立即寻址 :add bx,0xf000 (目的操作数立即数寻址,源操作数寄存器寻址) 3.直接寻址 :mov ax,[0x5c0f] 4.基址寻址:利用基址寄存器bx/bp中的值作为偏移地址,其中bx默认段寄存器为ds(数据段),bp默认段寄存器为ss(堆栈段)。堆栈段指针寄存器为sp,不要混淆。 如:mov dx,[bp-2] 5.变址寻址:利用变址寄存器si/di中的值作为偏移地址,默认段寄存器为ds 如:mov [si+0x100],al 6.基址变址寻址:利用基址寄存器bx/bp和变址寄存器si/di相加作为偏移地址 如:add word [bx+di],0x3000 加载程序 源程序c08_mbr.asm ;代码清单8-1 ;文件名:c08_mbr.asm ;文件说明:硬盘主引导扇区代码(加载程序) ;创建日期:2011-5-5 18:17 app_lba_start equ 100 ;声明常数(用户程序起始逻辑扇区号) ;常数的声明不会占用汇编地址 SECTION mbr align=16 vstart=0x7c00 ;设置堆栈段和栈指针 mov ax,0 mov ss,ax mov sp,ax mov ax,[cs:phy_base] ;计算用于加载用户程序的逻辑段地址 mov dx,[cs:phy_base+0x02] mov bx,16 div bx mov ds,ax ;令DS和ES指向该段以进行操作 mov es,ax ;以下读取程序的起始部分 xor di,di mov si,app_lba_start ;程序在硬盘上的起始逻辑扇区号 xor bx,bx ;加载到DS:0x0000处 call read_hard_disk_0 ;以下判断整个程序有多大 mov dx,[2] ;曾经把dx写成了ds,花了二十分钟排错 mov ax,[0] mov bx,512 ;512字节每扇区 div bx cmp dx,0 jnz @1 ;未除尽,因此结果比实际扇区数少1 dec ax ;已经读了一个扇区,扇区总数减1 @1: cmp ax,0 ;考虑实际长度小于等于512个字节的情况 jz direct ;读取剩余的扇区 push ds ;以下要用到并改变DS寄存器 mov cx,ax ;循环次数(剩余扇区数) @2: mov ax,ds add ax,0x20 ;得到下一个以512字节为边界的段地址 mov ds,ax xor bx,bx ;每次读时,偏移地址始终为0x0000 inc si ;下一个逻辑扇区 call read_hard_disk_0 loop @2 ;循环读,直到读完整个功能程序 pop ds ;恢复数据段基址到用户程序头部段 ;计算入口点代码段基址 direct: mov dx,[0x08] mov ax,[0x06] call calc_segment_base mov [0x06],ax ;回填修正后的入口点代码段基址 ;开始处理段重定位表 mov cx,[0x0a] ;需要重定位的项目数量 mov bx,0x0c ;重定位表首地址 realloc: mov dx,[bx+0x02] ;32位地址的高16位 mov ax,[bx] call calc_segment_base mov [bx],ax ;回填段的基址 add bx,4 ;下一个重定位项(每项占4个字节) loop realloc jmp far [0x04] ;转移到用户程序 ;------------------------------------------------------------------------------- read_hard_disk_0: ;从硬盘读取一个逻辑扇区 ;输入:DI:SI=起始逻辑扇区号 ; DS:BX=目标缓冲区地址 push ax push bx push cx push dx mov dx,0x1f2 mov al,1 out dx,al ;读取的扇区数 inc dx ;0x1f3 mov ax,si out dx,al ;LBA地址7~0 inc dx ;0x1f4 mov al,ah out dx,al ;LBA地址15~8 inc dx ;0x1f5 mov ax,di out dx,al ;LBA地址23~16 inc dx ;0x1f6 mov al,0xe0 ;LBA28模式,主盘 or al,ah ;LBA地址27~24 out dx,al inc dx ;0x1f7 mov al,0x20 ;读命令 out dx,al .waits: in al,dx and al,0x88 cmp al,0x08 jnz .waits ;不忙,且硬盘已准备好数据传输 mov cx,256 ;总共要读取的字数 mov dx,0x1f0 .readw: in ax,dx mov [bx],ax add bx,2 loop .readw pop dx pop cx pop bx pop ax ret ;------------------------------------------------------------------------------- calc_segment_base: ;计算16位段地址 ;输入:DX:AX=32位物理地址 ;返回:AX=16位段基地址 push dx add ax,[cs:phy_base] adc dx,[cs:phy_base+0x02] shr ax,4 ror dx,4 and dx,0xf000 or ax,dx pop dx ret ;------------------------------------------------------------------------------- phy_base dd 0x10000 ;用户程序被加载的物理起始地址 times 510-($-$$) db 0 db 0x55,0xaa |
|
|
|
只有小组成员才能发言,加入小组>>
4345个成员聚集在这个小组
加入小组3287 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4232 浏览 1 评论
4238 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 02:17 , Processed in 0.665743 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号