+ -
当前位置:首页 → 问答吧 → 读过《自己动手写操作系统》请进 一个汇编问题 (没读过也可以进,反正是汇编方面的问题)

读过《自己动手写操作系统》请进 一个汇编问题 (没读过也可以进,反正是汇编方面的问题)

时间:2008-02-13

来源:互联网

在kernel.asm中有一句
  jmp SELECTOR_KERNEL_CS:csinit
csinit: ; “这个跳转指令强制使用刚刚初始化的结构”——<<OS:D&I 2nd>> P90.

选择子指定的段是0~4G的一个段
为什么是jmp xxx:csinit 而不是jmp xxx:文件开始的物理地址+csinit
因为csinit是相对于文件开头的偏移 不是相对于内存的 
在loader.asm中跳转进保护模式就写成了jmp dword SelectorC:(BaseOfLoaderPhyAddr+LABEL_PM_START) 是物理地址加偏移 这才应该是对的啊

但是运行时,2个地方都没出现异常,用bochs调试 发现jmp xxx:csinit 的确jmp到了csinit标签 而不是相对于0x00偏移csinit的地方
这是为什么?

作者: sm_zl_kimi   发布时间: 2008-02-13

jmp有多种编译形式,虽然不懂32位汇编,但是猜想jmp指令对应的不同应用翻译成的指令码应该是不一样的,比如在16位下面有短转跳,有长转跳,有绝对转跳,32位是平坦模式,假如也是有区别的话:

转短跳的参数是相对偏移,不管代码加载到什么地方,相对偏移都是不变的
绝对转跳就不用说了。

作者: jennyvenus   发布时间: 2008-02-13

搜代码
http://code-search.kingofcoder.com/searchCode2.php

作者: kockoc2   发布时间: 2008-02-13

新回的贴子怎么看不见?csdn的bug.

作者: jennyvenus   发布时间: 2008-02-13

感觉跟跨节调用有关吧~~ 同样是《自己动手》的代码:
Assembly code

LABEL_LOADING_FILE:
    push    ax
    push    bx
    mov    ah,0eh
    mov    al,'.'
    mov    bl,0fh
    int    10h
    pop    bx
    pop    ax
    
    mov    cl,1
    call    ReadSector
    xor    eax,eax
    mov    ax,[wFatNo]
    call    GetFATEntry
    cmp    ax,0fffh
    jz    LABEL_LOAD_OVER
    mov    word [wFatNo],ax
    add    ax,RootDirSectors
    add    ax,DeltaSectorNo
    add    bx,[BPB_BytsPerSec]
    mov    cx,BaseOfKernelFile
    mov    es,cx
    jmp    LABEL_LOADING_FILE



这里的LABEL_LOADING_FILE 没必要再加个loader的地址了吧,同样 jmp xxx:csinit 同样是跳到一个节里,也没必要加loader的绝对地址了

我也不肯定 期望和楼主探讨下

作者: littlehedgehog   发布时间: 2008-03-18

还没有读,正准备读

作者: guoxyj   发布时间: 2008-03-19

编译器自动计算标签之间的相对位置

作者: ypyf3000   发布时间: 2008-03-20

什么呀

作者: UltraBejing   发布时间: 2008-05-01

同问!
在保护模式下,这里的SELECTOR_KERNEL_CS应该是个选择子吧,但是为什么SELECTOR_KERNEL_CS定义成下面的样子:
  SELECTOR_KERNEL_CS equ 8
这个是怎么引用到刚刚初始化了的选择子的阿?


问题还没解决,这个贴不能就这么沉了呀!
顶!
 

作者: w5543081   发布时间: 2008-11-28

回复ls

jmp dword 0x08:0xXXXXXXXX
自动把这个selector放到cs寄存器上...


另外,不明白你"为什么SELECTOR_KERNEL_CS定义成下面的样子: SELECTOR_KERNEL_CS equ 8"
是有什么问题?你认为是应该怎么样呢?

希望我的回复能够帮助你 [:-)

作者: harry_1523   发布时间: 2008-11-28

jmp有二种,相对偏移跳转,绝对地址跳转
long或更远时才会是绝对地址跳转
而相对的base都是当前PC ,考虑PC是在文件头?

作者: xiaopoy   发布时间: 2008-11-28

9楼,我感觉你说的点上了,只是还差一点点~~
------------------------------------
jmp dword 0x08:0xXXXXXXXX 
自动把这个selector放到cs寄存器上... 
------------------------------------
jmp dword 0x08:0xXXXXXXXX中0xXXXXXXXX是offset吧,
那么你说的selector 是那个selector呢?

给你看一下源代码吧:
============================================
SELECTOR_KERNEL_CS equ 8 ; 下面jump用到的参数

; 导入函数
extern cstart
extern exception_handler
extern spurious_irq

; 导入全局变量
extern gdt_ptr
extern idt_ptr
extern disp_pos

bits 32

[SECTION .bss]
StackSpace resb 2 * 1024
StackTop: ; 栈顶

[section .text] ; 代码在此

