先熟悉nasm 【1】

來源:互聯網
上載者:User
 註:應該是新浪部落格的一個bug:“define”前面加%是顯示亂碼的,只能把%用100代替,因此下文看到100define時不要被嚇到。
-----------------------------------------------------------------------------------------------------------------------------------------
 已經看到第3章“保護模式”,反覆讀那段“吸引眼球”的pmtest1.asm,總還是霧蒙蒙的感覺。對其中的SECTION,BITS等關鍵字不甚瞭解,於是知道要專門熟悉一下nasm彙編了。
 “可能有很多人開始學彙編時用的都是MASM“,作者猜的太對了,我當初學的就是王爽的那本(中國這樣的寫作者太少了)。於淵提及“學習成本”這個概念,很是贊同,反正AT&T和INTEL風格的彙編語句最終都翻成一樣的機器碼,那學通一樣就夠,反正是彙編工具嘛。
 所謂“熟悉一下nasm彙編”,就是用nasm寫一些基礎的子程式,慢慢體會,同時也累積一個自己的彙編子程式庫,就像libc似的。
 
1,100define plus(a,b) ((a)+(b))
  這種格式的宏跟C很像,預定義之後這樣使用:mov ax,plus(1,2)
  nasm的宏處理器便會把它翻譯成:mov ax,3 準確說是翻譯成"mov ax,((1)+(2))"
  至於((a)+(b))為什麼要加這麼多括弧,是防止變數a,b本身又是運算式,加上括弧是保證宏替代後,運算次序不被打亂。

2,org是做什麼的
 王爽的書裡沒提到org,但清華大學的那本黃皮書裡是有的(和國內大多數書一樣,那本書完全不是寫給自學者讀的)。
--------------------------------------------------------------------------------------

NASM組合語言彙編BIN格式的程式中,舉例說明ORG的意義

ORG 100H
START:
movax,START;        這裡相當於 mov ax,100h
……

上面有一個標籤 START ,執行mov ax,START時,ax=100h,如果不寫ORG 100H,那麼就是相當於 ORG0H,這樣的話,ax=00h

這就是說,地址引用的數值 = 該地址在檔案內的位移+ org 的數值。
更本質的說,org指令是提前告訴編譯器:“你正在編譯的這段的程式碼片段將來肯定會被載入到記憶體的XXX地址處”。編譯器據此來計算每個標籤(label)對應的物理地址。(這句話是我自己加上來的)

--------------------------------------------------------------------------------------
分割線裡就講得很清楚了,摘自http://hi.baidu.com/chinfs/blog/item/535d0eed42866addb21cb18d.html 僅摘了文章開頭,已足夠說明含義,且原文後半部分講的有些繞

3,寫一個最原始的echo
 nasm的多行宏是很強大的,現在就用它來實現最原始的echo功能,在螢幕1行1列處顯示一串字元。為方便重複利用,代碼都寫到一個標頭檔echo.mac裡,需要使用時加上句%include "echo.mac"就好了
----------
%ifndef echo_mac      ;這跟c很像,也是為了防止標頭檔的重複包含
100define echo_mac
%include"esbp.mac"     ;這是我自己寫的另一個多行宏,方便把標籤地址映射到相應的es,bp寄存器。
%macro echo 1
jmp%%start     ;nasm真是人性化:%%是專門為多行宏定義的一種本地標籤,即,你調用這個宏n次,nasm會
                        ;把%%start轉化為n個不同的標籤,調用n+1次,則轉化成n+1個不同的標籤。設想沒有這個功能
                        ;的話,同一個宏在一段代碼的n個位置展開後,就得到n個一模一樣的%%start,那是多麼恐怖
