这个标题有点唬人,我只是在看《自己动手写操作系统》的第二版《ORANGE’S:一个操作系统的实现》。作者喜欢命令行,我喜欢IDE。我尝试在RadASM下实现了第一个例子的编译与载入,觉得还不错。
RadASM默认只支持用Nasm开发win32应用程序,而写操作系统需要生成bin文件,只能自己修改配置来实现。本着瞎折腾的精神,我就折腾了一个nasm.ini,注意我将32位的nasm编译器放到了安装目录下的Nasm32目录中,所以写了一句$A=$R\Nasm32,读者请自行替换。
[Description] 1=Netwide assembler [Version] Version=2219 [CharTab] 2=0251222522222232;20-2F 3=1111111111242221;30-3F [Open] 0="汇编源文件 (*.asm;*.inc),*.asm;*.inc" 1="资源文件 (*.rc),*.rc" 2="文本文件 (*.txt),*.txt" 3="所有文件 (*.*),*.*" src="汇编文件 (*.asm),*.asm,asm" hdr="头文件 (*.inc),*.inc,inc" mod="模块 (*.asm),*.asm,asm" [CodeMacro] ;KeyWord,InsertBeforeActiveLine,InsertAfterActiveLine ;{I}=Copy indent from keyword line ;{C}=Cr ;{S}=Space ;{T}=Tab ;{$}=Copy Proc/Struct Name ;The macros are set up to assume AutoIndent on 1=%macro,{T},{C}{I}%endmacro 2=istruc,{T},{C}{I}iend 3=struc,{T},{C}{I}endstruc [Code] Skip={C},%include,at,push,mov,cmp Code=$ endp,$ proc Const={C},$ equ Data={C},$ db,$ dw,$ dd,$ dq,$ df,$ dt,$ byte,$ word,$ dword,$ qword,$ resd Macro=%endmacro,%macro $ Struct=iend,istruc $ Struct2=endstruc,struc $ Label={C},$ : [CodeBlock] 1=istruc $,iend,,,6 2=struc $,endstruc,,,14 3=[SECTION,,,,16 4=segment,,,,16 [Api] Trig=call Call=Nasm\nasmApiCall.api Const=Nasm\nasmApiConst.api Struct=Nasm\nasmApiStruct.api Word=Nasm\nasmApiWord.api Message=Nasm\nasmMessage.api Inc=%include,',' Lib= [Edit] Font=宋体 FontHeight=-16 FontWeight=400 TxtFont=宋体 TxtFontHeight=-16 TxtFontWeight=400 TabSize=4 Backup=9 AutoSave=1 BacupPath=$P\Bak\ AutoIndent=1 ApiList=1 ApiToolTip=1 Properties=1 MouseWheel=1 SaveSize=1 Maximize=1 ApiConst=1 CodeWrite=1 TabToSpc=0 ApiStruct=1 PrnFont=宋体 PrnFontHeight=-16 PrnFontWeight=400 PrnPage=20990,29690,1000,1000,1000,1000,0 PrnOption=2,0,1,1,1 PrnColor=0,32768,8421504,255,65280,10485760,10485760,10485760,10485760,10485760,10485760,10485760,10485760,10485760,10485760,0,0,0,0,0,0 FontCharSet=134 TxtFontCharSet=134 PrnFontCharSet=134 ApiWordConv=1 ApiWordLocal=1 CodeFiles=.asm.inc.rc.tpl.rad. FontItalic=0 TxtFontItalic=0 HexFont=新宋体 HexFontHeight=-16 HexFontWeight=400 HexFontItalic=0 HexFontCharSet=134 LnrFont=宋体 LnrFontHeight=-12 DlgFont=宋体 DlgFontHeight=-12 DlgFontWeight=400 DlgFontItalic=0 DlgFontCharSet=134 ToolFont=宋体 ToolFontHeight=-12 ToolFontWeight=400 ToolFontItalic=0 ToolFontCharSet=134 ThreadBuild=1 ChangeNotify=1 ApiShiftSpace=1 HiliteLine=0 HiliteCmnt=0 ProcsToApi=1 EnterOnTab=0 ProcInSBar=0 LnrWidth=4 LnrOnOpen=0 PageSize=66 OpenCollapsed=0 AutoBrackets=1 CodeTooltip=1 BraceMatch=({[,)}],\, [Dialog] Grid=1 GridX=3 GridY=3 SnapToGrid=1 ShowSize=1 SaveRC=1 SimpleProperty=0 [Error] BookMark=3 [Paths] $A=$R\Nasm32 $B=$A $D=$R/AddIns $H=$A/Help $I=$A/Inc $L=$A/Lib $P=$R\Nasm\Projects $S=$R\Nasm\Sniplets $T=$R\Nasm\Templates $M=$R\Nasm\Macro $E=D:/Program Files/emu8086 [MakeFiles] 0=.rap 1=.rc 2=.asm 3=.obj 4=.res 5=.exe 6=.def 7=.dll 8=.txt 9=.lib 10=.mak 11=.hla [Project] Type=Win32 App,Plat App,Dos App Files=Asm,Inc,Rc,Def,Txt,Mak Folders=Bak,Mod,Res MenuMake=编译资源脚本,编译,连接,构建,构建并运行,运行,在调试器中运行,全部构建并运行,编译模块 Group=1 GroupExpand=1 [MakeDefNoProject] MenuMake=1,1,1,1,1,1,1,1,0,0 1=rsrc.res,O,$B\GORC,rsrc.rc 2=$.obj,O,$B\NASMW -fobj,$.asm 3=$.exe,O,$B\ALINK -oPE,$.obj,\nasm\lib\win32.lib,rsrc.res 4=0,0,,$.exe 5=rsrc.obj,O,$B\CVTRES,rsrc.res 6=*.obj,O,$B\NASMW -fobj,*.asm 7=0,0,\OllyDbg\OllyDbg,$.exe 11=rsrc.res,O,$B\GORC,rsrc.rc 12=$.obj,O,$B\NASMW -fobj,$.asm 13=$.exe,O,$B\ALINK -oPE,$.obj,\nasm\lib\win32.lib,rsrc.res 14=0,0,,$.exe 15=rsrc.obj,O,$B\CVTRES,rsrc.res 16=*.obj,O,$B\NASMW -fobj,*.asm 17=0,0,\OllyDbg\OllyDbg,$.exe [Win32 App] Files=1,1,1,0,0 Folders=1,0,1 MenuMake=1,1,1,1,1,1,1,1,0,0 ;x=FileToDelete/CheckExistsOnExit, ;(O)utput/(C)onsole/0,Command, ;MakeFile1[,MakeFile2[,MakeFile3...]] 1=4,O,$B\GORC,1 2=3,O,$B\NASMW -fobj,2 3=5,O,$B\ALINK -oPE -o $5,3,$L\win32.lib,4 4=0,0,,5 5=rsrc.obj,O,$B\CVTRES,rsrc.res 6=*.obj,O,$B\NASMW -fobj,*.asm 7=0,0,\OllyDbg\OllyDbg,5 11=4,O,$B\GORC,1 12=3,O,$B\NASMW -fobj,2 13=5,O,$B\ALINK -oPE -o $5,3,$L\win32.lib,4 14=0,0,,5 15=rsrc.obj,O,$B\CVTRES,rsrc.res 16=*.obj,O,$B\NASMW -fobj,*.asm 17=0,0,\OllyDbg\OllyDbg,5 [Plat App] Files=1,1,0,0,0 MenuMake=0,1,0,1,1,1,1,1,0,0 1=rsrc.res,O,$B/GORC,rsrc.rc 2=$.bin,O,$B/Nasm -fbin,$.asm,-o,$.bin 3=$.com,O,$B/Nasm -g -fbin,$.asm,-o,$.com 4=0,0,,$.com 5=rsrc.obj,O,$B/CVTRES,rsrc.res 6=*.bin,O,$B/Nasm -fbin,*.asm 7=0,0,"$E/emu8086",$.com 11=rsrc.res,O,$B/GORC,rsrc.rc 12=$.bin,O,$B/Nasm -fbin,$.asm 13=$.com,O,$B/Nasm -g -fbin,$.asm,-o,$.com 14=0,0,,$.com 15=rsrc.obj,O,$B/CVTRES,rsrc.res 16=*.bin,O,$B/Nasm -fbin,*.asm,-o,$.bin 17=0,0,"$E/emu8086",$.com [Dos App] Files=1,1,0,0,0 MenuMake=0,1,0,1,1,1,1,1,0,0 1=rsrc.res,O,$B/GORC,rsrc.rc 2=$.obj,O,$B/Nasm -g -fobj,$.asm 3=$.exe,O,$B/Link,$.obj,,,,,,, 4=0,0,,$.exe 5=rsrc.obj,O,$B/CVTRES,rsrc.res 6=*.obj,O,$B/Nasm -g -fobj,*.asm 7=0,0,"$E/emu8086",$.exe 11=rsrc.res,O,$B/GORC,rsrc.rc 12=$.obj,O,$B/Nasm -g -fobj,$.asm 13=$.exe,O,$B/Link,$.obj,,,,,,, 14=0,0,,$.exe 15=rsrc.obj,O,$B/CVTRES,rsrc.res 16=*.obj,O,$B/Nasm -g -fobj,*.asm 17=0,0,"$E/emu8086",$.exe [MenuMake] 1=编译资源脚本(&C),372,M,1 2=编译(&A),116,M,2 3=连接(&L),1652,M,3 4=构建(&B),1396,M,2,3 5=-,0,M, 6=构建并运行(&G),628,M,2,3,4 7=-,0,M, 8=运行(&R),884,M,4 9=在调试器中运行(&D),580,M,7 10=-,0,M, 11=全部构建并运行(&A),1140,M,1,2,3,4 12=-,0,M, 13=编译模块(&M),0,M,6 Ver=100 [Color] UseColor=1 Back=4144959 Fore=12632256 Bar=12550399 Cmnt=8454143 Str=16777215 Oper=2631935 C0=8454016 C1=16777088 C2=16744448 C3=12615935 C4=12615808 C5=11184640 C6=4227327 C7=16711935 C8=33488896 C9=16711808 Output=12058623 Project=12058623 Property=12058623 Dialog=8421376 CmntBack=0 StrBack=0 NumBack=0 OperBack=0 B0=4144959 B1=4144959 B2=4144959 B3=4144959 B4=4144959 B5=4144959 B6=4144959 B7=4144959 B8=4144959 B9=4144959 B10=4144959 B11=4144959 B12=4144959 B13=4144959 B14=4144959 B15=4144959 DivLine=1 NoFlicker=0 SelBack=8388608 SelText=16777215 Num=8421376 HiLine1=15777984 HiLine2=12644544 HiLine3=12632304 BarPen=8421504 LnrFontColor=8388608 Outputtext=0 Projecttext=0 Propertytext=0 Info=12644592 Infotext=0 C10=16711680 C11=16711680 C12=16711680 C13=16711680 C14=16711680 C15=16711680 CustColors=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 [KeyWords] ;Registers C0=AH AL AX BH BL BP BX CH CL CR0 CR2 CR3 CS CX DH DI DL DR0 DR1 DR2 DR3 DR6 DR7 DS DX EAX EBP EBX ECX EDI EDX ES ESI ESP FS GS MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7 SI SP SS ST TR3 TR4 TR5 TR6 TR7 XMM0 XMM1 XMM2 XMM3 ;Instructions C1=ADC ADD AND CALL CBW CLC CLD CLI CMC CMP CMPS CMPSB CMPSW CWD DAS DEC DIV DAA ESC HLT IDIV IMUL IN INC INT INTO IRET JA JAE JB JBE JC JCXZ JE JG JGE JL JLE JMP JNA JNAE JNB JNBE JNC JNE JNG JNGE JNL JNLE JNO JNP JNS JNZ JO JP JPE JPO JS JZ LAHF LDS LEA LES LODS LODSB LODSW LOOP LOOPE LOOPEW LOOPNE LOOPNEW LOOPNZ LOOPNZW LOOPW LOOPZ LOOPZW MOV MOVS MOVSB MOVSW MUL NEG NOP NOT OR OUT POP POPF PUSH PUSHF RCL RCR RET RETF RETN ROL ROR SAHF SAL SAR SBB SCAS SCASB SCASW SHL SHR STC STD STI STOS STOSB STOSW SUB TEST WAIT XCHG XLAT XLATB XOR AAA AAD AAM AAS ;Instructions C2=ARPL BOUND BSF BSR BSWAP BT BTC BTR BTS CDQ CLTS CMPSD CMPXCHG CWDE ENTER INS INSB INSD INSW INVD INVLPG IRETD IRETDF IRETF JECXZ LAR LEAVE LFS LGDT LGS LIDT LLDT LMSW LOCK LODSD LOOPD LOOPED LOOPNED LOOPNZD LOOPZD LSL LSS LTR MOVSD MOVSX MOVZX OUTS OUTSB OUTSD OUTSW POPA POPAD POPFD PUSHA PUSHAD PUSHD PUSHFD PUSHW REP REPE REPNE REPNZ REPZ SCASD SETA SETAE SETB SETBE SETC SETE SETG SETGE SETL SETLE SETNA SETNAE SETNB SETNBE SETNC SETNE SETNG SETNGE SETNL SETNLE SETNO SETNP SETNS SETNZ SETO SETP SETPE SETPO SETS SETZ SGDT SHLD SHRD SIDT SLDT SMSW STOSD STR VERR VERW WBINVD XADD ;FPU Instructions C3=F2XM1 FABS FADD FADDP FBLD FBSTP FCHS FCLEX FCOM FCOMP FCOMPP FCOS FDECSTP FDISI FDIV FDIVP FDIVR FDIVRP FENI FFREE FIADD FICOM FICOMP FIDIV FIDIVR FILD FIMUL FINCSTP FINIT FIST FISTP FISUB FISUBR FLD FLD1 FLDCW FLDENV FLDENVD FLDENVW FLDL2E FLDL2T FLDLG2 FLDLN2 FLDPI FLDZ FMUL FMULP FNCLEX FNDISI FNENI FNINIT FNOP FNSAVE FNSAVED FNSAVEW FNSTCW FNSTENV FNSTENVD FNSTENVW FNSTSW FPATAN FPREM FPREM1 FPTAN FRNDINT FRSTOR FRSTORD FRSTORW FSAVE FSAVED FSAVEW FSCALE FSETPM FSIN FSINCOS FSQRT FST FSTCW FSTENV FSTENVD FSTENVW FSTP FSTSW FSUB FSUBP FSUBR FSUBRP FTST FUCOM FUCOMP FUCOMPP FWAIT FXAM FXCH FXTRACT FYL2X FYL2XP1 ;MMX Instructions C4=EMMS MOVD MOVQ PACKSSDW PACKSSWB PACKUSWB PADDB PADDD PADDSB PADDSW PADDUSB PADDUSW PADDW PAND PANDN PCMPEQB PCMPEQD PCMPEQW PCMPGTB PCMPGTD PCMPGTW PMADDWD PMULHW PMULLW POR PSLLD PSLLQ PSLLW PSRAD PSRAW PSRLD PSRLQ PSRLW PSUBB PSUBD PSUBSB PSUBSW PSUBUSB PSUBUSW PSUBW PUNPCKHBW PUNPCKHDQ PUNPCKHWD PUNPCKLBW PUNPCKLDQ PUNPCKLWD PXOR ;XMM/K3D Instructions C5=#define #include ACCELERATORS ALT AUTOCHECKBOX AUTORADIOBUTTON BEGIN BITMAP BLOCK CAPTION CLASS COMBOBOX CONTROL CURSOR DIALOGEX DISCARDABLE EDITTEXT EXSTYLE FILEOS FILETYPE FILEVERSION FONT GROUPBOX ICON LISTBOX LTEXT MENU MENUITEM NOINVERT POPUP PRODUCTVERSION PUSHBUTTON SEPARATOR SHIFT STRINGTABLE STYLE VALUE VERSIONINFO VIRTKEY C6=BYTE DB DD DQ DT DW DWORD OWORD QWORD REAL10 REAL4 REAL8 SBYTE SDWORD SWORD TBYTE WORD ;NASM Keywords (non-code producing) C7=%DEFINE %ENDMACRO %INCLUDE %MACRO AT CODE DATA ENDSTRUC EQU EXTERN IEND IMPORT ISTRUC RESB RESD RESW SECTION STRUC USE32 ;NASM Keywords (code producing) C8=CALL ;NASM Macro Ops C9= C10= C16= [ReallyRad] AddDlg=1 AddMnu=1 AddRes=1 AddVer=1 CtlClk=1 MnuSel=1 AddFile=1 AddFolder=1 CtlNme=1 AddStr=1 [MenuMacro] Ver=100
然后新建一个plat项目,写入第一章的代码:
org 07c00h ; 告诉编译器程序加载到7c00处 mov ax, cs mov ds, ax mov es, ax call DispStr ; 调用显示字符串例程 jmp $ ; 无限循环 DispStr: mov ax, BootMessage mov bp, ax ; ES:BP = 串地址 mov cx, 23 ; CX = 串长度 mov ax, 01301h ; AH = 13, AL = 01h mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮) mov dl, 0 int 10h ; 10h 号中断 ret BootMessage: db "Hello, OS world! Hankcs" times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节 dw 0xaa55 ; 结束标志
一键编译链接运行,得到bin文件和com文件,在DosBox下是这个效果:
注意上图不协调的黑色行,应该可以显示出字符串,但是没有显示出来,只显示出了黑底没显示红字。
按照作者的指导,将程序性加载地址改为org 0100h后,就可以看到效果了:
org 0100h mov ax, cs mov ds, ax mov es, ax call DispStr ; 调用显示字符串例程 jmp $ ; 无限循环 DispStr: mov ax, BootMessage mov bp, ax ; ES:BP = 串地址 mov cx, 23 ; CX = 串长度 mov ax, 01301h ; AH = 13, AL = 01h mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮) mov dl, 0 int 10h ; 10h 号中断 ret BootMessage: db "Hello, OS world! Hankcs" times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节 dw 0xaa55 ; 结束标志
还可以利用emulator来调试:
用作者提供的FloppyWriter.exe将项目目录下的bin文件写入代码目录下的a.img,然后用VMWare新建一个虚拟机载入a.img,看到屏幕上的红字了:
你好,请问倒数第二张图,emulator是什么软件 ,只用“emulator”搜不出什么有用信息来
emulator是模拟器的意思,也就是各种仿真器,比如bochs,qemu等
单词倒是知道意思,但这词太通用,搜不出东西。在别的论坛上有人认识,是emu8086