global _start ; 导出 _start
_start:
mov esp, StackTop ; 堆栈在 bss 段中

mov dword [disp_pos], 0


sgdt [gdt_ptr] ; 取得原来GDT的内容,cstart() 中将会用到 gdt_ptr
call cstart ; 在此函数中改变了gdt_ptr,让它指向新的GDT
lgdt [gdt_ptr] ; 使用新的GDT(与原来的GDT一样,只是存储地方不同),加载

lidt [idt_ptr]

jmp SELECTOR_KERNEL_CS:csinit
csinit: ; “这个跳转指令强制使用刚刚初始化的结构”——<<OS:D&I 2nd>> P90.<--不知道书里写
;的么,还没有找到这本书。
;jmp 0x40:0
;ud2
sti
hlt
==================================================================================
以下是选择子的定义:
; GDT ------------------------------------------------------------------------------------------------------------------------------------------------------------

; 段基址 段界限 , 属性
LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符
LABEL_DESC_FLAT_C: Descriptor 0, 0fffffh, DA_CR | DA_32 | DA_LIMIT_4K ; 0 ~ 4G
LABEL_DESC_FLAT_RW: Descriptor 0, 0fffffh, DA_DRW | DA_32 | DA_LIMIT_4K ; 0 ~ 4G
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW | DA_DPL3 ; 显存首地址; 
GDT ------------------------------------------------------------------------------------------------------------------------------------------------------------

GdtLen equ $ - LABEL_GDT
GdtPtr dw GdtLen - 1 ; 段界限
dd BaseOfLoaderPhyAddr + LABEL_GDT ; 基地址

; GDT 选择子 ----------------------------------------------------------------------------------
SelectorFlatC equ LABEL_DESC_FLAT_C - LABEL_GDT
SelectorFlatRW equ LABEL_DESC_FLAT_RW - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT + SA_RPL3
; GDT 选择子 ----------------------------------------------------------------------------------
============================================
如上面所示,上面的选择子有3个,你说的自动选择selector 是选择哪个selector 啊?


接着顶!顶!顶!


作者: w5543081   发布时间: 2008-11-29

关注,那本书叫<操作系统设计与实现>

作者: beijingbeerman   发布时间: 2008-12-02

刚刚又看了看代码,和相关资料。
如下代码:
-------------------------------
jmp SELECTOR_KERNEL_CS:csinit 
-------------------------------

SELECTOR_KERNEL_CS是已经在loader.asm中计算出来的0x08,第一个选择子的相对地址。
而此段代码的编译格式是elf格式文件,里面的csinit是绝对地址,
所以面的jmp会直接跳到此段的csinit 处。


以上的解释是否正确,请大虾批评。

作者: w5543081   发布时间: 2008-12-03

不懂,
学习

作者: xtdumpling   发布时间: 2008-12-03

有点深~~汗

作者: YX799808850   发布时间: 2008-12-03

SELECTOR_KERNEL_CS 是选择子吗?除了kernel.asm还在那个文件中出现过?

作者: beijingbeerman   发布时间: 2008-12-04

这个JMP是为了重新装入CS里的SELECTOR,更深远的意义是在寻址时使用在进入C语言后初始化的GDT,用了段间JMP后寻址就都用新的GDT了。JMP后的EIP就指向csinit这个LABLE,如果用段内JMP的后,JMP后EIP也是指向csinit这个LABLE,但这样的话程序寻址时使用的还是在LOADER时初始化的GDT。
“为什么是jmp xxx:csinit 而不是jmp xxx:文件开始的物理地址+csinit ” 这个问题是因为内核在编译的时候就以经加了个一个偏移了,那个偏移就是内核相对内存物理地址0的偏移了,所以不用像在LOADER里一样处理。而是直接JMP到csinit这个LABLE上。

作者: zhizhi_2008   发布时间: 2008-12-05

一楼正解。跳转的偏移是相对的,相对于正在执行的指令的地址。

作者: areful   发布时间: 2008-12-06

17楼正解。讲的挺清楚了。

作者: w5543081   发布时间: 2008-12-08

不懂,up

作者: filec75   发布时间: 2008-12-08

ding

作者: qap22   发布时间: 2008-12-08

17楼说的很好,怎么不给分啊

作者: huanghengpp   发布时间: 2009-02-17

up一下。。。

作者: caojapan   发布时间: 2009-05-12

我认为:因为kernel.asm文件是他的编译指令与之前的boot.asm和loader.asm编译指令不一样了,换句话说编译kernel.asm 用的是
nasm -f elf -o kernel.o kernel.asm
ld -s Ttext 0x30400 -o kernel.bin kernel.o 
所以kernel.bin 文件内部的指令地址 = 指令相对文件头的相对位移 + 0x30400
因此jmp selector_kernel : csinit 就是 jmp selector_kernel_cs : csinit+0x30400

另外 selector_kernel_cs = 8 是因为 Selectorflatc=8 即 cs=8 它指向拷贝到kernel空间的描述符
LABEL_DESC_FLAT_C 
清楚了吧

作者: cailong1988   发布时间: 2010-11-16

热门下载

更多