跳至內容

Aros/平臺/68k 支援/開發者/Exec

來自華夏公益教科書,為開放世界提供開放書籍
導航欄 Aros 華夏公益教科書
Aros 使用者
Aros 使用者文件
Aros 使用者常見問題解答
Aros 使用者應用程式
Aros 使用者 DOS Shell
Aros/使用者/AmigaLegacy
Aros 開發文件
Aros 開發者文件
從 AmigaOS/SDL 移植軟體
針對 Zune 初學者
Zune .MUI 類
針對 SDL 初學者
Aros 開發者構建系統
特定平臺
Aros x86 完整系統 HCL
Aros x86 音訊/影片支援
Aros x86 網路支援
Aros Intel AMD x86 安裝
Aros 儲存支援 IDE SATA 等
Aros Poseidon USB 支援
x86-64 支援
摩托羅拉 68k Amiga 支援
Linux 和 FreeBSD 支援
Windows Mingw 和 MacOSX 支援
Android 支援
Arm Raspberry Pi 支援
PPC Power Architecture
雜項
Aros 公共許可證

ArosBootStrap

[編輯 | 編輯原始碼]

如果我將地址從

  1. 主 ROM (0xf80000 - 0xffffff)

ROMLOC_rom := 0x0f80000 to 0x4FF80000 - 4FF8ffff

我是否需要告訴 arosbootstrap,還是它會遵循該指標?Arosbootstrap 與任何型別的外部地址重新對映不相容。該地址用於構建正常的 2x512K ROM 映像,arosbootstrap 使用可重定位的 ELF 映像。

請注意,ROM 會檢測到 arosbootstrap 模式,並自動使用 MMU(如果可用)將“ROM”重新對映到快速 RAM,如果 arosbootstrap 最初將其載入到晶片 RAM 中(如果可用快速 RAM 不相容,例如 Blizzard A1200 加速器的快速 RAM 有這個問題,因為它不是自動配置)。檢查日誌中的 MMU 訊息。

它顯然必須是 UBYTE m68060[0x12];我想 mc68060 在為 68060 編譯時與其他一些編譯器變數衝突。該聯合僅用於為最大的 FPU 堆疊幀(68882)保留空間,變數名並不重要。(也許用 fpu_?作為字首)

注意到 InternalLoadSeg_ELF 的一個奇怪的特性。

它對傳入的 BPTR 進行 Seek() 呼叫。現在,這本身並不奇怪,除了當 funcarray[] 對 Read 有一個覆蓋(見 workbench/c/AddDatatypes.c)它對記憶體中的資料結構而不是檔案進行操作時。

因為我也需要記憶體中的搜尋功能來將 GZIP 壓縮的 ELF 檔案載入到 RAM 中(別問),所以修改了 InternalLoadSeg 及其相關函式,使用第四個 funcarray 成員(覆蓋 Seek)來提供此功能。

PPC 維護者:請仔細檢查我對您檔案的工作,以及它們是否可以合併回 rom/dos/internalloadseg_elf.c

Exec/ShutdownA(SD_ACTION_POWEROFF) 是否為任何 Amiga 機器定義?如果是,我需要做些什麼才能讓該機器關機?在任何 Amiga 型號中都沒有軟電源硬體。

對於其他機器,使螢幕完全變黑的最快方法是什麼?(這可能是一個銅列表,對嗎?)。據我所知,每個圖形驅動程式都會安裝一個重置處理程式鉤子,該鉤子會使螢幕變黑。重置處理程式可能不會在 ShutdownA(SD_ACTION_POWEROFF) 上被呼叫,但也許應該。

開啟視窗似乎需要很多記憶體。AROS 是否為每個視窗分配了一個完整的點陣圖?還是我的開啟方式不對?有沒有一個神奇的 OpenWindow() 標籤說“沒有後備儲存”?只有智慧重新整理視窗應該使用額外的視窗點陣圖(至少在 AOS 上是這樣)。

事實證明,Deallocate() NULL 是問題所在。我已經提交了一個修復程式,使 NULL 的 Deallocte() 成為一個無操作。今晚我會恢復 UAEGfx 的更改。

參考列表

task->tc_Launch()、task->tc_Switch() 和 Exec/Exception() 應該在什麼特權模式下執行?

我想應該是使用者模式,但考慮到 core_Dispatch 可以從 Switch() 中呼叫,這意味著 tc_Launch() 可以在管理模式下執行嗎?

另一個重要的缺失部分似乎是 expansion.library 自動配置板處理(以及棘手的額外功能:如果檢測到快速 RAM,則將 exec/管理程式堆疊重新定位到快速 RAM)。這將比 Exec/Dispatch() 和 Exec/Supervisor() 實現更簡單!

但是,您可能需要檢視 exec/child* 系列呼叫,因為它們看起來以一種奇怪的方式進行型別轉換,例如

child = FindChild((ULONG)tid);

我不知道這對 x86_64 是否安全,我不知道您的 tid 實現。

一個典型的 68k 彙編編碼的 PutChProc 函式執行

  move.b d0,(A3)+
  rts

A3 = PutChData(通常是字串緩衝區),並且該函式依賴於獲得修改後的 A3(指向要插入的下一個位元組/字元),下次呼叫 PutChProc 時。

例如:“Hello”,A3 = 0x100000

call PutChProc("H", 0x100000)
call PutChProc("e", 0x100001)
call PutChProc("l", 0x100002)
call PutChProc("l", 0x100003)
call PutChProc("o", 0x100004)

所以 A3 基本上是一個輸入+輸出引數,而不僅僅是輸入引數。

您也可以嘗試在真實的自動配置快速 RAM 中(在 ConfigChain() 呼叫之後)獲得 exec(如果您還有太多空閒時間)。您是在談論移動“啟動任務”堆疊,還是將整個 Exec 從 ROM 移動到 RAM?不,我的意思是隻有 execbase。官方的 2.0+ ROM 會將 execbase 移動到真實的自動配置快速(而不是 0xc00000 慢速 RAM)RAM,如果它存在。這樣做是因為晶片 RAM 和“慢速 RAM”(實際上與晶片 RAM 具有完全相同的速度)在真正的 Amiga 上相對較慢。這很容易做到。我將其新增為一個架構函式到 rom/expansion 或 rom/strap 中。

關於動態重定位

我試圖將可重定位的 1M ROM 映像載入到可用快速 RAM 的末尾。從技術上講,它已經可以工作,但是對於在重置過程中消失的自動配置 RAM 板存在問題。(UAE Z3 板不會,至少在 WinUAE 中不會,A3000/A4000 主機板 RAM 也是“安全的”)

1: 讓原始 KS(位於 ROM 中)執行自動配置操作,並新增 coolcapture/kicktag hack,將 ConfigDevs 複製到 AROS 擴充套件列表中。- Aros 自動配置實現未使用。這不會幫助我們發現任何錯誤。- KS 擴充套件行為可能具有無法記錄的功能,這些功能可能會破壞複製階段。

