<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      咸魚(yú)暄

      咸魚(yú)暄的學(xué)習(xí)空間!

      導(dǎo)航

      匯編語(yǔ)言入門(mén)學(xué)習(xí) | 2 - 匯編語(yǔ)言代碼基本結(jié)構(gòu)

      從一個(gè)例子開(kāi)始

      根據(jù)個(gè)人習(xí)慣,我更愿意從一個(gè)實(shí)例開(kāi)始某種語(yǔ)言的學(xué)習(xí)。


      這里以一個(gè) 16 位匯編程序?yàn)槔?br>我們?cè)?xp 虛擬機(jī)中新建文件 hello.asm,用記事本編輯:

       1 data segment
       2 abc db "hello, world!", 0Dh, 0Ah, "$"
       3 data ends
       4 ;這是一條注釋
       5 code segment
       6 assume cs:code, ds:data
       7 main:
       8   mov ax, data
       9   mov ds, ax
      10   mov ah, 9
      11   mov dx, offset abc
      12   int 21h
      13   mov ah, 4Ch
      14   int 21h
      15 code ends
      16 end main
      


      將其放在 \Masm 目錄中。該目錄中同時(shí)包含了 LINK.EXE 以及 MASM.EXE。我們?cè)?command 中進(jìn)入對(duì)應(yīng)目錄,輸入指令:

      masm hello;
      link hello;
      hello
      

      我們通過(guò)運(yùn)行 masm.exe 來(lái)編譯 hello[.asm],然后通過(guò) link.exe 來(lái)連接 hello[.obj],最后運(yùn)行 hello[.exe]。結(jié)果顯示: hello, world!


      下面,我們對(duì)代碼進(jìn)行逐句解析:

        • 對(duì)于 8086PC 機(jī),在編程時(shí)可以根據(jù)需要將一組內(nèi)存單元定義為一個(gè)段(機(jī)器語(yǔ)言代碼也存儲(chǔ)在內(nèi)存中)。例如第 1 行和第 5 行就分別定義了名為 data 的段和名為 code 的段。第 3 行和第 15 行分別是這兩個(gè)段的結(jié)束。

        • 8086CPU 要求每個(gè)段的容量不能超過(guò) 64KB。這與計(jì)算機(jī)的尋址方式有關(guān):

          • 計(jì)算機(jī)對(duì)內(nèi)存的編碼是線性的。例如內(nèi)存為 256M,則地址就應(yīng)該為 0~(256M-1) 。這個(gè)地址稱為 物理地址 或 絕對(duì)地址 。
          • 8086CPU 可以傳送 20 位的地址 0~(1M-1),但是由于 8086CPU 是 16 位結(jié)構(gòu)的,因此如果采用簡(jiǎn)單的方法傳遞物理地址,那么它的尋址能力只有 0~(64K-1)。因此 8086CPU 采用兩個(gè) 16 位地址合成的方法來(lái)形成一個(gè) 20 位的物理地址。比如 12ABh:34DEh 就是一個(gè)地址(其中 12ABh 表示 16 進(jìn)制下的 12AB。匯編語(yǔ)言中用末尾的一個(gè) h 來(lái)表示 16 進(jìn)制數(shù)。匯編語(yǔ)言中數(shù)字的表示不區(qū)分大小寫(xiě)。如果一個(gè) 16 進(jìn)制數(shù)是字母開(kāi)頭的,則需要在它前面增寫(xiě)一個(gè) 0,如 ABCDh 應(yīng)寫(xiě)為 0ABCDh,因?yàn)樽帜搁_(kāi)頭的字符串表示的是變量的名稱),它由兩個(gè) 16 位的地址組成,分別稱為 段地址 (Segment) 和 偏移地址 (Offset)。這樣表示的地址稱為 邏輯地址 。
          • 地址加法器采用 物理地址 = 段地址 * 16 + 偏移地址 的方法合成物理地址。
          • 需要說(shuō)明的是,同一個(gè)物理地址可以表示成多個(gè)邏輯地址。如 123BC = 123B:000C = 122A:011C。
          • 因此,我們?nèi)绻?段地址:偏移地址 的方式尋址,偏移地址的范圍為 0h~FFFFh,即 10000h 個(gè)字節(jié),即 64KB。
        • 偽指令

          • 在匯編語(yǔ)言源程序中,包含 2 種指令,一種是匯編指令,一種是偽指令。匯編指令是與機(jī)器碼一一對(duì)應(yīng)的,而偽指令由編譯器來(lái)執(zhí)行,編譯器會(huì)進(jìn)行相關(guān)的編譯工作。
          • 例如,segment 和 ends 就是一對(duì)成對(duì)使用的偽指令。
      • 定義數(shù)組

        • 第 2 行 abc db "hello, world!", 0Dh, 0Ah, "$" 定義了一個(gè)字節(jié)類型的變量(db: define byte,byte 類型實(shí)際上等價(jià)于 C 語(yǔ)言中的 char 類型),名為 abc,內(nèi)容為 "hello, world!", 0Dh, 0Ah, "$" ,相當(dāng)于 C 語(yǔ)言中的 char abc[] = "hello, world!\x0D\x0A$"; ,即逗號(hào)隔開(kāi)的內(nèi)容會(huì)被連接成一個(gè)變量。其中 0Dh, 0Ah 分別是回車(光標(biāo)回到行首)和換行(光標(biāo)向下移動(dòng)一行)的 ASCII 碼。在匯編語(yǔ)言中,$ 是字符串結(jié)束的標(biāo)志。

        • 我們可以通過(guò) ans db 100 dup(0) 定義一個(gè)定長(zhǎng)的數(shù)組,相當(dāng)于 C 語(yǔ)言中的 char ans[100] = {0}; 。dup 是 duplicate 的簡(jiǎn)寫(xiě),表示重復(fù)。我們可以通過(guò)這種方法來(lái)取得內(nèi)存空間存放數(shù)據(jù)。

        • 匯編語(yǔ)言將所有的變量定義放在一起,即 data segment 區(qū)域中。

        • 類似地,我們可以用 dw(define word) 定義字型數(shù)據(jù)(16位)。

      • 注釋 

        • 如第 4 行,匯編語(yǔ)言源代碼中,可以用分號(hào) ; 表示本行中后面的內(nèi)容均為注釋。這與 C 中的 // 類似。
      • 寄存器

        • CPU 本身只負(fù)責(zé)運(yùn)算,不負(fù)責(zé)存儲(chǔ)數(shù)據(jù)。數(shù)據(jù)一般存放在存儲(chǔ)器中,CPU 需要使用數(shù)據(jù)時(shí)就會(huì)去存儲(chǔ)器中調(diào)用數(shù)據(jù)。然而,CPU 的運(yùn)算速度遠(yuǎn)高于內(nèi)存的讀寫(xiě)速度,因此為了提高效率,CPU 自帶緩存和 寄存器 (register)。緩存可以看做讀寫(xiě)速度較快的內(nèi)存,而寄存器是 "fastest, smallest and most expensive" 的,用來(lái)存儲(chǔ)最常用的數(shù)據(jù)。

        • 寄存器不依靠地址區(qū)分?jǐn)?shù)據(jù),而依靠名稱。每一個(gè)寄存器都有自己的名稱。
          8086CPU 有 14 個(gè)寄存器,分別為 AX, BX, CX, DX, SI, DI, SP, BP, IP, CS, SS, DS, ES, PSW,它們都是 16 位的。

        • 本文中,我們用加括號(hào)的寄存器名稱來(lái)表示寄存器中存儲(chǔ)的數(shù)據(jù)。例如, (ax) 表示 ax 寄存器中存儲(chǔ)的數(shù)據(jù)。

        • AX, BX, CX, DX 這 4 個(gè)寄存器通常用來(lái)存放一般性數(shù)據(jù),稱為 通用寄存器 。為了與上一代 CPU 兼容,每個(gè)通用寄存器都可以拆成兩個(gè) 8 位寄存器獨(dú)立使用,如 AX 可拆分為 AH 和 AL,BX 拆分為 BH 和 BL 等。H 和 L 分別表示高 8 位和低 8 位。
          計(jì)算機(jī)存儲(chǔ)信息的基本單位是一個(gè) 二進(jìn)制位(bit),一位可存儲(chǔ)一個(gè)二進(jìn)制數(shù) 0 或 1。每 8 位組成一個(gè) 字節(jié)(Byte)。每?jī)蓚€(gè)字節(jié)組成一個(gè) 字(word),這兩個(gè)字節(jié)分別稱為高位字節(jié)和低位字節(jié)。

        • 代碼段寄存器 CS(code segment) 和指令指針寄存器 IP(Instruction Pointer) 是 8086CPU 中最關(guān)鍵的兩個(gè)寄存器。它們分別用來(lái)提供當(dāng)前指令的段地址和偏移地址。即任意時(shí)刻,8086CPU 將 CS:IP 指向的內(nèi)容當(dāng)做命令執(zhí)行。每條指令進(jìn)入指令緩沖器后、執(zhí)行前,IP += 所讀取指令的長(zhǎng)度,從而指向下一條指令。

        • 其余寄存器將在用到時(shí)再做記錄。

      • 偽指令 assume

        • 第 6 行 assume cs:code, ds:data 將段寄存器和段名建立了關(guān)系。即 assume 使得段寄存器儲(chǔ)存了對(duì)應(yīng)段的段地址。
      • 標(biāo)號(hào) 

        • 第 7 行 main: 是一個(gè)標(biāo)號(hào)。標(biāo)號(hào)在程序中的主要用途是方便跳轉(zhuǎn)語(yǔ)句的執(zhí)行。跳轉(zhuǎn)語(yǔ)句將在后面再做學(xué)習(xí)。
      • 傳送指令 mov 

        • 傳送指令 mov 的一般格式為 mov A, B ,用于將 B 的內(nèi)容賦給 A(如果合法)。
        • 傳送指令在本文文末專門(mén)記錄。
      • offset 

        • 操作符 offset 的功能是取得標(biāo)號(hào)的偏移地址。第 11 行 mov dx, offset abc  的作用就是將 abc 的偏移地址賦給 dx。 
      • 中斷 

        • 第 12 和 14 行的 int 21h 調(diào)用了中斷。中斷在本文文末專門(mén)記錄。
        • 在這里,mov ah, 9;mov dx, offset abc;int 21h 調(diào)用了中斷 21h 的 09h 號(hào)功能,實(shí)現(xiàn)了對(duì)字符串 abc 的輸出。中斷 21h 的 09h 號(hào)功能實(shí)現(xiàn)的是:將自 ds:dx 開(kāi)始、到 '$' 為止的字符串輸出到標(biāo)準(zhǔn)輸出設(shè)備上。
        • 程序返回:每個(gè)可執(zhí)行文件的類型都來(lái)自于某一個(gè)正在運(yùn)行的程序的調(diào)用。可執(zhí)行文件運(yùn)行完畢后,它要將 CPU 的控制權(quán)交還給調(diào)用它的程序,這個(gè)過(guò)程稱為程序返回。 mov ah, 4Ch   int 21h 完成的就是這個(gè)過(guò)程。
      • end 

        • end 指令用于通知編譯器:程序運(yùn)行結(jié)束了。
        • 在 end 后面加上一個(gè)標(biāo)號(hào),如 end main,則在起到上述效果的同時(shí)還會(huì)通知編譯器程序的入口在什么地方(即偏移地址)。即,程序的入口由 end 指出。在本代碼中,程序自標(biāo)號(hào) main 開(kāi)始運(yùn)行。

      mov 指令(傳送指令)

      將數(shù)據(jù)直接送入寄存器

      指令 mov ax, 4E20h 表示將 4E20h 送入寄存器 AX。等價(jià)于高級(jí)語(yǔ)言中的 AX = 4E20h; (此后文中會(huì)大量使用高級(jí)語(yǔ)言的語(yǔ)法描述匯編指令)。

      將一個(gè)寄存器中的內(nèi)容送入另一個(gè)寄存器

      類似地, mov ax, bx 表示 AX = BX; 。

      將一個(gè)內(nèi)存單元中的內(nèi)容送入一個(gè)寄存器

      之前我們提到,8086CPU 中的地址由段地址和偏移地址組成。8086CPU 中有一個(gè) DS 寄存器(段寄存器),用來(lái)存放要訪問(wèn)數(shù)據(jù)的段地址。
      例如,我們要讀取 10000h 單元的內(nèi)容,可以用以下的程序段進(jìn)行:

        mov bx, 1000h
        mov ds, bx
        mov al, [0]
      

      上面的三條指令將 10000h (1000:0) 中的數(shù)據(jù)讀到了 al 中。可見(jiàn),我們可以通過(guò) mov register, [ address ] 的方式來(lái)將內(nèi)存中 DS:address 的數(shù)據(jù)讀到合法的寄存器 register 中。
      值得注意的是,我們通過(guò) 1,2 兩行將 1000h 放入了 DS,這是因?yàn)?8086CPU 不支持將數(shù)據(jù)直接送入段寄存器(ds, ss, cs, es)的操作。


      我們還可以顯式地規(guī)定我們調(diào)用的內(nèi)存地址的段地址,如我們可以用 ds:[0] 來(lái)表示我們調(diào)用的內(nèi)存單元為 ds:0。這允許了我們使用 ds 以外的段地址。這樣的 "ds:" "cs:" 等被稱為 段前綴。邏輯地址中的偏移地址可以用常數(shù)表示,但是段地址必須用段寄存器表示。


      另外,我們可以通過(guò) [bx] 表示內(nèi)存單元 ds:bx,即段地址由 ds 提供,偏移地址由 bx 提供。
      需要注意的是,8086CPU 中只有 bx, si, di, bp 這四個(gè)寄存器可以用來(lái)在 [] 中進(jìn)行內(nèi)存單元的尋址,其他寄存器進(jìn)行這樣的操作都是非法的。
      同時(shí),在 [] 中,這四個(gè)寄存器只能單獨(dú)出現(xiàn)或以 bx, si / bx, di / bp, si / bp, di 的組合出現(xiàn),如 [bx+si+1] 是合法的,而 [bx+bp] 就是非法的。兩個(gè)寄存器只能相加,不能相減
      只要在 [] 中用到寄存器 bp,而指令中沒(méi)有顯式給出段地址,那么段地址就默認(rèn)在 ss 中而不是 ds 中。


      由于 8086CPU 是 16 位結(jié)構(gòu),因此可以一次性傳送 16 位數(shù)據(jù)。比如:

      內(nèi)存情況:
      10000H 11
      10001H 22
      
      指令:
      mov ax, 1000h
      mov ds, ax
      mov ax, [0]
      
      結(jié)果:
      ax = 2211H
      

      這是因?yàn)椋覀儗?1000:0 處存放的字?jǐn)?shù)據(jù)(由兩個(gè)字節(jié)組成)送入 ax 時(shí),1000:0 處存放的是字?jǐn)?shù)據(jù)的低 8 位,即 11;1000:1 處存放的數(shù)字?jǐn)?shù)據(jù)的高 8 位,即 22。(小端規(guī)則:對(duì)于 8 位以上的變量,先存放低位,再存放高位,即低位的內(nèi)存地址低于高位的內(nèi)存地址。)執(zhí)行 mov 時(shí),字?jǐn)?shù)據(jù)的低 8 位送入 al,高 8 位送入 ah,因此 ax = 2211H。


      這也說(shuō)明,mov 操作的內(nèi)存單元的長(zhǎng)度由其他操作對(duì)象(寄存器)指出。但是,兩個(gè)不同長(zhǎng)度的寄存器之間的傳遞是非法的,如 al 和 bx。


      另外,下面的代碼反映了一種常見(jiàn)的錯(cuò)誤:

      data segment
      xyz dw 1234h, 0ABCDh
      data ends
      ...... ;略去
          
      code segment
      ...... ;略去
      mov ax, xyz[1]
      ...... ;略去
      

      在 C 語(yǔ)言的理解中,short int xyz[2] = {1234h, 0ABCDh}; 定義出的數(shù)組,xyz[1] 的值應(yīng)該為 0ABCDh。而實(shí)際上在匯編語(yǔ)言中,xyz[1](即 [xyz + 1])指向的就是 xyz 物理地址 +1 的地址。假設(shè) xyz 地址為 10000H,那么內(nèi)存情況為(小端規(guī)則):

      10000h 10001h 10002h 10003h
        34     12     CD     AB
      

      實(shí)際上 xyz + 1 即 10001h,那么實(shí)際上程序認(rèn)為 mov ax, xyz[1] 調(diào)用了以 10001h 為低八位的 16 個(gè)字節(jié),根據(jù)小端規(guī)則,ax 被賦值為 0CD12h。
      因此,如果希望引用 0ABCDh,實(shí)際上要寫(xiě)的是 mov ax, xyz[2] 。這是需要特別注意的。


      中斷

      posted on 2020-04-15 00:14  咸魚(yú)暄  閱讀(716)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 国产精品成人午夜久久| 97免费人妻在线视频| 久久人妻无码一区二区三区av| 日韩精品成人网页视频在线| 久久久久久性高| 国产69精品久久久久人妻| 天堂网av最新版在线看| 日韩人妻无码一区二区三区| 亚洲精品无码成人A片九色播放| 欧美亚洲另类自拍偷在线拍 | 国产在线观看网址不卡一区| 国产伦码精品一区二区| 国产成人8X人网站视频| 精品无码国产污污污免费| 浮妇高潮喷白浆视频| 明光市| 久久国产精品精品国产色| 国产精品视频中文字幕| 亚洲精品蜜桃久久久久久| 伊人久久大香线蕉综合网站| 国产精品美女一区二三区| 人人做人人澡人人人爽| 国产无遮挡又黄又爽不要vip软件 国产成人精品一区二区秒拍1o | 日韩乱码卡一卡2卡三卡四 | 欧美成人aaa片一区国产精品| 成年女人免费碰碰视频| 免费的特黄特色大片| 国产97视频人人做人人爱| 奇米777四色影视在线看| 国产在线精品欧美日韩电影| 樱花草视频www日本韩国| 久久男人av资源站| 中文字幕有码无码AV| 四虎国产精品久久免费精品| 熟女人妻视频| 熟女人妻aⅴ一区二区三区电影 | 无码日韩精品一区二区三区免费 | 爆乳2把你榨干哦ova在线观看| 精品无码一区在线观看| 激情在线一区二区三区视频| 日本精品极品视频在线|