彙編語言:知識點拾遺

彙編語言:知識點拾遺

前言

讀王爽的書已經有一段時間了,馬上就要學習有關“中斷”的知識了。在繼續學習之前,我想把一些我感覺比較有意思的小細節,小技巧總結一下。文章不長,如果以後有新的收穫,我會把這一系列繼續寫下去。

大小寫字轉換的技巧

一般來說,要想實現大小寫字母的轉換,有兩種基本思路。

  1. 根據大小寫字母在ascii表中的相對位置進行轉換
  2. 根據字母在字母表中相對於首字母a的位置進行轉換

第一種思路:
如果字母爲大寫字母,小寫字母 = 大寫字母 + 20H
如果字母爲小寫字母,大寫字母 = 小寫字母 - 20H

第二種思路:
如果字母爲大寫字母,小寫字母 = ‘a’ + 大寫字母 - ‘A’
如果字母爲小寫字母,大寫字母 = ‘A’ + 小寫字母 - ‘a’

王爽的書中有提供了令一種方法:
假設當前字母在寄存器AL中
如果AL爲大寫字母,則and al,11011111B
如果AL爲小寫字母,則 or al,00100000B
此時AL中即爲所要轉換的結果。

爲什麼可以這樣做呢?我下面給出一張表格,供大家驗證。

大寫 十六進制 二進制 小寫 十六進制 二進制
A 41H 01000001 a 61H 01100001
B 42H 01000010 b 62H 01100010
C 43H 01000011 c 63H 01100011
D 44H 01000100 d 64H 01100100
E 45H 01000101 e 65H 01100101
F 46H 01000110 f 66H 01100110

JMP、CALL、RET指令的機制

以下用s表示標號

  • jmp short s——依據位移修改IP進行段內短轉移(8位位移)
  • jmp near ptr s——依據位移修改IP進行段內近轉移(16位位移)
  • jmp far ptr s——段間遠轉移,使(CS) = s的段地址,(IP) = s的偏移地址
  • jmp 16位reg——使(IP) = (reg)
  • jmp word ptr 內存單元地址——使(IP) = (內存單元地址)
  • jmp dword ptr 內存單元地址——使(CS) = (內存單元地址+2),(IP) = (內存單元地址)

詳細內容見原書。

我們可以用彙編語言(儘管不符合語法)去理解ret和call指令

  • ret——相當於pop IP
  • retf——相對於先pop IP,然後pop CS
  • call s——相當於先push IP,然後jmp near ptr s
  • call far ptr s——相當於先push CS,再push IP,最後jmp far ptr s
  • call 16位reg——相當於push IP,然後jmp reg(16位)
  • call word ptr 內存單元地址——相當於push IP,然後jmp word ptr 內存單元地址
  • call dword ptr 內存單元地址——相當於先push CS,再push IP,最後jmp dword ptr 內存單元地址

由於call與ret常常配合使用,所以之前我以爲這兩條指令必須成對出現(在設計子程序的時候)。彙編語言是相當自由的語言,當然沒有這種約束,這些指令你想怎麼用,你就怎麼用,只不過它們的配合使用是一種“套路”罷了。
如果不熟悉call,ret的執行原理,在設計子程序的堆棧傳參時,就會很難理解。
我在課堂上學習這兩條指令的時候,老師完全沒說堆棧的事,之後我發現有一個實驗(輸出一個集合的所有子集)是要用遞歸的技巧的,我當時就要罵人了,老師當時堆棧傳參講的不清不楚(說難聽點,講了和沒講是一樣的),果斷放棄這個選題,選了一個更簡單的實驗,但這樣怎麼體現出我認真的學習態度呢?(不要臉
後來學習了王爽的書,弄懂了這些原理,堆棧傳參就很好理解了。

最後補充一點:

  • ret n——相當於pop IP,然後add sp,n

C語言中局部變量也在堆棧中存放。

標誌位DF與串處理指令

這部分老師在課堂上是不講的(不知道其他學校是怎麼樣的)。其實這部分很簡單。
方向標誌位DF

  • DF = 1,每次操作後inc si, inc di
  • DF = 2,每次操作後dec si, dec di

cld指令使DF=0,std指令DF =1

下面用匯編指令(不符合語法)來理解下面兩條指令

movsb

功能:

mov         es:[di], byte ptr ds:[si]
;如果DF = 0
                inc si
                inc di
;如果DF = 1
                dec si
                dec di

movsw

功能:

mov         es:[di], word ptr ds:[si]
;如果DF = 0
                add     si,2
                add     di,2
;如果DF = 1
                sub      si,2
                sub      di,2

rep指令

rep指令常常和以上兩條指令配合使用。舉個例子:
rep movsb 相當於

s:      movsb
        loop  s    ;根據CX決定循環次數

小結

串傳送指令的注意點

  • 傳送的初始位置:ds : si
  • 傳送的目的位置:es : di
  • 傳送的長度: CX
  • 傳遞的方向: 標誌爲DF

其他注意事項

由於篇幅原因(其實就是懶得再寫下去了),還有一些注意點就不詳細討論了。
比如:
- 除法指令的溢出問題
- 80X25彩色字符模式的顯示緩衝區

總結

彙編語言是一門相當自由的語言,只要你有耐心,你可以用它完成好多事情。
這種感覺是在學習王爽的教材中體會得到。在此之前,我只是通過學校課堂大概瞭解了一下彙編語言,我甚至不知道數據段,代碼段,堆棧段是可以通過自己修改段寄存器來“定義”的(就是蠢,沒別的解釋)。但這種自由也帶來一種壞處,就是代碼的可讀性較差,核心代碼往往被其他操作掩蓋(比如中間值傳遞,傳參,保護寄存器),因此看似很長的代碼,實際實現的功能很簡單(這讓我怎麼顯擺),甚至昨天剛寫的代碼,第二天居然讀不懂了(好吧,我只是因爲懶,沒寫註釋,但不管怎麼說,彙編就是難讀!)。
但不管怎麼說彙編還是很有用的。下面就用王爽書中的實驗11——編寫子程序,結束這篇博文。(我怎麼還沒寫註釋!反正沒有老師看,偷個懶啦)

assume      cs:codesg

datasg      segment
    db 'Beginner`s All-purpose Symbolic Instruction Code.',0
datasg      ends

codesg      segment

main:       mov     ax,datasg
            mov     ds,ax
            mov     si,0
            call    letterc

            mov     ax,4c00h
            int     21h
;-----------------------------------------------------------
;proc_name:     letterc
;function:      translate uppercase into lowercase in a string which ends with digit 0
;interface:     ds:si points to the first address of the string

letterc:            push    ax
                    push    si

    letterc_s:      mov     al,[si]
                    cmp     al,'a'
                    jb      letterc_next
                    cmp     al,'z'
                    ja      letterc_next
                    and     al,11011111b
                    mov     [si],al
    letterc_next:   inc     si
                    cmp     al,0
                    je      letterc_out
                    jmp     short letterc_s

    letterc_out:    pop     si
                    pop     ax
                    ret
;----------------------------------------------------------
codesg      ends

end   main
發佈了58 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章