%%local:db %1
%strlen bytenum%1         ;用C語言描述就是——#define bytenum strlen(%1)
%%start:movcx,bytenum         ;開始為int 10h中斷填充相關參數  cx儲存要顯示的字串長度,即幾個byte
movah,13h         ;int 10h中斷的13h號子功能:在指定行列顯示es:bp指向的字串
moval,1h         ;al設定顯示輸出方式,1表示字串只含顯示字元,其顯示內容在bl,顯示後,游標位置改變
mov dh,0          ;第0行     
movdl,0         ;第0列
movbh,0         ;0頁為顯示頁
movbl,00000100b         ;紅色字元
esbp%%local        ;%%local即字串所在記憶體位址,用esbp宏將其映射到es,bp寄存器
int 10h
%endmacro
%endif
----------
這是esbp.mac檔案:
----------
%ifndef esbp_mac
100define esbp_mac
%macro esbp 1
;the address passed here must be a 16-bit digit,namely not greaterthan 0xffff
push ax
push dx
mov ax,%1
mov dx,%1
and dx,0x000f
shr ax,4
mov bp,dx
mov es,ax
pop dx
pop ax
%endmacro
%endif
----------
試試效果如何吧,下面的測試檔案boot.asm
----------
%include "echo.mac"
org 0x7c00
start:echo 'hello! oranges world'
times 510-($-start) db 0
dw 0aa55h
----------
編譯成bin檔案,並dd到虛擬磁碟的mbr,bochs調試,


這個石器時代的echo宏就做好啦!

4,稍微增強這個echo的功能,能夠將字串顯示到指定行列。下面是echoAtLC.mac
----------
%ifndef echoAtLC_mac
100define echoAtLC_mac
%include "esbp.mac"
%macro echoAtLC 3
jmp %%start
%%local:db %1
%strlen bytenum %1
%%start:mov cx,bytenum
mov ah,13h
mov al,1h
mov dh,%2
mov dl,%3
mov bh,0
mov bl,00000100b
esbp %%local
int 10h
%endmacro
%endif
----------

5,把echo再做強一些,使其能將字串顯示到游標所在位置
思路是:利用int 10h的3號子功能擷取游標所在行列,再調用echoAtLC宏就好了。下面是echoUnderCursor.mac
----------
%ifndef echoUnderCursor_mac
100define echoUnderCursor_mac
%include "echoAtLC.mac"
%macro echoUnderCursor 1
;get the line&column cursor locate
push dx
push cx
push ax
push bx
mov ah,3h
mov bh,0
int 10h             ;dx changed,and it storesline,column 
pop bx
pop ax
pop cx                  
echoAtLC %1,dh,dl
pop dx                    ;dxrecovered
%endmacro
----------

6,readCursor_D.mac和setCursor_page_line_column.mac
這兩個標頭檔內的宏,分別用來讀取游標資訊和設定游標位置,即對int 10h的3號和2號子功能的封裝
標頭檔readCursor_D.mac
----------
;change dx
;dh store line,dl store column
%ifndef readCursor_D_mac
100define readCursor_D_mac
%macro readCursor_D 0
push bx
push ax
push cx
mov bh,0
movah,3h         ;3號子功能的出口參數分別放在放在cx,dx中,cx裡的資訊我用不上,於是pop覆蓋了
int 10h
pop cx
pop ax
pop bx
%endmacro
%endif
----------

標頭檔setCursor_page_line_column.mac
----------
;change no reg
%ifndef setCursor_mac
100define setCursor_mac
%macro setCursor_page_line_column 3
push ax
push bx
push dx
mov bh,%1
mov dh,%2
mov dl,%3
movah,2h         ;2號子功能就是設定游標的文本座標的
int 10h
pop dx
pop bx
pop ax
%endmacro
%endif
----------
此類的標頭檔越寫越多,我開始注意統一規範:例如,第一行注釋,講明這個宏執行後是否對寄存器造成影響,如果是,在宏的名字後統一加_D尾碼,像比readCursor_D,_D就是說這個宏dangerous。例如,假如這個宏需要的參數多於2個,我就將參數的名字資訊附加到宏的名字裡,像比setCursor_page_line_column,這樣一看就知道要輸入哪些參數。例如,宏的名字盡量跟標頭檔的名字一樣。(當然,不包括.mac尾碼部分了)

7,實現游標的斷行符號功能 cursorEnter.mac
----------
;change no reg
%ifndef cursorEnter_mac
100define cursorEnter_mac
%include "setCursor_page_line_column.mac"
%include "readCursor_D.mac"
%macro cursorEnter 0
push dx
readCursor_D        ;擷取當前游標的行,列資訊
incdh         ;將游標的行數值加1,實現換行
setCursor_page_line_column 0,dh,0         ;最後一個參數0,將游標置於第0列,實現斷行符號----->這就實現一個
               

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.