反向工程拆解 Intel 8087 浮點晶片的 69 位元加法器
righto.com · 2026-06-14
Ken Shirriff 最新一篇逆向工程文章鎖定 Intel 8087 浮點協處理器(1980 年)的核心運算電路——一顆 69 位元加法器。8087 能讓數學運算速度提升最多 100 倍,包括正切、指數、對數等超越函數,而這一切效能都繫於這顆加法器之上。晶片面積僅 5mm×6mm,加法器位於分數資料路徑(fraction datapath)的正中央。
曼徹斯特進位鏈
二進位加法最大的瓶頸在於進位傳播(carry propagation):若讓進位訊號逐位元「漣漪」傳遞,69 位元加法將耗費大量時間。8087 採用 1959 年曼徹斯特大學為 Atlas 電腦開發的曼徹斯特進位鏈技術,將 69 位元切成 4 位元一組,以並行開關讓進位快速穿越導線,大幅壓縮傳播步數。
每個位元依輸入組合分為三種狀態:Generate(1+1,無論進位輸入皆產生進位輸出,對應 AND 邏輯)、Delete/Kill(0+0,消滅任何進位輸入,對應 NOR 邏輯)、Propagate(0+1,進位輸出等同進位輸入,對應 XOR 邏輯)。這三種訊號可同時並行計算,不需等待上一位元結果。
電路實作細節
物理實作以兩顆 NMOS 傳遞電晶體(pass transistors)受 propagate 訊號控制,構成多工器選擇邏輯。由於傳遞電晶體在每一級都會損失些微電壓,設計者將進位鏈限制在 4 位元一組,再搭配進位跳越(carry-skip)電路:當一個 4 位元區塊內所有位置都處於 propagate 狀態時,進位輸出可直接等於進位輸入,跳過該區塊的計算。
為進一步加速,設計採用預充電(precharging)技巧——NMOS 電晶體拉低訊號比拉高更快,因此加法開始時先將進位線充電至 5V,再由電路依需要拉低。propagate 電路在預充電期間強制拉高,將所有進位線綁在一起快速分配電壓。即使有這些最佳化,完整加法仍需兩個時脈週期。
69 位元的由來
8087 名義上處理 64 位元分數值,但加法器實際接受 69 位元輸入、輸出 70 位元。這五個額外位元各有明確用途:
- Guard bit、Round bit、Sticky bit:低位三個捨入精度保障位元(IEEE 754 要求)
- B 暫存器倍增位:支援基數-4 Booth 乘法,可直接計算 2B、B、0、−B
- 二補數位:支援減法透過取負加法實現,容納兩補數取負後的溢位
70 位元輸出再經 Sum Shifter 右移兩位,縮減為 68 位元,供後續乘法、除法與開方運算使用。除法以反覆相減加法與移位實現,開方則沿用二進位長除法原理。矽晶片顯微照片顯示,加法器每個 4 位元區塊佔滿整個金屬佈線層,垂直金屬線負責接地與電源分配,水平線提供分數匯流排通路。
每一幀都要合理:UI 動畫的工程信任問題
tonsky.me · 2026-06-14
Nikita Prokopov 在 tonsky.me 提出一個簡單卻嚴苛的 UI 標準:「在任意時刻對你的應用程式截圖,畫面都必須合理。」這個原則源自 Wayland 的設計目標——確保顯示器上的每一幀都是完整且一致的狀態,不存在過渡期的破碎畫面。這不只是美學要求,而是可量測的工程品質標準。
原本的問題
現代應用程式充斥著在動畫中途截圖會令人困惑的畫面:頁面切換時出現白色閃爍、半載入狀態的佈局暴露給使用者、UI 上同時顯示互相矛盾的狀態訊息。Prokopov 記錄了數個實際案例,其中最典型的是佔位文字與游標動畫不同步——文字從中央位置開始移動,游標卻從左側起始,兩個元素使用不同的錨點,造成明顯的視覺錯位。
另一個案例出現在圖片裁切模式切換:圖片瞬間移位,但裁切邊框卻以動畫過渡,讓使用者在動畫進行中看到一個不存在的中間狀態,誤以為操作出錯。YouTube 的矩形位移動畫也因 DOM 架構限制而產生非預期行為,屬於結構性問題而非一般疏失。
採用的方法
文章的核心技術論點是:正確的動畫實作要求所有相關元素共用同一個時間驅動源(single time source),確保在任意時刻採樣,各元素的狀態仍保持內部一致。若不同元素分別使用獨立的計時器或 CSS transition,就會在系統負載高或幀率降低時出現相位偏移。
- 頁面切換:新頁面完整渲染後才替換舊頁面,不出現空白過渡幀
- 載入佔位:避免將未完成的部分佈局暴露給使用者,骨架屏(skeleton screen)必須與真實內容尺寸一致
- 多元素動畫:確保所有動畫元素採用相同的 easing 函數與時間軸起點
- 狀態一致性:任何時刻畫面上不應同時出現互相矛盾的狀態指示
實際效果
這個標準最終是一個信任問題:使用者無法看見後端程式碼的品質,只能透過 UI 的細節推斷整體工程水準。動畫不同步、畫面閃爍、佈局跳動,在無聲地傳達「這個產品的細節沒有被認真對待」。反之,每一幀都保持視覺邏輯一致的應用程式,即便功能相同,也讓使用者感受到更高的可靠性。精確動畫不只是視覺需求,而是工程誠信的外在可見指標。
在 Behringer 混音台上從零撰寫 x86 BIOS,三週後成功開機 FreeDOS
chrisdevblog.com · 2026-06-08
一位開發者在 chrisdevblog.com 記錄了他花費三週,在 Behringer DDX3216 數位混音台上撰寫自製 x86 BIOS,最終成功開機至 FreeDOS 1.4 命令列的完整過程。DDX3216 的主處理器是 AMD Elan SC300 386 SoC,原廠 BIOS 原始碼無從取得(製造商 PC Engines 與 Phoenix 均未提供),因此必須從頭重寫整套開機韌體。
硬體規格
| 元件 | 型號 / 規格 |
|---|---|
| 主處理器 | AMD Elan SC300(386 SoC) |
| DRAM | 16MB(8× HYB5117400BJ60,4M×4bit) |
| SRAM(顯示用) | 64KB |
| BIOS ROM | 27C512(64K×8bit) |
| 主軟體 Flash | 4× 29C040-120 |
| 外部 UART | Toshiba TLC16C552(雙串口+單並口) |
| 擴充介面 | PCMCIA(接 CompactFlash 卡) |
| 選配 FDC | Intel 82078(焊盤預留,未焊接) |
BIOS 實作的核心挑戰
x86 開機的第一步是重置向量(reset vector):CPU 上電後跳至記憶體位址 0xFFF0 執行指令,作者透過連結器腳本(linker script)強制將重置程式碼放置於 ROM 對應位置,確保 x86 相容性。實模式的記憶體定址公式為 (SEGMENT << 4) + OFFSET,傳統記憶體上限為 640KB,SC300 的 MemoryMappingSystem 可將外部 Flash 的 64KB 區塊分頁映射至 0xD0000–0xEFFFF 與 0xA0000–0xAFFFF 視窗。
LCD 顯示需要使用 ES 暫存器的遠指標(far pointer)函數才能寫入超出當前段的視訊記憶體段 0xB800,作者還需自行生成 8×8 像素字型表(22KB)。外部 UART TLC16C552 需先透過並口訊號啟用晶片選擇邏輯,再設定位元率除法器至 9600bps。CF 卡存取需將 PCMCIA 從記憶體模式切換至 TrueIDE 模式(操作 Card Information Structure),之後以標準 ATA 命令(I/O 位址 0x1F0–0x1F7)用 LBA 方式讀取磁區。
中斷實作與開機結果
DOS 幾乎所有操作都透過軟體中斷而非直接硬體存取,因此 BIOS 必須實作完整的中斷向量表。作者實作了 14 個關鍵中斷:
- INT 0x08:計時器(仿 8254,設定為 18.2Hz)
- INT 0x10:視訊顯示功能
- INT 0x13:磁碟操作(CHS 轉 LBA 定址)
- INT 0x16:鍵盤輸入
- INT 0x19:開機序列啟動
MS-DOS 6.22 成功載入 IO.SYS 與 MSDOS.SYS,但在某個未識別的 INT 0x15 功能呼叫時當機,未能到達 COMMAND.COM。FreeDOS 1.4 則順利開機至命令列提示符,確認自製 BIOS 的相容性。開發過程使用 PicoROM 與 OneROM 模擬器取代反覆燒錄 EEPROM,大幅加速迭代速度;完整原始碼已公開於 GitHub。
原始來源:chrisdevblog.com — Running DOS on Behringer's DDX3216 with a DIY x86 BIOS