這是一個經典的 MASM 5.0 教學範例,示範如何純粹用組合語言指令模擬 16 位元有號二進制整數減法運算,包含原碼/補碼轉換、逐位減法、借位處理、結果轉十六進位顯示。適合初學者理解電腦底層算術運算原理。
questBuma proc near
mov al,[bx+0]; cmp al,'0'; jz qbret ; 正數直接返回
mov si,1
qbroat: ; 取反
mov al,[bx][si]; cmp al,'0'; jz qb1
mov al,'0'; mov [bx][si],al; jmp qb2
qb1: mov al,'1'; mov [bx][si],al
qb2: inc si; cmp si,16; jl qbroat
qnext: ; 加 1
mov dh,1; mov si,15
qbincre:
mov al,[bx][si]; sub al,'0'; add al,dh; mov dh,0
cmp al,2; jnz qbi1; mov al,0; mov dh,1
qbi1: add al,'0'; mov [bx][si],al
dec si; cmp si,0; jnl qbincre
qbret: ret
questBuma endp
演算法:符號位不變,數值位取反加一。使用字元 '0'/'1' 運算,DH 作為進位旗標。
bsubproc proc near
push ax bx cx si
mov bx,0; mov si,15 ; BX=借位旗標, SI=最低位索引
broat:
mov al,num1[si]; add al,bh; mov bh,0
cmp al,num2[si]; jnl bnext
add al,2; dec bh ; 借位處理
bnext: sub al,num2[si]; add al,'0'; mov sum[si],al
dec si; cmp si,0; jnl broat
pop si cx bx ax; ret
bsubproc endp
從最低位 (索引 15) 向最高位 (索引 0) 迴圈。BH 保存借位 (0 或 -1)。若被減數位 < 減數位,則被減數位 +2 (借位),設 BH=-1 供下一位使用。
BinaryToHexAndOut proc near
mov dh,2; mov si,0
bth1: mov al,0; mov di,0
bth2: mul dh; add al,[bx][di]; sub al,'0'; inc di; cmp di,4; jl bth2
cmp al,9; jna bth3; sub al,10; add al,'A'; jmp bth4
bth3: add al,'0'
bth4: mov hexsum[si],al; inc si; add bx,4; cmp si,4; jl bth1
ret
BinaryToHexAndOut endp
每 4 位一組 (共 4 組),以加權法計算十六進位值:AL = b3*8 + b2*4 + b1*2 + b0 (此處 DH=2,MUL DH 相當於左移 1 位,累加 4 次)。結果 0-9 → '0'-'9',10-15 → 'A'-'F'。
binary(YuanMa) num1=1000000000001011 ; 被減數原碼 (-11)
binary(YuanMa) num2=1000000000001101 ; 減數原碼 (-13)
binary(Buma) num1 BM=1111111111110101 ; 被減數補碼
binary(Buma) num2 BM=1111111111110011 ; 減數補碼
binary(Buma) diff sub=0000000000000010 ; 差補碼 (+2)
binary(YuanMa)diffsub=0000000000000010 ; 差原碼 (+2)
hex sumHEX=0002
驗證:(-11) - (-13) = +2,結果正確。
| 優點 | 說明 |
|---|---|
| 原理透明 | 逐步展示補碼轉換、減法邏輯、進制轉換 |
| 字元級操作 | 直接處理 ASCII '0'/'1',直觀易懂 |
| 模組化 | 三個獨立 PROC,結構清晰 |
| 缺點/改進 | 說明 |
| 效率低 | 未善用 CPU 算術指令 (SUB, SBB, DAA 等) |
| 錯誤處理簡陋 | 輸入非 0/1 直接重輸,無提示 |
| 溢位未檢查 | 16 位有號減法可能溢位 (OF),未處理 |
| 硬編碼緩衝區 | 固定 19/5 位元組,缺乏邊界檢查 |
這個範例雖然不具實用性 (CPU 內建減法指令遠快於模擬),但作為教學工具極為優秀。它將「黑盒子」指令拆解為可視的位元操作,幫助初學者建立「補碼減法 = 加法器 + 取反 + 1」的硬體視角。對於進階學習,可嘗試改寫為使用 SBB (帶借位減法)、DAA (十進位調整)、查表法轉十六進位等優化版本,體會指令集設計的精妙。