[轉譯][馬基 傑斯特(MarkeyJester) 摩托羅拉68000 入門教程] 叄 - 位 指令 | 5. BSET, BCLR 和 BCHG 指令


注意:本文經過原作者授權轉譯,轉載請標明出處

原文地址:http://mrjester.hapisan.com/04_MC68/Sect03Part05/Index.html

條件允許建議閱讀原文,網上非中文資料還是較多,當作鍛煉英文豈不美哉
翻譯若有不足之處歡迎批評指正

譯文:

"好朋友只能由偶然相遇的天性和諧的雙方組成,並不是想成為好朋友就能成為好朋友" ---- 佛

簡介

直到第三章的目前為止,我們已經學習了一系列以字節長字為單位的對二進制數據的修改指令。那么如果你想要修改數據中的某一而不是好幾該怎么辦呢?

接下來的三個指令就是為這個疑問而設計的,請留意它們有着非常相似的使用規則,所以它們在匯編的時候是歸於一類的

BSET 指令

BSET - 設置某個位為1

這條指令會把目的操作數中的某一位設置成1,具體是哪一位取決於源操作數

例子

匯編程序可能會對這些指令的使用比較挑剔,讓我們先來康康一個在數據寄存器上使用這條指令的例子:

    bset.l     #$0E, d0

我們知道數據寄存器d0中是一個長字的內容 (32 ):

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

如你所見,在指令執行前,數據寄存器d0中的32全是0,上面的每個數字表示每一

在上面的例子里,源操作數0E,所以d00E位會被設置成1

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

此時d0的內容是00004000 (二進制表示為:0000 0000 0000 0000 0100 0000 0000 0000)

差不多就是這么簡單,不過我們再康一個例子加深下理解:(假設d0的內容現在還是00004000)

    bset.l     #$01, d0

這條指令會把d0的第01設置為1:

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0

現在d0的內容變成了00004002 (二進制表示為:0000 0000 0000 0000 0100 0000 0000 0010)

當然了,源操作數的內容可以是一個大於1F的值,那么此時指令會怎么執行呢?比如:

    bset.l     #$27, d0

由於最高位是第1F位,所以任何更高的位都會從00重新計算,比如20會變成0021會變成0122會變成02等等,所以對於上面這條指令:

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0

07位被設置為1,任何更高位都會重新計算 (事實上,這條指令只讀取了源操作數的后5位因為二進制中5位可以表示00-1F)

注意 如果目的操作數是一個數據寄存器 (就像上面例子列出的那樣),那么長度必須是長字 (.l),你不能對數據寄存器使用字節或是長度

現在讓我們再康康這條指令用在內存上的例子:

    bset.b     #$04, $000009C8

先看看指令執行前內存的內容:

偏移量 0 1 2 3 4 5 6 7 8 9 A B C D E F
...
000009A0 00 00 00 00 00 00 00 00 00 00 00 00 43 55 4E 54
000009B0 00 00 FE DC 00 00 00 00 00 00 00 00 00 00 00 00
000009C0 00 00 00 00 00 00 00 03 40 3F 00 00 00 00 00 00
000009D0 10 20 79 2A B2 00 00 00 00 00 00 00 00 00 00 00
...

內存中地址為$000009C8的內容是40,換算成二進制就是0100 0000

  07 06 05 04 03 02 01 00
40 0 1 0 0 0 0 0 0

因為源操作數04,所以把第04位設為1

  07 06 05 04 03 02 01 00
50 0 1 0 1 0 0 0 0

結果變成了50,然后存入到內存中去:

偏移量 0 1 2 3 4 5 6 7 8 9 A B C D E F
...
000009A0 00 00 00 00 00 00 00 00 00 00 00 00 43 55 4E 54
000009B0 00 00 FE DC 00 00 00 00 00 00 00 00 00 00 00 00
000009C0 00 00 00 00 00 00 00 03 50 3F 00 00 00 00 00 00
000009D0 10 20 79 2A B2 00 00 00 00 00 00 00 00 00 00 00
...

同樣的對於內存的操作,如果源操作數大於07,它將會從00開始重新算,08變成0009變成010A變成02等等

注意 如果目的操作數是一個內存地址,或是通過地址寄存器獲得的內存地址,那么長度必須是字節 (.b),你不能對內存地址使用或是長字長度

同時源操作數可以是立即數:

    bset.l     #$00, d0

也可以是數據寄存器:

    bset.l     d2, d0

不能是一個內存地址,或是通過地址寄存器獲得的內存地址,或是直接一個地址寄存器,比如下面這些錯誤的示范:

    bset.l     a0, d0         
    bset.l     (a0), d0       
    bset.l     $20(a0), d0    
    bset.l     (a0)+, d0      
    bset.l     -(a0), d0      
    bset.l     $00FF8010, d0  

目的操作數可以是數據寄存器或是內存地址 ,或是通過地址寄存器獲得的內存地址:

    bset.l     #$00, d0
    bset.b     #$00, $00FF8010
    bset.b     #$00, (a0)
    bset.b     #$00, $20(a0)
    bset.b     #$00, (a0)+
    bset.b     #$00, -(a0)

但是不能是一個地址寄存器:

    bset.l     #$00, a0       

接下來你會發現另兩個指令BCLRBCHG也有着相同的規則。

BCLR 指令

BCLR - 擦除某個位為0

這條指令會把目的操作數中的某一位擦除成0,具體是哪一位取決於源操作數

例子

bset指令幾乎相同,除了僅僅一點:

    bclr.l     #$0E, d0

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1

它會把那一擦除成0而不是設置為1,除此之外無任何區別,我想在這里就不贅述了

BCHG 指令

BCHG - 翻轉某個位

這條指令會把目的操作數中的某一位做翻轉,如果是0就會變成1,如果是1就會變成0,具體是哪一位取決於源操作數

例子

同樣的規則,除了一點,比如d0原本內容是480E072C:

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 0 1 1 0 0

然后執行完下面這條指令后:

    bchg.l     #$07, d0

因為d0中第07原本是0,所以執行后會變成1:

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0

如果此時再執行下面這條指令:

    bchg.l     #$1B, d0

因為d0中第1B原本是1,所以執行后會變成0:

1F 1E 1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00
0 1 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0

所以現在d0的內容是400E07AC

如你所見,上面原本是0 (擦除) 的被修改成了1,而原本是1 (設置) 的被修改成了0,就是這么簡單

除了這些,別的規則和bsetbclr完全一樣

家庭作業

現在我們已經學習了主要的位指令,讓我們來康一個測試吧:

    move.b     #$24, d0
    bclr.l     #$02, d0
    ori.b      #$03, d0
    move.b     #$F8, d1
    and.b      d0, d1
    not.w      d1
    eori.w     #$FF00, d1
    move.b     d1, $00002200
    bset.b     #$05, $00002200
    bchg.b     #$01, $00002200

所有寄存器的初始值都是00000000,你的任務就是算出內存中地址為00002200處的字節是什么,像往常一樣,答案在下一節,看之前先自己捋一遍哦

目錄
上一篇:[轉譯][馬基 傑斯特(MarkeyJester) 摩托羅拉68000 入門教程] 叄 - 位 指令 | 4. EOR 指令
下一篇:[轉譯][馬基 傑斯特(MarkeyJester) 摩托羅拉68000 入門教程] 叄 - 位 指令 | 6. 家庭作業答案 - 3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM