当裸机之下没有org 0x7c00之后
来源:互联网 发布:蚁族的奋斗 知乎 编辑:程序博客网 时间:2024/06/05 23:40
this is my first blog !!!
测试系统:Ubuntu
汇编器:Nasm
虚拟机:virtualbox
当没有使用保护模式下实现打印‘AB’这两个字符在屏幕的代码如下,这很简单
代码在执行的时候,CS=0,IP=0X7C00,标号的偏移量从0X7C00计起
org 0x7c00
start:
mov ax,cs
mov ds,ax
mov es,ax
mov ax,0xb800
mov gs,ax
mov word [gs:0],0x0741 ; 打印‘A’
mov word [gs:2],0x0c42 ; 打印‘B’
jmp $
times 510-($-$$) db 0
dw 0xaa55
接着,我们时入保护模式:在实模式下只打印‘A’,然后到保护模式下打印‘B’
org 0x7c00
[BITS 16]
start:
mov ax,cs
mov ds,ax
mov es,ax
mov ax,0xb800
mov gs,ax
mov word [gs:0],0x0741
cli
lgdt [ gdtr ]
mov eax,cr0
or al,1
mov cr0,eax
jmp codesel:protectedmode
[BITS 32]
protectedmode:
mov ax,videosel
mov gs,ax
mov word [gs:2],0x0c42
jmp $
[BITS 16]
gdtr:
dw gdt_end - gdt - 1
dd gdt
gdt:
nullsel equ $-gdt
dd 0,0
codesel equ $-gdt
dw 0xffff
dw 0
db 0
dw 0xcf9a
db 0
datasel equ $-gdt
dw 0xffff
dw 0
db 0
dw 0xcf92
db 0
videosel equ $-gdt
dw 3999
dw 0x8000
db 0xb
dw 0x0092
db 0
gdt_end:
times 510-($-$$) db 0
dw 0xaa55
好了,最后的一个版本里头,我把org 0x7c00这条指令干掉,因为有某个特殊情况下,我们不能使用它
然后麻烦的问题就来了,所有的标号偏移量从0计起,解决的方法大致就是把“一部分”的加上0X7C00,
但有“小部分”的标号不能加0X7C00!为了防止太多的标号引起BUG,我把很多标号干掉了,用$来代替。。。
OFFSET equ 0x7c00
[BITS 16]
real_mode:
; 把CS和IP的值交换过来
; 并把IP的值指定第4行"mov ax,cs"这条指令的起始位置
db 0xea
dw $+4
dw 0x7c0
; OK,此时CS的值改变了,所以设置其他段寄存器
mov ax,cs
mov ds,ax
mov es,ax
; 在屏幕上打印一个灰色的字符‘A’
mov ax,0xb800
mov gs,ax
mov word [gs:0],0x0741
; 加载gdtr这个寄存器的值,并启动保护模式
cli
lgdt [ gdtr ] ;为什么这里没有加上OFFSET? 因为此时DS=0x7c0
mov eax,cr0
or al,0x01
mov cr0,eax
; 好了,现在跳转到protected_mode
jmp 8 : $+5+OFFSET
[BITS 32]
;protected_mode:
; 在屏幕上打印一个绿色的字符‘B’,位于之前打印的字符‘A’之后
mov ax,24
mov gs,ax
mov word [gs:2],0x0c42
dw 0xfeeb
[BITS 16]
gdtr:
dw 31 ; 总共有4个描述符,32=4*8-1=32-1
dd $+4+OFFSET
; 空的描述符,虽然没用,但不能没有
dd 0,0
; 代码段描述符
dw 0x0ffff ; 4G
dw 0x0
db 0x00
dw 0xcf9a
db 0x00
; 数据段描述符
dw 0x0ffff ; 4G
dw 0x0
db 0x00
dw 0xcf92
db 0x00
; 显示屏的描述符
dw 3999 ; 80 cols * 25 * rows * 2bytes - 1
dw 0x8000
db 0x0b
dw 0x0092
db 0x00
times 510-($-$$) db 0
dw 0xAA55
以上的三个版本的代码都可以正常地运行 ,我已经测试过了.....
- 当裸机之下没有org 0x7c00之后
- ORG 0x7C00
- org 0x7c00解疑
- 0x7c00解疑
- 0x7C00 理解
- 0x7c00引导地址详解
- 为什么GRUB起始地址为0x7c00.
- vs2010安装之后没有framework2.0
- 为什么bios将mbr装载到0x7c00地址,0x7c00怎么来的?
- 为什么bios将mbr装载到0x7c00地址,0x7c00怎么来的?
- 为什么bios将mbr装载到0x7c00地址,0x7c00怎么来的?(翻译)
- 为什么bios将mbr装载到0x7c00地址,0x7c00怎么来的?
- 当.emacs修改之后
- android6.0之下apk运行正常,6.0之后突然一直报需要某个权限且apk崩溃
- 当Web2.0瓦解了洗脑文化之后
- 当Web2.0瓦解了洗脑文化之后
- 当外部div没有设置高度 或者内部div float之后 边框 内外边距等不起作用的解决办法
- [Sencha ExtJS6 Modern] 改进bug: 当store.remove/removeAt执行之后,DataView的对应item的dom没有移除
- hive中的复杂类型使用
- 利用POI生成Excel并通过Servlet下载示例
- 第八周实验报告(二)
- 第九周实验报告(4)
- try..catch..finally块中的跳转语句(return,break,continue)使用注意事项
- 当裸机之下没有org 0x7c00之后
- C++程序设计实验报告(9-5)
- <<我的邮件客户端(mutt+getmail+msmtp+procmail)>>
- 如何运行android sdk sample中的单元测试
- 第九周任务2
- R树
- CMake 错误
- php高级编程-函数
- rapidsvn "remains in tree conflict"的解决方法