2: 將 coldcapture/kicktag 放置到晶片 RAM,它指向 AROS expansion.library(也位於晶片 RAM 中)。它首先執行自動配置(啟用“rom”所在的 RAM 板),將資料儲存在晶片 RAM 中,跳到 AROS ROM,AROS ROM 會檢測到這種情況,並且只收集自動配置資料,而不會再次執行自動配置。- 是否可以擁有一個單獨的可重定位檔案,其中只包含 expansion.library?(Jason?)- 無法使用任何 exec 例程,需要一些修補。(只使用絕對晶片 RAM 地址,沒有人關心,它們是臨時的)(是的,我知道晶片 RAM 在執行重置時也會被 ROM 暫時替換,但這一點可以解決,即使在沒有崩潰的 68000 上也是如此。甚至有一個遊戲將此用作複製保護的一部分)。

3: 只複製當前的自動配置資料,然後跳到 RAM 中的 ROM 映像,而無需重置。只工作一次(任何重置都會破壞它),任何引導 ROM 板對 AROS ROM 都是不可見的。對我來說太愚蠢了 :)

選項 2 並不容易,但它將與所有 Amiga 模型相容(只要它至少有 1M 的快速 RAM)。只要需要特定的硬體或 EPROM 燒錄器,對“普通”使用者來說測試就太難了。(不幸的是,您必須對所有板進行自動配置,您無法選擇特定的 RAM 板,除非該 RAM 板是自動配置鏈中的第一個板,但我認為您不能假設這一點。)

WHDLoad 是如何做到的?我們可以生成 WHDLoad 可以使用的 ROM 映像/重定位對映嗎?它使用 .RTB 檔案,這些檔案也是某種重定位檔案(據我所知,它們最初由一些 ROM 映像載入器使用)。但就我個人而言,我更喜歡將所有內容放在單個檔案中,因為混用不同版本太容易了(也許甚至應該包含載入器,像“偽覆蓋”檔案一樣的 titanic 壓縮器很容易建立)。無論如何,在擁有可用的 expansion.library 自動配置 hack(+ Gayle IDE 驅動程式埠)之前,我並不太在意。

在 m68k-amiga Disable() 中刪除了 softint 檢查(r36842),並將所有處理移至 Cause(),因為 m68k Disable() 和 Enable() 應該儘可能短和快。使用 Paula 中斷時,softint 是“自動的”,因此無需在每次 Enable() 呼叫中檢查它們。(m68k-amiga 中斷處理可能應該完全使用匯編語言,如果這個東西要在 A500 上有用,它需要真正最佳化。但現在還為時過早。)

崩潰發生在呼叫 sprintf() 時。 sprintf() 不在 arosc.library 中嗎?當然,你可以始終用呼叫 RawDoFmt() 來替換它,並移除對 arosc.library 的依賴。我有點想對所有 workbench/c 都這樣做(移除對 arosc.library 的依賴)

AOS 3.1 iPrefs 實用程式會修補 RawDoFmt() 以進行本地化,並且不理解 AROS 的“魔術”常量

  • RAWFMTFUNC_STRING
  • RAWFMTFUNC_SERIAL
  • RAWFMTFUNC_COUNT
Would anyone mind if I made those 'magic constants' point to real m68k functions on AROS m68k, for better 3.1 support? It changes the magic constants for m68k to point to functions, but continues to support the 'NULL == RAWFMTFUNC_STRING' assumption of AOS 4.x and Morphos.

載入 locale.library,讓它修補 AROS 的 RawDoFmt,然後也修補它,使用一個包裝器將特殊程式碼正確地翻譯成真實函式。在退出 SetPatchAROS 之前,請記住在解除安裝 locale.library 之前取消修補 RawDoFmt。我更喜歡這種方式,而不是彈出視窗。它在 Exec/SetFunction 中會有點 hacky,但可行。

因此 WB locale.library SetFunction() 的 RawDoFmt(),然後需要非 AOS 擴充套件(RAWFMTFUNC_STRING 及其他)的 AROS 程式停止工作,對吧?擴充套件 RawDoFmt() 是個壞主意。RawDoFmt() 應該只做原始 Autodocs 中說明的事情,所有 AROS 程式都應該使用 VNewRawDoFmt()。解決方案:替換或新增包裝宏,用 VNewRawDoFmt() 包裝所有 AROS RawDoFmt() 呼叫。嗯,雖然這確實修復了 WB 在 AROS 上的問題,但它使得 AOS ROM 上的 AROS 使用者空間幾乎不可能(在 AOS exec.library 向量空間中沒有空間),除非 SetPatchAROS 重新定位並擴充套件 exec.library。在這種情況下,我最好做一個外部的“exec.library”來替換 AOS 的那個。

事實

  • AROS RawDoFmt() 接受“特殊”PutChFunc 向量 0、1 和 2
  • AOS RawDoFmt() 假設 PutChFunc 始終指向一個有效函式
  • AOS locale.library 使用 SetFunction() 將 Exec/RawDoFmt() 更新為具有 AOS PutChFunc 約定的一個
APTR realRawDoFmt;

AROS_UFP4(fixupRawDoFmt, blah, blah)
{
     If PutChProc is a magic vector, make it a real function.
     Call realRawDoFmt;
}
... Exec/SetFunction (AROS) ...

if (library_to_patch == SysBase && function_to_patch == LVO_RawDoFmt) {
     realRawDoFmt = vector_of_patch;
     vector_of_patch = fixupRawDoFmt;
}

Set library_to_patch -> function_to_patch = vector_of_patch

這實際上比我想到的要好,因為它不依賴於 locale.library,但任何試圖修補 RawDoFmt() 的東西都會得到它的包裝器。如果你不認為 hackish 修補 SetFunction() 本身。現在 AROS 的 locale.library 修補 RawDoFmt() 時會發生什麼?它也會經過魔法到真實函式轉換器的修正,這會在每次呼叫中新增 16 個 m68k 指令。我們將把 rom/exec/setfunction.c 中的所有與 m68k 相關的程式碼移動到 arch/m68k-all/exec/setfunction.c 中,這樣它實際上將成為其他體系結構的“清理”。這些 AOS 相容性 hack 應該明確標記還是放在一些 ifdefs 中?(它們應該易於查詢,否則有人遲早會忘記它們,這會變得非常混亂。)在 arch/m68k-all/exec/setfunction.c 中新增廣泛的註釋

我唯一能想到的問題

  • 有人試圖替換 RawDoFmt 會移除鏈,並在他的替換中獲得未轉換的值。
  • 碰巧將 RawDoFmt 連結到捕獲完全相同的值的人必須實際接收它們

但是從呼叫來看,我們無法區分鏈和替換,因此我們如何知道是否必須向該修補程式新增轉換器修補程式呢?

這是一個非常小的問題,因此取決於我們想要保證完全相容性,還是僅僅一個好的近似值。

此外,我認為沒有取消修補。我不確定這是否會造成明顯的問題。

