ASM 板


LINE

看板 ASM  RSS
曾经在这篇 ( http://goo.gl/mgVNVM )提到 os porcess 的切换, 那时候令我兴奋不已 。但当时的概念还是很模糊, 我决定要用我自己的话来说明这个概念, 也证明我真的搞懂 。 化繁为简是我的学习原则, 对於 process 切换的掌握度还不够, 打算用自己的方法来实 作一个 process 切换的程式。希望这程式符合几点: 程式码小 在 dos 下执行 使用 x86 real mode 上述这些条件都是为了简单, 若能用小小的程式以及简单的执行环境就可以完成 process 切换, 相信理解起来会容易些。在 dos 使用 .com 执行档, 可以让我的程式最 大有 64 K 那麽大 (那麽小), 对於所有程式码都是自己打造的来说, 已经非常够用, boot 磁区那 512 byte 才真的不够人用。 那这程式有多小呢?大概像下面这样: simple_proc.S 1 #define STACK_FRAME_OFFSET 6 2 .code16 3 .text 4 .global begin 5 begin: 6 xchg %bx, %bx #bochs magic break point 7 cli 8 9 xor %eax, %eax 10 mov %cs,%ax 11 mov %ax,%ds 12 13 ## reset 0x30 interrupt 14 movw $0x0, %bx 15 movw %bx, %es 16 movw $switch_proc, %es:0xc0 # isr offset 17 movw %ax, %es:0xc2 #isr seg 18 19 20 movw $0xb800, %ax 21 movw %ax, %gs 22 23 ## set stack frame eip 24 movw $proc_a, stack_frame 25 movw $proc_b, stack_frame+STACK_FRAME_OFFSET 26 27 ## set stack frame cs 28 movw %cs, %ax 29 movw %ax, stack_frame+2 30 movw %ax, stack_frame+STACK_FRAME_OFFSET+2 31 32 ## set stack frame flag 33 # get flag 34 pushf 35 movw (%esp), %ax 36 popf 37 movw %ax, stack_frame+4 38 movw %ax, stack_frame+STACK_FRAME_OFFSET+4 39 40 int $0x30 41 42 mov $0x4c00, %ax 43 int $0x21 44 45 cur_proc: 46 .word 0x0 51 52 .space 256, 0 53 proc_stack_top_a: 54 .space 256, 0 55 proc_stack_top_b: 56 57 stack_frame: 58 .word 0x0# eip 59 .word 0x1# cs 60 .word 0x2# flag 61 62 .word 0x0# eip 63 .word 0x1# cs 64 .word 0x2# flag 65 66 .global proc_a 67 proc_a: 68 1: 69 mov $0x1, %ax 70 int $0x30 71 jmp 1b 72 73 .global proc_b 74 proc_b: 75 1: 76 mov $0x2, %bl 77 int $0x30 78 jmp 1b 79 80 .global switch_proc 81 switch_proc: 82 movw cur_proc, %dx 83 cmp $stack_frame, %dx 84 je 1f 85 movw $stack_frame, cur_proc 86 jmp 2f 87 1: 88 movw $stack_frame+STACK_FRAME_OFFSET, cur_proc 89 2: 90 movw cur_proc, %sp 91 iret 66 .global proc_a 67 proc_a: 68 1: 69 mov $0x1, %ax 70 int $0x30 71 jmp 1b 72 73 .global proc_b 74 proc_b: 75 1: 76 mov $0x2, %bl 77 int $0x30 78 jmp 1b proc_a 和 proc_b 便是我们的两个 process, 你可能会抗议那明明就只是两个 function 。是的, 你没说错, 但你写的 c main 程式是不是也只是个 function, 而你却认为他是 一个 process 呢?若使用 call proc_a, call proc_b, 那是 function 的用法, 不是 process, 所以接下来的程式码要用很其特的方法 (iret) 来执行 proc_a, proc_b。 这两个 process 只有 3 行, 够简单, 只要略懂组合语言的程式员, 几乎不用说明就可看 懂。使用的 process 切换方式是类似 windows 3.1 的 non-preemptive 方式, 需要由 process 自己释放 cpu 来让其他 process 执行。int $0x30 就是用来做这件事情。当然 我可以把 int $0x30 包装成类似 os_yield(), 不过这样复杂度就提高了。 ( http://goo.gl/trgST8 ) 上图可以说明一切, 也许你会嫌字很丑, 应该用电脑画才是, 不过手工可是很难得的。重 点在 stack_frame, 里头有 3 个栏位: 分别代表 eip, cs, flag, 用来储存 proc_a, proc_b 目前的这 3 个值。int 0x30 isr 便是切换 stack_frame, stack_frame+6 来执 行 proc_a, proc_b。 节录 ref 1 的 int 指令做的事情: 把旗标暂存器 push 堆叠 禁止其他中断发生 清除陷阱旗标 把 CS 暂存器 push 堆叠 把 INT n 的下一指令位址 push 堆叠 由 0000:(4n) 位址取出中断服务程式所在位址,并执行长程跳跃指令,至该处继续执行 节录 ref 1 的 iret 指令做的事情: 由堆叠中 pop 4 bytes (cs:ip),并把控制权交到该 4 bytes 所指位址 由堆叠 pop 旗标暂存器 (2 bytes) 所以就是这样来让 proc_a, proc_b 可以轮流执行。先把 proc_a, %cs 的值填到 stack_frame eip, cs 的地方 (stack_frame, stack_frame+2), 将 %sp 指到 stack_frame 或是 stack_frame+6 的地方, 然後发动 iret 即可跳到 proc_a 或是 proc_b。因为 iret 会把 stack_frame, stack_frame+2 载入到 %eip, %cs, 而 cpu 会 执行 %cs:%eip 指向的程式码, 就会去执行 proc_a, 这就是和直接 call proc_a 不同的 执行方式。 int 指令则会把下一个指令的 %cs:%eip 存到 %ss:%esp 指到的地方, 所以 int 发动的 时候, 会把 proc_a 下个指令存到 stack_frame, stack_frame+2 里头, 等着我们下次发 动 iret 再让 proc_a 执行起来; 执行 proc_b 也是同样的道理, 很容易理解吧! 这程式的执行结果不重要, 重要的是执行过程, 怎麽感受这个执行过程? 我是用 bochs 内建 debugger single step, 观察所有暂存器, stack 来检查程式是否有真的执行切换 。 6 xchg %bx, %bx #bochs magic break point 是 bochs magic break point, 程式执行到这行, 会让 bochs 中断停下来, 就可使用 single step指令来观察整个程式行为。 而程式的过程便是在 proc_a, proc_b 之前相互执行, 为了简单, 我没有印出任何字元, 所以从萤幕上看不出任何事情, 为了有趣, 我自己倒是写了一个印出 a, b 的版本, 有兴 趣的朋友可以自己改看看, 在 proc_a 印出 a, prob_b 印出 b。 这个程式该怎麽执行呢? makefile 规则会把这只程式编译成 .com, 直接 copy 到 dos 执行即可, 再使用 bochs 的内建除错器就可以追踪整个流程。dos 环境最好不要载入任 何记忆体管理程式, ex: himem.sys, emm386.exe, 在我测试改写 0x30 中断时, 会造成 一些问题, 我花了不少时间排除这问题。 程式很简单, 说明也很简单, 希望不要造成误会, 如果你已经理解这篇的解释, process switch 并没有这麽简单, 我简化很多东西, 这没有考虑很周严 (ex: 没有保存所有的暂 存器), 真正的 process switch 还要加上不少 code, 而且我还没搞定 x86 real mode 如何保存 %esp 的问题。x86 保护模式在权限切换时, iret/int 指令会保存 %ss:%esp。 这程式若用上保护模式, 那得加上不少 code, 模糊了我要表达的事情, 就先这样。 尽管有如此缺失, 但用来作为 process switch 的实作理解, 不到 100 行的组合语言程 式能发挥如此功用, 已经足够。 下篇文章 x86 process switch implementation (1) ( http://goo.gl/A7n5ig ) 就会复 杂一点了。 soure code: https://github.com/descent/process ( http://goo.gl/IflJmV ) git commit : d25cb21e036b953f19ec69610c411c550dcfa8d6 x86 中断改写参考资料: 第 36 章 中断 ( http://goo.gl/ZtwD1T ) 中矢量表的构 ( http://goo.gl/ITR76N ) 中服程序 ( http://goo.gl/gKGIzS ) f=false ( http://goo.gl/36DfaE ) channel=fflb ( http://goo.gl/H3JeLD ) // 本文使用 Blog2BBS 自动将Blog文章转成缩址的BBS纯文字 http://goo.gl/TZ4E17 // blog 原文 http://descent-incoming.blogspot.tw/2013/03/x86-process-switch-implementation-0-in.html -- 凡经我手, 必属佳作。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 58.114.140.223
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/ASM/M.1413561837.A.B7E.html ※ 编辑: descent (58.114.140.223), 10/18/2014 00:11:11







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP