看板 b89902xxx 關於我們 聯絡資訊
(蹲了幾天 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