但如果 VNewRawDoFmt 使用了這些常量,它是否必須與它們進行檢查?為了比較,它們實際上是靜態函式指標並不重要。並且由於是符號化的,比較是識別它們的唯一允許的操作。

由於 AOS 沒有擴充套件的任務結構,因此此程式碼將 acpd 設定為 NULL->iet_acpd。修復 arosc 不要使用任務結構中的私有欄位。你可以使用 AVL 樹進行關聯(OS3.5+)。或者在 arosc 中靜態地複製這些函式。還請記住,arosc.library 依賴於一些其他 AROS 擴充套件,例如 NewAddTask() 和 NewStackSwap()。

ACPI。核心/exec 初始化很棘手,可能無法一次完成。Exec 已經被初始化了兩次(甚至三次,如果我們計算核心.resource 的獲取)。核心.resource 應該在優先順序 127 初始化,因為將來即使 AllocMem() 也將無法在沒有它的情況下工作(它將在核心的頁面分配器之上工作)。

SAD 除錯

[編輯 | 編輯原始碼]

用於在 PrepareExecBase 之前進行除錯。為此,你擁有 kernel_debug.h 中的 bug() 宏。在核心.resource 中進行非常早期的除錯時,你可以使用核心自己的 bug() 定義,它靜態地呼叫 KrnBug()。它不以任何方式使用 exec。並且 exec 的設施在呼叫 exec 的 init 程式碼後啟動並執行,這會填充 KernelBase。請注意,除了核心.resource 的啟動程式碼外,沒有其他程式碼可以在 PrepareExecBase() 之前執行。還要記住 KrnPutChar() 和內部 krnPutC()。

我如何早早啟用 SAD?我目前有一個(許可證很糟糕的)m68k-gdbstub,我正在使用它為我的 ROM 提供除錯,當我提交時必須刪除它。在你的核心.resource 中實現 KrnPutChar() 和 KrnMayGetChar(),它就可以工作。請注意,Alert() 不會呼叫它,因為當前的警報例程非常基本,不會處理任何輸入。這是因為 PC 上沒有通用的輸入硬體。事實上,這需要改進。也許警報需要接管螢幕,在上面列印資訊,然後接管輸入,並從它那裡請求一些命令。RFC,我寫了關於除錯通道的文章,是實現這種機制的一小步。

供列表審查。此修補程式啟用“--with-paranoia”./configure 選項,並在 rom/exec 中提供一個使用示例。

語義

./configure => 沒有 paranoia ./configure—with-paranoia => PARANOIA_CFLAGS=-Wall -W -Werror ./configure—with-paranoia=-Wmega => PARANOIA_CFLAGS=-Wmega

這允許(a)構建過程沒有變化,(b)開發者*為他們自己*啟用 paranoia,以及(c)開發者*僅*在他們認為乾淨的目標上啟用 paranoia。這樣,一旦庫中所有的 -Wall 問題都被清除,它就會保持這種狀態。

人們使用不同的編譯器版本(*),這些版本報告不同的警告——例如,現在 4.4 系列在沒有除錯的情況下編譯時會報告大量嚴格別名問題。我們可能會最終陷入這樣一種情況,即某個模組為 10 個人中的 9 個人構建,但不幸的 1 個人無法或不願意進行修復。

雖然同意 -Wall 中的一些警告。其中一些可能是錯誤的(例如,“變數 x 可能沒有初始化”),或者試圖強制執行特定的編碼風格(例如,“考慮在用作真值的賦值周圍使用括號”)。

我們的目標是避免使用 -fno-strict-aliasing 來提高效能。

我認為 USER_CFLAGS 在 mmakefile 中被過度使用;IMO 它應該只在某些符號需要定義等特殊情況下使用。大多數程式/庫應該使用 configure 生成的預設 CFLAGS 進行編譯。

BRA := "\("
KET := "\)"

TST := "test$(BRA)test$(KET) test"

USER_CFLAGS := -DDEFINE=\"$(TST)\"

或者

USER_CFLAGS := -DDEFINE=\"test\(test\)\ test\"

最後一個括號後面的反斜槓真的有必要嗎?我認為它只在需要指定後續字元為特殊情況時才需要?是的,它需要轉義空格並將整個內容作為一個命令列引數。

此外,你不需要複製除錯函式。還有一個關於 GDB 樁的問題。也許你應該考慮將它整合到現有的 SAD 中?能夠使用 gdb 遠端除錯任何機器將非常棒。不幸的是,gdb 樁非常特定於機器。我相信它們需要為每個埠重寫。我計劃在 SAD 工作後移除 GDB 樁。

不幸的是,gdb 樁非常特定於機器。我相信它們需要為每個埠重寫。我計劃在 SAD 工作後移除 GDB 樁。好吧,SAD 確實需要改造了。它是一個非常古老的東西。

此訊息主要針對 Jason 和 Toni。如果你檢視 arch/all-<cpu>/include/aros/<cpu>/cpucontext.h,我已經為除 m68k 之外的所有體系結構編寫了 CPU 上下文定義。指向此類結構的指標將在兩個地方使用

  • 它作為第三個引數傳遞給核心異常處理程式(使用 KrnAddExceptionHandler() 新增)。
  • 它作為第二個引數傳遞給 exec 陷阱處理程式(tc_TrapCode)。

這主要目的是統一和擴充套件崩潰處理程式碼,併為第三方開發者提供編寫除錯工具的可能性,這些工具可以捕獲異常並分析任務狀態。PowerPC 上下文與 AmigaOS4 相容。我希望 m68k 上下文與 m68k AmigaOS 相容。我知道在 m68k 上

tc_TrapCode  gets the whole context frame on the stack, this should be the  only  difference  to  other  ports.  I. e. on m68k we should take context pointer as follows:
void MyTrapHandler(ULONG trapCode)
{
     struct   ExceptionContext   *regs   =   (struct  ExceptionContext *)(&trapCode + 1);

     ... process exception here ...
}

你還需要編寫特定於 m68k 的 cpu_init.c、KrnCreateContext() 和 PrepareContext()。請參考其他體系結構的示例。

簡要說明

  • kb_ContextSize 需要設定為上下文的總大小。
  • kb_ContextFlags 可以用於任何你想要的目的。i386 和 ARM 使用它來指定 FPU 型別。也許你根本不需要它,因為在 m68k 上你擁有 SysBase->AttnFlags。這兩個變數由 cpu_init.c 設定,它執行啟動時 CPU 探測。

KrnCreateContext() 分配上下文幀並設定一些初始資料(如果需要)。常見用途是建立初始 FPU 幀。CPU 上下文的公共部分應該是 sizeof(struct AROSCPUContext)。這是託管埠所必需的,因為在託管上,你需要將一些特定於主機的私有資料儲存為 CPU 上下文的一部分。如果你檢視託管 CPU 定義,你將在 struct AROSCPUContext 的開頭看到 struct ExceptionContext。在本地,你只需

#define AROSCPUContext ExceptionContext

可選資料(如 FPU 上下文)跟隨同一個塊中的 struct AROSCPUContext。

