(蹲了幾天 217
趁今天休息的時候寫一點心得)
網頁上有提示可以參考 C 的作法
大概是這樣
/* C */
int xxx(int,int)
{
int counter,result;
int i,j;
i++;
counter = i + j;
...
return result;
}
; Assembly
xxx proc
push bp
mov bp,sp
sub sp,8
...
...
inc [bp+4]
mov ax,[bp+4]
add ax,[bp+6]
mov [bp],ax
...
mov ax,[bp+2]
mov sp,bp
ret
xxx endp
上面兩段 一段是 C 的程式
第二段可以用 C compiler 的一些指令產生
兩邊對照一下 大概就可以知道 local variable 在 C 裡面是怎麼處理的了
因為 stack 在 x86 是由高位址往低位址跑
所以 sub sp,8 會在 stack 裡留下 8 bytes 的空間
這 8 bytes 分別是 counter,result,i,j 四個變數
至於詳細的動作 最好是用 debugger 自己 trace 一次
觀察 register 的變化情況
描述太多沒有用 因為閱讀很簡單 可是實作起來 要注意的地方很多
只有親自做一遍才能體會
作業二想要挑戰 19 位以上的結果
變數一定會超過 64bits
如果 stack 不能滿足你的需求 想動用 ah=48h,int21h(dos)
剛開始一定會讓人陷入沮喪的窘境
...因為不管怎麼樣寫 一定會遇到 carry!
其實不是沒有 free memory space
是程式剛載入時 所有的 free memory space
全都給了你的程式
我是這樣處理
.DATA
PCB dw 0
.CODE
Start:
mov ax,@data
mov ds,ax
mov PCB,es ; (*1)
mov bx,0 ; (*2)
add bx,0010h ; (*3)
mov es,PCB
mov ah,4Ah
int 21h
mov bx,0FFFFh
mov ah,48h
int 21h
mov ah,48h
int 21h
mov Block_Seg,ax
...
在一開始的地方 也就是 mov ax,@data/mov ds,ax 這兩個指令動作前
os(dos) 將使用者的程式載入時
ds/es 是設成 pcb 開始的 segment address
pcb 大小是 100h bytes (256 bytes)
緊接著這 256 bytes 後面的 才是程式本身
所以(*3)才要 add bx,0010h.... 這裡別忘了 int 4xh 的 bx 放的是 paragraph
第一次 compile/link 時 產生 map 檔
看看整段 code 的總長度
然後在(*2)把長度填進去
重新再 compile 一次
為什麼要這麼麻煩做兩次 compile/link 的動作?!
其實可以不必這麼麻煩...
直接改用舊的格式就可以一次ok...
只是舊的 masm assembly 解釋起來很多
而我不知道 .dosseg 到底有哪些東西可以用
又今天下載 masm reference 一直失敗
所以挑這個最簡便的方式貼出來...
dos 管理記憶體 是用 link list 的方式去完成的
pcb 前面 16 bytes 通常是 mcb
有興趣的可以寫這樣一段
Start:
mov bx,3322h
mov ah,4Ah
int 21h
mov ah,4Ch
int 21h
END Start
用 debug 載入 先不要執行
直接下 d (ds-1):0 l16
然後用 g 或是 p 執行到 mov ah,4Ch 時
再下一次 dump (ds-1):0 l16
仔細看看 第三和第四 2 bytes
同樣的 可以把 3322h 換成 0FFFFh 再玩一次
比較一下傳回的 bx 和那兩個 byte
...
比較起來 還是在 linux 寫比較方便挑戰高位數
--
恰恰-- 啦啦--- 啦
--
Q: What is the difference between a methodologist and a terrorist?
A: You can negotiate with a terrorist.
--
※ 發信站: 批踢踢實業坊(ptt.csie.ntu.edu.tw)
◆ From: 211.74.135.66