這份文件用來解釋如何用組合語言來開發MikeOS的軟體。他將說明所需要的工具,即MikeOS程式是如何運作的。和使用核心所提供的系統呼叫。假如你有任何問題,可以參考MikeOS網站中有連絡的細節與信箱列表資訊。 點擊左邊的連結來瀏覽這份文件。 概觀 介紹 許多MikeOS程式在16位元下撰寫,真實模式的組合語言。(作業系統也包含一個BASIC解譯器)因為MikeOS和他的程式被放在單一個64K記憶體區段,你不需要關注使用的區段暫存器。 MikiOS程式載入到32K 點(32768)的區段,且最大為32K。結果,你的程式將會用下面這兩行做開頭: BITS 16 ORG 32768 在MikeOS中有許多系統呼叫用來控制螢幕,取得輸入,操作字串,載入/儲存檔案等等。所有的MikeOS系統呼叫通過對暫存器傳遞參數,而非堆疊。要在你的程式中使用它,你需要; %INCLUDE "mikedev.inc" 這沒有包含任何碼,但會有等同的指令指向核心中的系統呼叫向量。所以,引入這個檔案你才能呼叫。MikeOS的os_print_string常式不用確實知道他在核心的哪個位置。mikedev.inc被包括在MikeOS下載中的programs/目錄─他也提供一個對系統呼叫的快速參考。 假如一個MikeOS程式在指令行下執行,一個或多個參數被提供給指令,他們會藉由SI暫存器傳遞給程式通過一個零結束的字串。 需要的工具 寫下MikeOS程式你需要: NASM ─ 一個強大,免費且開放原始碼的組譯器 mikedev.inc ─ 系統呼叫向量描述在上面 一個方式新增程式到磁片 細節是:MikeOS使用NASM在他的程式和核心程式碼,所以我們在這裡推薦他。當然你可以使用任何組譯器來輸出二元檔案且接受16位元碼。NASM在許多Linux系統中可以取得,或你也可以從這裡下載Windows版本(取得'win32'檔案)。 第二點,複製programs/mikedev.inc 第三點,假如你要寫入MikeOS到實體硬碟,你只要複製你的.BIN程式到磁片上(僅有根目錄),啟動MikeOS並測試他。假如你在虛擬mikeos.flp磁片影像下工作,可以查看使用者手冊中的複製檔案。 例子 程式碼 這裡有一個MikeOS程式的範例,使用NASM格式,用來印出一段文字到螢幕上,且等待使用者按下一個按鍵: BITS 16 ORG 32768 %INCLUDE 'mikedev.inc' start: mov si, mystring call os_print_string call os_wait_for_key ret mystring db 'My first MikeOS program!', 0 建置 將上面的程式儲存為testapp.asm,並輸入指令來組譯他(在Windows和Linux都適用): nasm -f bin -o testapp.bin testapp.asm 使用-f bin選項用來告訴NASM,我們想要一個二元檔案:沒有標頭或片段。結果的可執行檔是testapp.bin,我們可以複製到我們的磁片或加入到虛擬磁片影像,描述在使用者手冊中的複製檔案。然後我們可以啟動MikeOS並執行程式。 解釋 這是一個簡短的程式,但是我們將描述他是如何工作的。最初的三行不能被組譯為機器碼指令,但是這個宣告告訴NASM我們要在16位元模式下操作,我們的碼被寫入執行從32K的位置,我們將使用MikeOS API中的系統呼叫。 接下來,我們有一個'start:'標籤,他能讓我們的程式更清楚。我們放入零結束字串的位置到SI暫存器,然後呼叫MikeOS中的os_print_string常式,我們能存取藉由在mikedev.inc中的向量列表。之後我們暫停程式直到使用者按下一個鍵。 所以的MikeOS程式必須以ret指令結束,傳回控制權到作業系統中,之後我們擁有資料給我們的字串。 系統呼叫 介紹 MikeOS核心包含系統呼叫用來輸出到螢幕上,取得鍵盤輸入,操作字串,產生PC聲音,數學運算,硬碟輸入輸出。你可以參考mikedev.inc,和查看使用這些 呼叫的練習從programs/目錄。 這裡我們有一個細節API的描述。你可以查看系統呼叫的完整的程式碼從source/features目錄。每個API都包含了組譯程式碼,所以你能增強系統呼叫的功能,須參考MikeOS系統開發者手冊。 磁碟 os_get_file_list 產生磁碟的檔案字串,檔案間以逗號分隔 IN/OUT: AX = 儲存零結束檔名字串之位置 Example: mov ax, .filestring call os_get_file_list ; Now .filestring will contain something like ; 'HELLO.BIN,FOO.BAR,THREE.TXT', 0 .filestring times 256 db 0 os_load_file 載入檔案到RAM IN: AX=檔案位置,CX=在RAM中載入檔案的位置 OUT:BX=檔案大小(以bytes計), carry set if file not found 例子: mov ax, filename mov cx, 36960 ; 4K after where external program loads call os_load_file ... filename db 'README.TXT' os_write_file 儲存檔案到磁碟(最大64K) IN: AX = 檔名, BX = 資料位置, CX = 寫入多少位元組 OUT: Carry clear if OK, set if failure Example: ; For this example, there's some text stored in .data mov ax, .filename mov bx, .data mov cx, 4192 call os_write_file .filename db 'HELLO.TXT', 0 .data times 4192 db 0 os_file_exists 檢查檔案是否存在於磁片 IN: AX = 檔名位置 OUT: carry clear if found, set if not Example: mov ax, .filename call os_file_exists jc .not_found ... .not_found: ; Print error message here .filename db 'HELLO.TXT', 0 os_create_file 建立一個新的零個位元組的檔案到磁片中 IN: AX = 檔名位置 OUT: Nothing Example: mov ax, .filename call os_create_file ... .filename db 'HELLO.TXT', 0 os_remove_file 從檔案系統中刪除指定的檔案 IN: AX = 要刪除的檔名位置 OUT: Nothing os_rename_file 在磁碟中更改檔案名稱 IN: AX = 要更改的檔案之檔名, BX = 新的檔名 (零結束字串) OUT: carry set on error Example: mov ax, .filename1 mov bx, .filename2 call os_rename_file jc .error ... .error: ; File couldn't be renamed (may already exist) .filename1 db 'ORIG.TXT', 0 .filename2 db 'NEW.TXT', 0 os_get_file_size 取得指定檔案之檔案大小資訊 IN: AX = 檔名 OUT: BX = 檔案大小以位元組計 (最大 64K) or carry set if file not found Keyboard os_wait_for_key Waits for keypress and returns key IN: Nothing OUT: AX = key pressed, other regs preserved Example: .loop: call os_wait_for_key cmp al, 'y' je .yes cmp al, 'n' je .no jmp .loop os_check_for_key Scans keyboard for input, but doesn't wait IN: Nothing OUT: AX = 0 if no key pressed, otherwise scan code Example: see code above Math os_bcd_to_int Converts binary coded decimal number to an integer IN: AL = BCD number OUT: AX = integer value Example: mov al, 00010110b ; 0001 0110 = 16 (decimal) or 10h in BCD call os_bcd_to_int ; AX now contains the 16 bit-integer 00000000 00010000b os_long_int_negate Multiply value in DX:AX by -1 IN: DX:AX = long integer OUT: DX:AX = -(initial DX:AX) Example: mov dx, 01h mov ax, 45h call os_long_int_negate ; DX now contains 0xFFFF ; and AX 0xFEBB os_get_random Get a random integer between high and low values (inclusive) IN: AX = low integer, BX = high OUT: CX = random number between AX and BX Misc os_get_api_version Return current version of MikeOS API IN: Nothing OUT: AL = API version number Example: call os_get_api_version ; AL now contains version number (eg 8) os_pause Delay execution for specified 10ths of second IN: AX = number of 10ths of second to wait OUT: nothing Example: ; Halt execution for 3 secs mov ax, 30 call os_pause os_fatal_error Display error message and halt execution IN: AX = error message string location OUT: nothing Example: mov ax, .error_msg call os_fatal_error .error_msg db 'Massive error!', 0 Ports os_port_byte_out Sends a byte to the specified port IN: DX = port address, AL = byte OUT: Nothing os_port_byte_in Retrieves a byte from the specified port IN: DX = port address OUT: AL = byte os_serial_port_enable Turn on the first serial port IN: AX = 0 for normal mode (9600 baud), or 1 for slow mode (1200 baud) OUT: AH = bit 7 clear on success os_send_via_serial Send a byte via the serial port IN: AL = byte to send via serial OUT: AH = bit 7 clear on success Example: mov al, 'a' ; Place char to transmit in AL call os_send_via_serial cmp ah, 128 ; If bit 7 is set, there's an error jnz all_ok ; Otherwise it's all OK jmp oops_error ; Deal with the error os_get_via_serial Get a byte from the serial port IN: nothing OUT: AL = byte that was received; OUT: AH = bit 7 clear on success Example: call os_get_via_serial cmp ah, 128 ; If bit 7 is set, there's an error. jnz all_ok ; Otherwise it's all OK jmp oops_error ; Deal with the error all_ok: mov [rx_byte], al ; Store byte we retrieved Screen os_print_string Displays text IN: SI = message location (zero-terminated string) OUT: Nothing (registers preserved) Example: mov si, .message call os_print_string ... .message db 'Hello, world', 0 os_clear_screen Clears the screen to background IN/OUT: Nothing (registers preserved) os_move_cursor Moves cursor in text mode IN: DH, DL = row, column OUT: Nothing (registers preserved) Example: ; Move to middle of screen mov dh, 12 mov dl, 40 call os_move_cursor os_get_cursor_pos Return position of text cursor OUT: DH, DL = row, column os_print_horiz_line Draw a horizontal line on the screen IN: AX = line type (1 for double, otherwise single) OUT: Nothing (registers preserved) os_show_cursor Turns on cursor in text mode IN/OUT: Nothing os_hide_cursor Turns off cursor in text mode IN/OUT: Nothing os_draw_block Render block of specified colour IN: BL/DL/DH/SI/DI = colour/start X pos/start Y pos/width/finish Y pos OUT: Nothing Example: mov bl, 0100111b ; White on red mov dl, 20 ; Start X position mov dh, 2 ; Start Y position mov si, 40 ; Width mov di, 23 ; Finish Y position call os_draw_block os_file_selector Show a file selection dialog IN: Nothing OUT: AX = location of filename string (or carry set if Esc pressed) Example: call os_file_selector jc .esc_pressed ; Now AX points to the chosen filename ... .esc_pressed: ... os_list_dialog Show a dialog with a list of options IN: AX = comma-separated list of strings to show (zero-terminated), BX = first help string, CX = second help string OUT: AX = number (starts from 1) of entry selected carry set if Esc pressed Example: mov ax, .list mov bx, .msg1 mov cx, .msg2 call os_list_dialog jc .esc_pressed ; Now AX = number (from 1) of option chosen ... .esc_pressed: ... .list db 'Open,Close,Reboot', 0 .msg1 db 'Choose an option', 0 .msg2 db 'Or press Esc to quit', 0 os_draw_background Clear screen with white top and bottom bars, containing text, and a coloured middle section IN: AX/BX = top/bottom string locations, CX = colour OUT: Nothing Example: mov ax, .title_msg mov bx, .footer_msg mov cx, 00100000b ; Colour call os_draw_background ... .title_msg db 'File manager', 0 .footer_msg db 'Choose an option...', 0 os_print_newline Reset cursor to start of next line IN/OUT: Nothing (registers preserved) os_dump_registers Displays register contents in hex on the screen IN/OUT: AX/BX/CX/DX = registers to show os_input_dialog Get text string from user via a dialog box IN: AX = string location, BX = message to show OUT: AX = string location Example: mov bx, .filename_msg mov ax, .filename_input call os_input_dialog ... .filename_msg 'Please enter a filename:', 0 .filename_input times 12 db 0 os_dialog_box Print dialog box in middle of screen, with button(s) IN: AX, BX, CX = string locations (set registers to 0 for no display), DX = 0 for single 'OK' dialog, 1 for two-button 'OK' and 'Cancel' OUT: If two-button mode, AX = 0 for OK and 1 for cancel NOTE: Each string is limited to 40 characters Example: mov ax, .string1 mov bx, .string1 mov cx, .string1 mov dx, 1 call os_dialog_box cmp ax, 1 je .first_option_chosen ; Otherwise second was chosen ... .first_option_chosen: ... .string1 db 'Welcome to my program!', 0 .string2 db 'Please choose to destroy the world,', 0 .string3 db 'or play with fluffy kittens.', 0 os_print_space Print a space to the screen IN/OUT: nothing os_dump_string Dump string as hex bytes and printable characters IN: SI = points to string to dump OUT: Nothing os_print_digit Displays contents of AX as a single digit (works up to base 37, ie digits 0-Z) IN: AX = "digit" to format and print OUT: Nothing os_print_1hex Displays low nibble of AL in hex format IN: AL = number to format and print OUT: Nothing os_print_2hex Displays AL in hex format IN: AL = number to format and print OUT: Nothing os_print_4hex Displays AX in hex format IN: AX = number to format and print OUT: Nothing os_input_string Take string from keyboard entry IN/OUT: AX = location of string, other regs preserved (Location will contain up to 255 characters, zero-terminated) Example: mov ax, .string call os_input_string ... .string times 256 db 0 String os_string_length Return length of a string IN: AX = string location OUT AX = length (other regs preserved) Example: jmp Get_Len Test_String db 'This string has 46 characters including spaces', 0 Get_Len: mov ax, Test_String call os_string_length ; AX now contains the number 46 os_find_char_in_string Get the position of a character in a string IN: SI = string location, AL = character to find OUT: AX = location in string, or 0 if char not present Example: jmp Search_Str Test_String db 'This is the test string', 0 message_1 db 'Character not found', 0 message_2 db 'Character found at position', 0 message_3 db ' ', 0 str_len dw 0 Search_Str: mov ax, Test_String ; string to search mov si, ax xor ax, ax ; clear ax mov al, 'x' ; x is the character to find call os_find_char_in_string mov [str_len], ax ; store result cmp ax, 0 jz Char_Not_Found jmp Char_Found Char_Not_Found: mov si, message_1 call os_print_string jmp Main_Pgm Char_Found: mov ax, [str_len] ; convert result into string first mov bx, message_3 call os_int_to_string mov si, message_2 call os_print_string ; print message_2 call os_print_space ; print a space mov si, message_3 call os_print_string ; print the position at which x was found os_string_reverse Swar order of characters in a string IN: SI = location of zero-terminated string Example: mov si, mystring call os_string_reverse ; Now mystring contains 'olleH' mystring db 'Hello', 0 os_string_charchange Change instances of character in a string IN: SI = string location, AL = char to find, BL = char to replace with os_string_uppercase Convert zero-terminated string to upper case IN/OUT: AX = string location os_string_lowercase Convert zero-terminated string to lower case IN/OUT: AX = string location os_string_copy Copy one string into another IN/OUT: SI = source, DI = destination (programmer ensure sufficient room) Example: mov si, .old_string mov di, .new_string call os_string_copy ... .old_string db 'Hello', 0 .new_string times 16 db 0 os_string_truncate Chop string down to specified number of characters IN: SI = string location, AX = number of characters OUT: string modified, registers preserved Example: mov si, .string mov ax, 3 call os_string_truncate ; .string now contains 'HEL', 0 .string db 'HELLO', 0 os_string_join Join two strings into a third string IN/OUT: AX = string one, BX = string two, CX = destination string Example: mov ax, .string1 mov bx, .string2 mov cx, .string3 ; CX now points to 'HELLOYOU', 0 .string1 db 'HELLO', 0 .string2 db 'YOU', 0 .string3 times 50 db 0 os_string_chomp Strip leading and trailing spaces from a string IN: AX = string location OUT: nothing Example: mov ax, .string call os_string_chomp ; AX now points to 'KITTEN', 0 .string db ' KITTEN ', 0 os_string_strip Removes specified character from a string IN: SI = string location, AL = character to remove OUT: nothing Example: mov si, .string mov al, 'U' call os_string_strip ; .string now contains 'MOSE', 0 .string db 'MOUSE', 0 os_string_compare See if two strings match IN: SI = string one, DI = string two OUT: carry set if same, clear if different Example: mov si, .string1 mov di, .string2 call os_string_compare jc .same ; Strings are different ... .same: ; Strings are the same .string1 db 'ONE', 0 .string2 db 'TWO', 0 os_string_strincmp See if two strings match up to set number of chars IN: SI = string one, DI = string two, CL = chars to check OUT: carry set if same, clear if different Example: like above, but with CL = number of characters to check os_string_parse Take string (eg "run foo bar baz") and return pointers to zero-terminated strings (eg AX = "run", BX = "foo" etc.) IN: SI = string OUT: AX, BX, CX, DX = individual strings Example: mov si, .string call os_string_parse ; Now AX points to 'This', ; BX to 'is', ; CX to 'a', ; and DX to 'test' .string db 'This is a test', 0 os_string_to_int Convert decimal string to integer value IN: SI = string location (max 5 chars, up to '65536') OUT: AX = number Example: mov si, .string call os_string_to_int ; Now AX contains the number 1234 .string db '1234', 0 os_int_to_string Convert unsigned value in AX to string IN: AX = unsigned integer OUT: AX = location of internal string buffer with result Example: mov ax, 1234 call os_int_to_string ; Now AX points to '1234', 0 os_sint_to_string Convert signed value in AX to string IN: AX = signed integer OUT: AX = location of internal string buffer with result Example: mov ax, -1234 call os_int_to_string ; Now AX points to '-1234', 0 os_long_int_to_string Convert value in DX:AX to string IN: DX:AX = long unsigned integer, BX = number base, DI = string location OUT: DI = location of converted string os_set_time_fmt Set time reporting format (eg '10:25 AM' or '2300 hours') IN: AL = format flag, 0 = 12-hr format OUT: nothing os_get_time_string Get current time in a string (eg '10:25') IN/OUT: BX = string location os_set_date_fmt Set date reporting format (M/D/Y, D/M/Y or Y/M/D - 0, 1, 2) IN: AX = format flag, 0-2 If AX bit 7 = 1 = use name for months If AX bit 7 = 0, high byte = separator character OUT: nothing os_get_date_string Get current date in a string (eg '12/31/2007') IN/OUT: BX = string location 聲音 os_speaker_tone Generate PC speaker tone (call os_speaker_off to turn off) IN: AX = note frequency OUT: Nothing (registers preserved) Example: see code below os_speaker_off Turn off PC speaker IN/OUT: Nothing (registers preserved) Example: ; Generate "middle C" 261.626 Hz (263 Hz close enough) for 2 secs ; 2 secs = 2,000,000 uS which is 1E8480h jmp Play_It music_note dw 263 Play_It: mov ax, [music_note] call os_speaker_tone mov cx, 1Eh mov dx, 8480h call os_pause call os_speaker_off BASIC os_run_basic 在指定點執行核心BASIC解譯器 IN: AX = lBASIC碼的位置, BX = 碼的大小 (以位元組計) 幫助 假如你有任何關於MikeOS的問題,或你要開發類似的系統且想要分享程式碼和想法, 可前往MikeOS網站,並加入到信箱列表。你就可以寫信到 mikeos-developer@lists.berlios.de 來發表到列表。 授權 MikeOS是個開放原始碼,在BSD-like下授權釋出(可參考在MikeOS.zip檔案中的doc/LI CENSE.TXT)。它意指你可以為程式碼做任何事情,包括在你的專案中使用它, 你只須保留授權檔案。
2013年2月20日 星期三
MikeOS組譯程式開發者手冊
Labels:
OS
嗨,大家好!我是一位資訊人、畫畫人、科技人和行銷人。定位自己為網路觀察家,永遠保持好奇心與熱情,學習跨領域新事物,希望最終能成為一個全方位的人。喜歡探索新技術和創意,並將其應用於工作和生活中。也喜歡畫畫、旅行、閱讀和寫作。希望我的部落格可以為您帶來啟發和樂趣,並與您分享我的經驗和見解。謝謝您的訪問,期待與您交流!
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言