PrepareContext() 沒有改變,我只是擴充套件了所有宏。由於上下文是統一的,你不再需要為每個埠定義相同的宏。

kernel_cpu.h 中唯一仍然需要的舊宏是 GET_PC 和 SET_PC。它們由 exec 的崩潰處理程式使用。它們將在一段時間後消失。PRINT_CPU_CONTEXT 事實上列印了無用的內容,所以你可以安全地移除它。Debug() 將在沒有它的情況下工作。

應該記住,BPTR 在(所有?)其他埠上並不真正存在。

> struct ExceptionContext

這是 AROS 側上下文的公共形式。這是 AROS 異常處理程式期望獲取的內容。在使用相同 CPU 的所有架構上,它都是相同的。

> regs_t

這是 CPU 生成的原始堆疊幀。在託管 AROS 中,它是主機作業系統上下文結構的別名。在本地,它可能與 ExceptionContext 相同。

> struct AROSCPUContext

ExceptionContext + 私有部分。在託管環境中(您儲存主機特定的內容)是有意義的。在本地,它應該與 ExceptionContext 相同。struct AROSCPUContext 在開頭包含 struct ExceptionContext。

> ucontext

上下文的 UNIX 名稱。regs_t 是它在 UNIX 託管環境中的別名。

> 我試圖讓 m68k 與所有其他架構相似,但陷阱/異常區域發生了很多變化,並且文件太少了(或者至少我不知道文件在哪裡)。

這是一個新設計的東西。我在原始碼中提供了一些註釋,我希望這足夠了。對不起,我現在時間不多,甚至不能積極地閱讀郵件列表。所做工作的核心思想是統一每個 CPU 的 CPU 上下文格式。因此,struct ExceptionContext 在同一個 CPU 上是相同的,無論它是託管系統還是本地系統。是的,我研究過 AmigaOS exec 陷阱處理,我知道這個怪癖。我建議使用 asm 存根。我在程式碼中註釋了這一點。

請在您的評論中放置指示器 FIXME 或 TODO,以表示需要稍後注意的事項。這使得稍後更容易找到它並且不會忘記它。例如

    /* fetch Task pointer before function call because A6 can change inside initialPC
     * (FIXME: temporary hack) */

新增 MoveExecBase(),以便 m68k-amiga 埠可以使用它將 exec 從晶片/慢速 RAM 移動到自動配置快速 RAM。出於好奇:這在 WinUAE 上會帶來任何改進,還是針對實際硬體?在實際硬體中,execbase 或任何其他通常訪問的晶片 RAM(或“慢速”RAM)中的系統結構會導致明顯的減速,尤其是在加速的 OCS/ECS Amiga 上。

16 位 OCS/ECS 晶片 RAM 與加速器 32 位快速 RAM 之間的速度差異可能很大,而且晶片 RAM 也不可快取。

KS 2.0 是第一個正式的 ROM,引入了將 exec 傳輸到快速 RAM 的功能。

(如果我們想要工作重置證明程式,這將變得非常棘手)

排程程式

[edit | edit source]

您需要使用現有的 kernel.resource。它已經具有完整的排程程式,您只需要編寫特定於 CPU 的程式碼,就可以完成。檢視 rom/kernel/kernel_schedule.c 中的 core_* 程式碼。

請注意,將來可能會出現更好的排程程式(請記住 KrnSetScheduler() 函式)。另一個注意:啟動程式碼(start.c)在引導目錄中,恕我直言,最好位於核心目錄中,因為它實際上是 kernel.resource 的一部分。

檢視 Windows 託管和 UNIX 託管埠。它們是最新的,它們是使用最新模型設計的。x86-64 和 PPC 埠只是比較舊,它們沒有使用公共程式碼,但它們是我的實現的基礎。我只是沒有重寫它們,因為我沒有這些機器並且無法測試。實際上,引導目錄包含一個外部載入程式,它應該將 kickstart 映像載入到機器的 RAM 中並執行它。在 Amiga 上,kickstart 位於 ROM 中,它不需要任何引導載入程式(好吧,如果你不重新重新整理 ROM 而是以程式設計方式重新啟動 Amiga,它可能有一個引導載入程式,在這種情況下,kickstart 交換器將是你的載入程式)。

當我完成 kernel.resource 重寫時,我寫了它。它在某些地方仍然不完整,並且缺少移植 HOWTO。

確保任務切換僅在從監督模式返回使用者模式時完成,而不在從監督模式返回監督模式(中斷內部中斷)時完成。很久以前,x86 本地也有類似的消失任務問題,這是由 exitintr 處理中錯誤的“我們是否返回使用者模式”檢查引起的。arch/m68k-amiga/kernel/amiga_irq.c 中的程式碼僅在返回使用者模式時呼叫 core_ExitInterrupt()。當然,我可能是錯的。我很樂意讓第二個人看看我的 arch exec 和核心程式碼,現在我已經更接近標準約定。系統呼叫在 amiga_irq.c 中處理(透過 F-Line 陷阱),並且僅針對使用者模式,所有其他中斷要麼陷阱到偵錯程式,要麼(對於 Paula 中斷)透過 amiga_irq.c 中的 Paula 處理程式。

在慢速處理器下,它更明顯,任務切換必須儘可能快。它與排程程式無關,問題是處理程式程序優先順序太低。太低的優先順序 dos 資料包處理程式和某個人使用所有 CPU 時間 = 控制檯和檔案系統 io 爬行。您可以在 AOS 上輕鬆確認它,方法是將所有處理程式程序的優先順序更改為零或更低 : )

Sysbase

[edit | edit source]

在 expansion.library 和 scsi.device 中,似乎存在專門製作的 16 位非法指令,'原始' Exec 會查詢這些指令併為捕獲它們後適當地設定 D0。是否有任何地方有這些'非法指令'陷阱的文件?您必須使用 Amiga Forever 3.x ROM(s),它們至少有一條特殊的非法指令,使其與真實的 Amiga 不相容(UAE 有一個 rom 檢查駭客修復了這個問題)。據我所知,它是許可證的一部分,rom 映象不能在真實的 Amiga 上使用。確保您擁有真正的原始 kickstart rom 映象。

解決方案是確保當您擁有'SysBase'時,它是全域性的,而不是本地副本。

SysBase = PrepareExecBase(...)

一個小問題:你為什麼認為 PrepareExecBase() 不應該設定全域性 SysBase?我記得有一次我也想出了這樣的想法,只是因為我認為它看起來不好。改變之後,我意識到自己錯了多少。許多意想不到的地方可能依賴於全域性 SysBase。我記得我在某個地方有早期的除錯輸出,這破壞了它。也許那個輸出甚至都不存在了,但這證明了這個想法很糟糕。全域性 SysBase 應該儘早設定。這意味著 - 在 PrepareAROSS 之前。被 PrepareExecBase() 如何返回 SysBase 所誤導,以及它所有的呼叫者都將它用作'SysBase = PrepareExecBase()'。它看起來就像 PrepareExecBase() 缺少一個本地'struct ExecBase *SysBase'的錯別字。也許 PrepareExecBase() 應該返回 void,以便它的呼叫者必須 *顯式* 獲取全域性 SysBase?

此外,goUser() 是否應該始終降級到使用者特權,或者恢復 goSuper() 之前存在的特權?它切換到使用者模式。還有 goBack() 定義,它跳轉到 goSuper() 記住的先前模式。

最後一點 - 任務->tc_Launch()、任務->tc_Switch()、Launch 和 Switch 回撥是在監督程式內部直接呼叫的,我相信這是可以的,我認為原始的 Amiga 也這樣做。無論如何,您不會在這些回撥中執行長時間執行的操作。

以及 Exec/Exception() 應該在什麼特權模式下執行?Exception()(與 AmigaOS 不同)是在完成所有特定於架構的準備工作後呼叫的,您處於任務上下文中的使用者模式。此程式碼只檢查訊號並呼叫相應的例程,它不包含任何特定於架構的程式碼。

為了正確處理異常,您需要將任務的上下文(cpu_Dispatch() 將要跳轉到的上下文)儲存到某個地方,然後調整上下文,以便您的任務跳轉到異常處理程式。處理程式應該呼叫 exec 的 Exception(),然後它應該獲取原始任務的上下文(您在 cpu_Dispatch() 中儲存的上下文),並跳轉到它。

結果看起來就像您的任務只是呼叫了它的異常處理程式。您可以檢視 Windows 託管實現,這是一個工作示例。UNIX 託管實現不起作用(至少在 PPC 上不起作用)。在本地埠上,異常也不起作用。請注意,在 m68k-native 上,您 100% 知道您的堆疊上發生了什麼,因此您不需要使用將上下文傳遞給異常處理程式的技巧。您可以將其直接儲存到任務的堆疊上(這是 UNIX 託管版本所做的,也是它不起作用的原因)。

中斷

[edit | edit source]

在我的最後一次更改中(我記得在進入 cpu_Dispatch() 中的 CPU 空閒狀態之前重新啟用硬體中斷),我似乎能夠進入 KickStart 1.3 Intuition 空閒迴圈。

但是,我似乎遺漏了一些東西,因為(除了一個漂亮的白色螢幕)我什麼也沒得到。

我認為我需要呼叫 KS 的“strap”或“romboot.library”,或者 AROS 的“dosboot.library”,但我不知道應該從哪裡呼叫它們。FWIW,AROS 的 strap 是由於它位於駐留列表(優先順序 -50)中而呼叫的。請參閱 rom/boot/strap.c。

strap 模組在 dos 初始化之前在真實的 rom 中執行磁碟塊讀取,它似乎沒有很好的文件記錄。

訊號量

[edit | edit source]

我遇到了一些結構佈局問題,因為當我嘗試從 AROS exec 初始化 KickStart 3.0 庫時,我得到了 MH 免費列表的損壞。(奇怪的是,它們似乎初始化了很多。記憶體損壞發生在 expansion.library 中,在呼叫 Exec/InitSemaphore 之後,以及另一個似乎在 Intuition 呼叫 Graphics/Screen OpenScreen 時發生的損壞 - 可能都是相同的結構)> Amiga os 3.1 的一個很好的來源是 .i 包含檔案,它們是 AmigaOS 結構的位元組級佈局的良好參考?(即 SignalSemaphore 等)。

您的編譯器是否使用 WORD(2 位元組)對齊來處理 LONG 等,正如 AOS 所期望的那樣?如果不是,您可能需要像 AOS4/MOS 中那樣在標頭檔案中包含以下內容

#pragma pack(2)

[...]

#pragma pack()

NewAddTask 想要將堆疊對齊到 16 位元組。我已經在 AROS_FLAVOUR_BINCOMPAT 中關閉了它。例如,PPC 埠需要這種對齊方式。當然,其他埠可能不需要它。

我在 KS 3.1 上注意到,Exec/InitStructure 的一些呼叫者將大小欄位的第 16 位設定為 1。不知道為什麼。現在,我必須將其遮蔽掉(這將 InitStructure 限制為只能處理大小不超過 64k 的結構)。

這可能是函式的一個情況,其中原始函式只檢視低 16 位,即使庫原型對引數說的是 LONG 或 ULONG。因此,高 16 位可能包含垃圾,而其他一些程式碼可能依賴於此(== 在呼叫函式時實際上在高 16 位中包含垃圾)。

您也可以在其他地方看到這一點,例如 graphics.library。在某些函式中,我們使用

 x = (WORD)x

(FIX_GFXCOORD 宏)來清除高 16 位中的垃圾。

例如,如果原型是 LONG,預期值寬度是 WORD,傳遞的垃圾 < 0,那麼為什麼型別轉換應該足夠呢?

x = (WORD) (x & 0x0000FFFF)

確保您只獲得低 16 位?我在 x86(gcc 4)和 68k(gcc 2.95)上嘗試過,它在那裡起作用。

#include <stdio.h>
void func(int param)
{
    int fixed = (short)(param);
    printf("%d (%x) %d (%x)\n", param, param, fixed, fixed);
}
int main(void)
{
    func(0xF234fffe);
}

-231407618 (f234fffe) -2 (fffffffe)

你說得對——當從(無符號或有符號)長整型轉換為(無符號或有符號)短整型時,C 語言的規則似乎是保留低位字。我個人更喜歡“&”符號,因為它直觀地展示了操作過程,而不是需要記住編譯器根據某種隱含的約定所進行的操作。

請閱讀 這裡這裡這裡

記憶體

[編輯 | 編輯原始碼]

在修復 i386-pc exec 初始化的過程中,我再次遇到了 SysBase->MaxLocMem。AmigaOS 3.x NDK 將其描述為“最大晶片記憶體量”。如果是這樣,為什麼不能透過檢查 MemList 並將所有 MEMF_CHIP 記憶體大小相加來設定它?為什麼需要對地址進行一些神奇的處理?它的確切值是什麼?關於 MaxExtMem 也有同樣的問題。我想為所有平臺正確地實現它。

MaxLocMem 是晶片 RAM 的大小(等於 AOS 上晶片 RAM 的最後一個地址 + 1)

MaxExtMem 是“慢速”/“Ranger” RAM 的最後一個地址 + 1(不是大小!)(0x00C00000)。沒有慢速 RAM = NULL。它永遠不會包含任何其他本地 RAM 區域。

我認為這些設計並非為了支援多個記憶體區域。

文件(和原型檔案)說明返回值型別為 BYTE,但許多程式(包括 WB1.3 system/setmap)都假定返回值型別為 LONG。KS1.3 和 3.1 OpenDevice() 都會獲取 io_Error,然後將其擴充套件(EXT.W D0 + EXT.L D0)為 LONG,然後再返回。哪個是錯誤的,文件還是實現?(或者兩者都不是? :))

(m68k-amiga 埠已經有擴充套件 OpenDevice() 返回碼的駭客程式,但會被 dos lddemon 鉤子覆蓋)

在 rom/dos/endnotify.c 中

   /* get the device pointer and dir lock. The lock is only needed for
    * packet.handler, and has been stored by it during FSA_ADD_NOTIFY */
   iofs.IOFS.io_Device = (struct Device *) notify->nr_Handler;
   iofs.IOFS.io_Unit = (APTR)notify->nr_Reserved[0];

“iofs.IOFS.io_Unit”是一個指標,而 notify->nr_Reserved[0] 是 ULONG。

這個程式碼位置和 FSA_ADD_NOTIFY 需要處理 64 位指標。

目前沒有解決方法。

在 rom/dos/deviceproc.c 中

 
/* all good. get the lock and device */
   SetIoErr(dvp->dvp_Lock);
   res = dvp->dvp_Port;

問題是 dvp->dvp_Lock 是一個 BPTR,它不能(安全地)在 x86_64 下轉換為 LONG。由於他的函式被標記為已棄用,我認為它應該在 x86_64 下丟擲 ERROR_DEVICE_NOT_MOUNTED。我不確定這樣做是否可行,可能我們在整個程式碼庫中做了很多假設,才讓它變得簡單,但一種想法是將 BPTR 視為一個不透明的控制代碼:在 x86 上,它只是一個指標,出於速度考慮,而在其他不允許這種“最佳化”的架構上,它可能是一個指向某種字典的鍵(使用雜湊表、二叉樹或類似的東西實現)。

將 pr_Result2 更改為 SIPTR 會有什麼危害嗎?

這是我們位於 trunk/contrib/necessary/USB:classes/HID 類/MassStorage 棧/存根中的“舊”USB 棧(未使用)。當前棧位於 rom/poseidon 中。舊的棧用於 ppc-efika,雖然該埠目前無法使用。另一方面,我希望能在 sam 埠取得進展。

有沒有人知道 AmigaOS 上 input.device 的 IECLASS_TIMER 滴答率是多少?(Google 和 Autodocs 幫不上忙——它們只說 IECLASS_TIMER 是一個“定時器事件”,但沒有說明事件發生的頻率)。在 AROS 中,它被設定為每 100 毫秒一次。正確嗎?還是應該使用 VBlank 頻率?或者更慢?

Trackdisk.device

[編輯 | 編輯原始碼]

需要 MFM 解碼和一些簡單的硬體操作(Paula 和 CIA)。

對於 cia,骨架應該保留在 rom/cia 中,據我所知,你只需要將特定於 Amiga 的檔案新增到 arch/m68k-amiga/cia 中,並使用 %build_archspecific 宏來覆蓋初始檔案,使其特定於架構。

disk.resource GetUnit() 永遠不會啟用磁碟 DMA 完成中斷。它之所以“能用”,是因為序列傳輸和磁碟中斷使用相同的中斷級別。Trackdisk.device 負責啟用中斷。

如果我新增 arch/m68k-amiga/cia 目錄並將特定於 Amiga 的檔案放在那裡(例如 seticr.c 和 ableicr.c),就會出現錯誤。

目標是 amiga-m68k。

arch/m68k-amiga/cia/mmakefile.src 很簡單

include $(TOP)/config/make.cfg

FILES := seticr ableicr USER_CFLAGS := -I$(SRCDIR)/rom/cia

%build_archspecific \

 mainmmake=kernel-cia maindir=rom/cia arch=amiga-m68k \
 files=$(FILES) modulename=cia

trackdisk.device 應該位於... m68k-amiga/devs/

而 HIDD 應該位於... m68k-amiga/hidd/

另一方面,資源應該直接放在 m68k-amiga 中——我認為這映射了 AROS/rom 目錄的佈局。

“Retro”相關問題:我們應該如何配置 ROM 以實現“相容”模式/特定於型號的配置,例如未擴充套件的 A500?ROM 必須不要使用太多 RAM 進行高階操作(例如,trackdisk.device 必須不要為 HD 磁碟分配 DMA 緩衝區,15k 與 30k 在晶片 RAM 使用方面存在巨大差異。目前我動態地執行此操作,只有在插入 HD 磁碟時才會重新分配 HD 大小緩衝區,請注意,除非插入 HD 磁碟,否則 HD 磁碟會報告為 DD)。

今天並不太重要,但我希望能夠製作一個能夠啟動大多數 A500 遊戲和演示的免費 ROM :)(當然不可能完全相容,一些非常舊的遊戲會直接跳轉到 ROM...)

我還注意到(以前我不知道它有那麼糟糕)生成的 M68k 程式碼非常糟糕,效率低下,而且很長...(希望只是因為使用的選項?)

讀取驅動器 ID 的程式碼(來自我的 disk.resource 實現)

void readunitid_internal (struct DiscResource *DiskBase, LONG unitNum)
{
    volatile struct CIA *ciaa = (struct CIA*)0xbfe001;
    volatile struct CIA *ciab = (struct CIA*)0xbfd000;
    UBYTE unitmask = 8 << unitNum;
    ULONG id = 0;
    int i;

    ciab->ciaprb &= ~0x80; // MTR
    ciab->ciaprb &= ~unitmask; // SELx
    ciab->ciaprb |= unitmask; // SELX
    ciab->ciaprb |= 0x80; // MTR
    ciab->ciaprb &= ~unitmask; // SELx
    ciab->ciaprb |= unitmask; // SELX
    for (i = 0; i < 32; i++) {
        ciab->ciaprb &= ~unitmask; // SELx
        id <<= 1;
        if (!(ciaa->ciapra & 0x20)) // RDY
            id |= 1;
        ciab->ciaprb |= unitmask; // SELX
    }
    if (unitNum == 0 && HAVE_NO_DF0_DISK_ID && id == 0)
        id = 0xffffffff;
    DiskBase->dr_UnitID[unitNum] = id;
}

結果是:(開頭和結尾已刪除)

00FE8AB6 206f 0010                MOVEA.L (A7, $0010) == $0000ee78,A0
00FE8ABA 7208                     MOVE.L #$00000008,D1
00FE8ABC 2008                     MOVE.L A0,D0
00FE8ABE e1a9                     LSL.L D0,D1
00FE8AC0 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8AC6 0200 007f                AND.B #$7f,D0
00FE8ACA 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8AD0 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8AD6 1401                     MOVE.B D1,D2
00FE8AD8 4602                     NOT.B D2
00FE8ADA c002                     AND.B D2,D0
00FE8ADC 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8AE2 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8AE8 8001                     OR.B D1,D0
00FE8AEA 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8AF0 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8AF6 0000 ff80                OR.B #$80,D0
00FE8AFA 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8B00 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8B06 c002                     AND.B D2,D0
00FE8B08 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8B0E 1039 00bf d100           MOVE.B $00bfd100,D0
00FE8B14 8001                     OR.B D1,D0
00FE8B16 13c0 00bf d100           MOVE.B D0,$00bfd100
00FE8B1C 327c 0020                MOVEA.W #$0020,A1
00FE8B20 7000                     MOVE.L #$00000000,D0
00FE8B22 1639 00bf d100           MOVE.B $00bfd100,D3
00FE8B28 c602                     AND.B D2,D3
00FE8B2A 13c3 00bf d100           MOVE.B D3,$00bfd100
00FE8B30 d080                     ADD.L D0,D0
00FE8B32 1639 00bf e001           MOVE.B $00bfe001,D3
00FE8B38 0803 0005                BTST.L #$0005,D3
00FE8B3C 6604                     BNE.B #$00000004 == $00FE8B42
00FE8B3E 7601                     MOVE.L #$00000001,D3
00FE8B40 8083                     OR.L D3,D0
00FE8B42 1639 00bf d100           MOVE.B $00bfd100,D3
00FE8B48 8601                     OR.B D1,D3
00FE8B4A 13c3 00bf d100           MOVE.B D3,$00bfd100
00FE8B50 5389                     SUBA.L #$00000001,A1
00FE8B52 b2fc 0000                CMPA.W #$0000,A1
00FE8B56 66ca                     BNE.B #$ffffffca == $00FE8B22

