• 3

最小的 執行檔 只需 1 個 Byte

IQuit wrote:
我 電腦 還 收藏 有 近 20,000 隻 病毒


COVID-19 included?
cruiseton wrote:
短暫玩過APPLE II ( MOS 6502) + ZILOG Z80 add-in card + CP/M ^++^
====
為什麼 every DOS 程序開頭都是 CD 20?
在 1980 年代初期,CP/M-80 是 8 位元電腦(Intel 8080 / Zilog Z80)的霸主。微軟與西雅圖計算機產品公司(Seattle Computer Products)為了讓開發者願意把 CP/M 上的軟體轉移到 16 位元的 8086 / MS-DOS 上,推出了「自動轉譯工具」(把 8080 組合語言直接機械式轉換成 8086 組合語言)。
為了讓這些轉譯過來的舊程式不用改動核心邏輯、也不會當機,DOS 在程式記憶體的最開頭(PSP,Program Segment Prefix, 256 bytes)複製了 CP/M 的記憶體佈局:
1. 程式結束(Exit)的兼容:
CP/M 做法:跳轉到記憶體 0000h 位置(例如 JMP 0000h 或 RET)。
DOS 的應對:在 PSP 的 Offset 0000h 放上 CD 20(即 INT 20h)。
結果:轉譯後的 CP/M 程式照舊執行 JMP 0000h 時,CPU 一跳過去就會讀到 CD 20,觸發 INT 20h 中斷,安全的把控制權交還給 DOS,完全不會崩潰。
2. 系統呼叫(API Call)的兼容:
CP/M 做法:呼叫 0005h 位置(CALL 0005h)來執行系統功能(BDOS)。
DOS 的應對:在 PSP 的 Offset 0005h 放上 9A ...(遠跳轉 CALL FAR 到 DOS 的 API 入口)。
結果:舊程式呼叫 CALL 0005h 時,也能順利呼叫到 DOS 的服務。
CP/M 與 DOS PSP 的記憶體對照表

PSP 偏移量 (Offset) CP/M 原始用途 DOS PSP 對應機器碼 / 內容 作用
0000h Warm Boot(重啟/退出程式) CD 20 (INT 20h) 讓舊程式跳回 0000h 時能優雅退出
0002h 記憶體上限 最高可用記憶體段位址 告知程式剩餘記憶體大小
0005h BDOS 系統呼叫入口 9A ... (CALL FAR DOS) 讓舊程式呼叫 0005h 時能執行 DOS 功
所以,每個 DOS 程式(不論是 .COM 還是 .EXE)載入時,DOS 都會在記憶體頭部 256 位元組(PSP)的第 0 個位置固定塞入 CD 20。這就是為什麼你在反組譯或用 DEBUG.EXE 觀察記憶體時,開頭永遠都會看到 CD 20 的原因!


你 寫 這些 AI 文 只是 原理,
並 沒有 回在 點上.

1 Byte 程式碼 並 沒有 主動 JMP 到 CS:0x0000
主要 關鍵 是 MS 在 堆疊頂 就 預堆 0x00 0x00
所以 1 Byte 程式碼 執行 RET 這時 從 堆疊 取回 0x00 0x00
接著 才是 後續 ...
★★★ "我要留言" 不回, 只回 1 般回文. ★★★
cruiseton

Assembly 只學了皮毛. [^++^] 問了三個 AI, 懶的貼 [XD]

2026-08-04 11:50
cruiseton wrote:
COVID-19 included?


等到 COVID-520 再 收藏.
★★★ "我要留言" 不回, 只回 1 般回文. ★★★
IQuit wrote:你 寫 這些 AI 文 只是 原理,
並 沒有 回在 點上.

1 Byte 程式碼 並 沒有 主動 JMP 到 CS:0x0000
主要 關鍵 是 MS 在 堆疊頂 就 預堆 0x00 0x00
所以 1 Byte 程式碼 執行 RET 這時 從 堆疊 取回 0x00 0x00
接著 才是 後續 ...

好吧, (大) 補貼

1 byte 程式怎麼運作?

假設檔案只有 1 byte:
C3
載入後記憶體大概是:
PSP
0000h-00FFh(256 bytes)


程式
0100h: C3


CPU 從 0100h 開始執行:
RET

RET 不是應該回到呼叫者嗎?

對,一般情況是這樣。
但 DOS 在啟動 COM 程式時,故意先把堆疊(stack)準備好。
它在 stack 裡放入一個返回位址:
0000h
所以 RET 會跳到:
PSP:0000

PSP 的開頭放了什麼?

DOS 建立的 PSP(Program Segment Prefix)前兩個 byte 是:
CD 20
也就是:
INT 20h
這是最早的 DOS「結束程式」功能。

整個流程

0100: C3
RET
從 stack 取出 0000h
0000: CD 20
INT 20h
返回 DOS

所以這個 1-byte 程式其實是利用了 DOS 預先安排好的堆疊與 PSP。

這其實是在模仿 CP/M

在 CP/M 中,程式結束時常常只要:
RET
因為載入器會先在 stack 放好返回位址,讓 RET 回到作業系統。
DOS 為了讓移植 CP/M 程式更容易,就保留了這種行為。

另一個重要相容技巧:CALL 5

CP/M 程式呼叫系統服務時常用:
CALL 0005h
DOS 也在 PSP 的 0005h 放了一個「跳板(stub)」。
PSP 內容(簡化)
<thead></thead>
偏移
用途
0000h INT 20h(程式結束)
0005h CP/M 相容的系統呼叫跳板


因此很多從 CP/M 翻譯過來的程式,只要稍微修改就能在 DOS 上運作。

DOS 是「真相容」嗎?

不是。
要分清楚兩種相容:
二進位相容(Binary compatible)

8080/Z80 的 CP/M 程式 不能直接在 DOS 執行。


原始碼相容(Source compatible)

程式重新組譯後,通常只需少量修改即可移植到 DOS。




為什麼這麼重要?

這些小技巧讓 IBM PC 在 1981 年能快速獲得大量軟體:
  • WordStar

  • dBase

  • SuperCalc

  • 各種 CP/M 工具程式

開發者不必重寫整個程式,只要移植。
只要移植。
cruiseton wrote:
好吧, (大) 補貼 XD
1 byte 程式怎麼運作?
假設檔案只有 1 byte:
C3
載入後記憶體大概是:
PSP
0000h-00FFh(256 bytes)
程式
0100h: C3
CPU 從 0100h 開始執行:
RET
RET 不是應該回到呼叫者嗎?
對,一般情況是這樣。
但 DOS 在啟動 COM 程式時,故意先把堆疊(stack)準備好。
它在 stack 裡放入一個返回位址:
0000h
所以 RET 會跳到:
PSP:0000
PSP 的開頭放了什麼?
DOS 建立的 PSP(Program Segment Prefix)前兩個 byte 是:
CD 20
也就是:
INT 20h
這是最早的 DOS「結束程式」功能。
整個流程
0100: C3
RET
從 stack 取出 0000h
0000: CD 20
INT 20h
返回 DOS
所以這個 1-byte 程式其實是利用了 DOS 預先安排好的堆疊與 PSP。
這其實是在模仿 CP/M
在 CP/M 中,程式結束時常常只要:
RET
因為載入器會先在 stack 放好返回位址,讓 RET 回到作業系統。
DOS 為了讓移植 CP/M 程式更容易,就保留了這種行為。
另一個重要相容技巧:CALL 5
CP/M 程式呼叫系統服務時常用:
CALL 0005h
DOS 也在 PSP 的 0005h 放了一個「跳板(stub)」。
PSP 內容(簡化)

偏移
用途
0000h INT 20h(程式結束)
0005h CP/M 相容的系統呼叫跳板
因此很多從 CP/M 翻譯過來的程式,只要稍微修改就能在 DOS 上運作。
DOS 是「真相容」嗎?
不是。
要分清楚兩種相容:
二進位相容(Binary compatible)
8080/Z80 的 CP/M 程式 不能直接在 DOS 執行。
原始碼相容(Source compatible)
程式重新組譯後,通常只需少量修改即可移植到 DOS。
為什麼這麼重要?
這些小技巧讓 IBM PC 在 1981 年能快速獲得大量軟體:
WordStar
dBase
SuperCalc
各種 CP/M 工具程式
開發者不必重寫整個程式,只要移植。
只要移植。


AI 懶的看 賊長,
AI 不要常用 會 變 賊笨,
鵝你鴕騾 我不慈悲.
★★★ "我要留言" 不回, 只回 1 般回文. ★★★
cruiseton

無意深究, 打發時間而已 [笑到噴淚]

2026-08-04 12:19
IQuit wrote:
不解,
為啥 最小的 執行檔 只需 1 個 Byte,
而且 能 正常執行 且 正常結束.



INT 20h 是 2 bytes (CD 20)。

一個只有 RET 的 1 byte .COM 程式 不能安全執行,因為它會跳到未知位址,導致不可預期的結果
sansen wrote:
INT 20h 是 2 bytes (CD 20)。
一個只有 RET 的 1 byte .COM 程式 不能安全執行,因為它會跳到未知位址,導致不可預期的結果


表示 你 沒看 文.
★★★ "我要留言" 不回, 只回 1 般回文. ★★★
sansen

看了, 你那個1.com, debug 就是只有一個 RET

2026-08-05 6:14
IQuit wrote:
等到 COVID-520...(恕刪)



推薦以下幾隻毒,有收藏價值喔

T病毒:全名 Tyrant-virus,是保護傘公司(Umbrella)開發的生化兵器,會讓生物新陳代謝加速 並使人變成喪屍。
G病毒:全名 Generation-virus 或 Golgotha,由科學家威廉·柏金發現,會造成宿主身體持續性且激烈的突變。
始祖病毒:源自非洲原始花朵的母體病毒,是一切生化病毒與怪物的根源。
T-維洛尼卡病毒:由亞莉克莎·艾希佛德結合始祖病毒與女王蟻基因研發的高級病毒。
ailaug2 wrote:
推薦以下幾隻毒,有收藏價值喔
T病毒:全名 Tyrant-virus,是保護傘公司(Umbrella)開發的生化兵器,會讓生物新陳代謝加速 並使人變成喪屍。
G病毒:全名 Generation-virus 或 Golgotha,由科學家威廉·柏金發現,會造成宿主身體持續性且激烈的突變。
始祖病毒:源自非洲原始花朵的母體病毒,是一切生化病毒與怪物的根源。
T-維洛尼卡病毒:由亞莉克莎·艾希佛德結合始祖病毒與女王蟻基因研發的高級病毒。


等 SkyNet 阿諾蝦米碗擱.
★★★ "我要留言" 不回, 只回 1 般回文. ★★★
IQuit wrote:
不解,
為啥 最小的 執行檔 只需 1 個 Byte,

因為至少要一個 RET..
x86 的 c3 ret 就是 1 個 Byte, ex:
0: b8 05 00 00 00  mov    eax,0x5
5: c3 ret

系統 call 進來, 馬上返回 .. 讓系統立即拿回控制權..
如果沒有返回, 那CPU會去執行到 先前遺留在記憶體的資料... 什麼資料, 不可預期...
  • 3
內文搜尋
X
評分
評分
複製連結
Mobile01提醒您
您目前瀏覽的是行動版網頁
是否切換到電腦版網頁呢?