沒有相對地址的 CIA 定址,移動到暫存器,執行操作,然後寫回... 無法更糟糕了。為什麼它會將地址暫存器用作計數器(subaq.l #1,a1; cmpa.w #0,a1?你使用了 volatile 關鍵字,因此對 ciaprb 的每次操作都會執行!)

考慮

    ciab->ciaprb &= ~0x80; // MTR
    ciab->ciaprb &= ~unitmask; // SELx

將替換為

    ciab->ciaprb &= ~(0x80 | unitmask); // MTR, SELx

生成的程式碼會更短... ;)

將“int i”更改為“UBYTE i”,因為你只從 0 計數到 31。否則,你會迫使 gcc 為你分配一個 32 位暫存器。

我的意思是,為什麼它沒有建立簡單而短的

and.b #$7f,$bfd100
and.b d0,$bfd100

(或者更好的是,將 bfd100 放在某個地址暫存器中,並執行 and.b #$7f,(a0))

許多資料暫存器完全沒有使用。volatile 關鍵字會強制生成完全無最佳化的程式碼嗎?:) 當然!它禁止任何過度最佳化,因為變數的狀態始終可能以無法預測的方式發生變化。使用 volatile 關鍵字描述的暫存器將被訪問的次數與你的程式碼建議的一樣多 :P

控制代碼

[編輯 | 編輯原始碼]

con-handler 將 Shell 的 I/O 指向 console.device,後者在視窗中繪製輸出,並從鍵盤讀取輸入。con-handler 用於開啟視窗並將視窗傳遞給 console.device,但現在 console.device 會執行此操作。con-handler 仍然處理名稱完成、命令歷史記錄等,但已發生了很大的改變。

console.device 開啟顯示器,讀取鍵盤,處理顯示歷史記錄,在一個視窗中處理多個控制檯(選項卡)、選單等。它已被重構,並在很大程度上被重寫。

我昨天成功地讓 dos 資料包正常工作(主要是啟動時需要的函式,如 open/lock、examine、getdeviceproc、assignlock)。Lock 和 Open 使用 FileLock 和 FileHandle 結構。

UAE FS 會啟動,直到第一個可執行檔案執行,CON 也需要儘快轉換。

但我釋出此帖子的原因是:NIL 控制代碼。

無法建立 NIL 控制代碼,因為 CreateProcess() 需要 NIL:而 NIL 需要 CreateProcess(),以此類推... 原始的 NIL“控制代碼”只不過是 Open() 檢查“NIL:”並返回 fh_Type 為 NULL(資料包埠)的 FileHandle。

問題是:這會導致其他端口出現問題嗎?如果是,如何解決?(是否需要某種特殊版本的 CreateProcess()?)Aminet 上有一個 NULL 控制代碼檔案系統,但我已經好幾年沒有看過它了。 http://aminet.net/package/util/batch/NULL-Handler 可能是一種選擇,因為它附帶原始碼。NULL: 和 NIL: 之間的區別在於 NIL: 是一個虛擬檔案系統,而 NULL: 檔案系統不是。

我們能不能直接刪除 NIL 控制代碼?這會造成相容性問題嗎?如果存在期望(可能是意外地)使用“完整”NIL 控制代碼(或 DosList 中列出的 NIL,作為 DLT_DEVICE)的特定於 AROS 的程式。實際上,這不是問題,如果需要,可以從 Dosboot 手動啟動真正的 NIL: 控制代碼(覆蓋偽 NIL)。

DOS 資料包轉換正在順利進行,UAE FS 現在可以啟動(並且速度更快,原因不明)。直到呼叫 Open(CON:) 時。下一個問題:控制檯控制代碼,在沒有看到螢幕上的任何內容的情況下,很難測試基於磁碟的命令。它看起來不像 NIL 控制代碼那樣簡單轉換(我之前轉換過,後來發現它不能使用)。我們是否在某個地方隱藏了更舊的、真正基於 dos 資料包的版本?沒有,console.handler 的第一個簽入(在 1998 年)使用了 FSA_* API。

diff --git a/arch/m68k-amiga/devs/filesys/console_handler/con_handler.c b/arch/m
index 2f0bc85..38c3bb9 100644
--- a/arch/m68k-amiga/devs/filesys/console_handler/con_handler.c
+++ b/arch/m68k-amiga/devs/filesys/console_handler/con_handler.c
@@ -297,10 +297,10 @@ static void startread(struct filehandle *fh)
 }
 
 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
-
-    /* SegList points here, must be long aligned */
-    __attribute__((aligned(4)))
-
+    /* We use the GCC trick of .balign, which
+     * will pad us with NOPs
+     */
+asm (" .text\n.balign  4\n");
 #endif
 
 LONG CONMain(void)

為什麼 Amiga 編譯器不會出現這個問題?僅僅是運氣,還是它們會自動將函式對齊到 4 位元組?如果是後者,也許我們應該在 68k 交叉編譯器中執行相同的操作。

這是一種非常糟糕的程式碼,它只是偶然起作用了... 文件中沒有說明輸入控制代碼有額外的暫存暫存器。我們是否只需要儲存 D2 和 D3,或者其他程式也會(非法地)修改其他非暫存暫存器?同樣糟糕的是 Titanics Cruncher 解壓縮器,它使用 A5 作為基址暫存器來呼叫 dos 函式,而 A6 指向 dosbase 之外的其他內容,它之所以能用(再次是偶然),是因為 dos 資料包可以在沒有 dosbase 的情況下發送... 我認為所有暫存器都需要儲存,但也許可以新增一個 GCC 編譯器命令,這樣在呼叫事件處理程式後,所有暫存器都將失效,因此後面的程式碼將不使用任何暫存器。

但當你檢視軟體中斷時,這裡的文件寫著“不要修改 a6”,而在中斷中寫著

“(D0/D1/A0/A1/A5/A6) 可以被中斷處理程式用作暫存暫存器”

當 Inputhandler 中沒有可用的暫存器時,我認為 AOS 中的程式碼是為所有暫存器都可以在 Inputhandler 中使用而編寫的。不要假設這種行為是允許的。請提供文件證明你的假設。由於 InputHandlers 在 input.device 中以 Interrupt 結構的形式進行鏈式連線,我認為與軟體中斷相同的規則也適用。

IMO 規則是,臨時暫存器是 D0-D1/A0-A1,除非文件另有說明,否則不要觸碰其他暫存器。不要只是想,修改你的測試程式來確認它(檢視哪些暫存器可以更改而不會導致 AOS 輸入處理程式崩潰,我相信至少有一個地址暫存器不能修改,否則會導致崩潰)。

或者,你可以看看為什麼螢幕切換器 awin 在 AROS 上無法工作。也許我錯了,但為了找出原因,一個儲存所有暫存器的 AROS 版本很有用。所有這些程式都會導致 AROS 崩潰。

http://aminet.net/package/util/wb/ScreenSwitch http://aminet.net/package/util/wb/awin

awin 是由 kas1e 編寫的,也許他知道可能出現的問題,也許商品處理程式也存在類似問題,它們不接受修改暫存器。

CON 的原始原因是:編譯器/autoinit/stdiowin.c,它總是將輸入和輸出流設定為 "CON://///AUTO/CLOSE"。這將強制開啟控制檯視窗,如果程式從 Input()/Output() 中讀取或寫入任何內容。

這是正確的。此行為是從 libnix 中複製的。我建議首先在 AmigaOS 上測試從該檔案讀取是否真的會開啟控制檯視窗。也許只有輸出會開啟它,而輸入不會。視窗不會立即開啟,而是在第一次訪問時開啟。

在編寫這篇文章時,我理解了它的起源。CreateNewProc() 會處理這個問題,但在從 Workbench 啟動時,程序的輸入/輸出都是 NIL:。啟動程式碼接管了這兩個,最終導致 Input() 不包含任何預注入的資料。

我建議在 AmigaOS 上測試以下順序

1. 使用這些引數開啟 CON:。 2. 嘗試讀取一些內容。 3. 嘗試寫入一些內容。 4. 嘗試再次讀取。

如果我的猜測正確,步驟 (2) 不會導致視窗開啟,只會返回 EOF。如果是這樣,我們的控制檯處理程式需要修復。這種情況最初沒有發生(=錯誤的行為),直到(我認為)一些與 dos 資料包相關的修復被移到主線上。它不是與資料包相關的,而是與 AmigaOS 如何處理程序的引數相關的。它將它們注入 Input() 中。

KS3.1

handle = Open("CON://///AUTO/CLOSE", MODE_OLDFILE) 控制檯視窗尚未開啟 Read(handle,buf,1) = 視窗開啟,等待輸入或 Write(handle,buf,1) = 視窗開啟

資源

[edit | edit source]

存在一個微小的先有雞還是先有蛋的問題。AOS 在使用第三方自動引導 ROM(UAE 硬碟檔案驅動程式是第三方自動引導 ROM)進行自動掛載時會執行此操作:FileSystem.resource 被新增。

某些東西將 FFS dostype 節點新增到 FileSystem.resource 中。這發生在 dos 初始化之前。(也許是在 FileSystem.resource 初始化時,或者是在 FFS 初始化時,根據 Guru Book,它在 dos 之前初始化)。

自動引導 ROM 執行其工作,檢查分割槽,從 RDB 載入檔案系統(如果已安裝),並將版本與 FileSystem.resource 中的檔案系統進行比較。如果不存在 RDB FFS,則檢查 FileSystem.resource,新增 dos 節點等。Dos 初始化,依此類推…

問題:AROS 非 dos 資料包 AFS.handler 在初始化期間需要 dos。這意味著它不能在 dos 之前初始化,因此 FileSystem.resource 節點不能由 AFS 處理程式過早新增。(我很樂意將其破壞,因為它不正確,但我認為我是少數派:D)。

但 AFS 處理程式的版本和修訂資訊需要正確填充 FileSystem.resource AFS 條目。(不需要 seglist,因為 NULL seglist 意味著使用 rn_FileHandlerSegment,它可以在 dos 之後設定)。

此外,駐留列表條目需要由除 AFS.handler 之外的其他東西新增(我不知道)(同樣,需要 dos 來執行此操作)。

我認為真正的問題是 AROS 檔案系統檢測根本沒有使用 FileSystem.resource。M68k-amiga 需要它,因為第三方引導 ROM 預計它會存在,並預計它在 KS2.0+ 中包含 AFS Dostypes。

此剩餘問題阻止從第三方引導 ROM 驅動程式 RDB 硬碟驅動器啟動,而沒有安裝 RDB LSEG FFS(使用例如任何 SCSI 介面卡或正常 UAE 硬碟檔案驅動程式的真實 Amiga)或正常分割槽硬碟檔案(僅限 UAE)。

AROS ata.driver 工作是因為它知道如何處理它,UAE 目錄硬碟驅動器也是如此,因為它是一個檔案系統,而不是一個裝置驅動程式。

是的,但請注意,AOS 甚至沒有 FFS 節點中的 seglist 欄位("patchflags" 中的 seglist 位未設定,seglist 指標位於分配的記憶體之外,它們每個節點節省了 4 位元組的 RAM!),處理程式啟動程式碼在 RootNode 中的 seglist 為 null 時使用 rn_FileHandlerSegment。

這似乎暗示

  • FileSystem.resource 初始化
  • afs.handler 透過向 FileSystem.resource 註冊自身進行初始化
  • dos.library 初始化,在 FileSystem 中查詢 'afs.handler' 條目,並將 rn_FileHandlerSegment 設定為條目的 fse_SegList

如果 AROS 的 AFS 處理程式在初始化期間不需要 DOS,我們將沒問題。是的,只要它以比 dos 更高的駐留優先順序工作即可。如果是這樣,這可能是最好的方法。AFS 處理程式在初始化期間所做的只是將自身(版本和處理程式 LSEG)註冊到 FileSystem.resource?是的,但請注意,AOS 甚至沒有 FFS 節點中的 seglist 欄位("patchflags" 中的 seglist 位未設定,seglist 指標位於分配的記憶體之外,它們每個節點節省了 4 位元組的 RAM!),處理程式啟動程式碼在 RootNode 中的 seglist 為 null 時使用 rn_FileHandlerSegment。

我們可以擺脫 AROS_STACK_GROWS_DOWNWARDS 嗎?這似乎不必要地使一些事情複雜化,而且它似乎在整個 AROS 中並沒有被一致地使用。我們是否真的支援“堆疊向上增長”的架構?是否有人能想到一個不是來自 1980 年代之前的架構?

我認為是為 PA RISC(我可能錯了),這在 90 年代中期,這段程式碼編寫時仍然很常見。(我記得當時它幾乎是最快的 CPU)。

也就是說,我認為出於實際原因,擺脫它是有意義的。我預計 AROS 會在使用暫存器視窗的 CPU 上執行,然後才會在堆疊以另一種方式增長的 CPU 上執行。

華夏公益教科書