• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            luqingfei@C++

            為中華之崛起而崛起!
            兼聽則明,偏聽則暗。

            匯編語言--call和ret指令

             

            callret指令

            callret指令都是轉(zhuǎn)移指令,它們都修改IP,或同時修改CSIP。

            它們經(jīng)常被共同用來實(shí)現(xiàn)子程序的設(shè)計。

             

            retretf

            ret指令用棧中的數(shù)據(jù),修改IP的內(nèi)容,從而實(shí)現(xiàn)近轉(zhuǎn)移;

            retf指令用棧中的數(shù)據(jù),修改CSIP的內(nèi)容,從而實(shí)現(xiàn)遠(yuǎn)轉(zhuǎn)移。

            CPU執(zhí)行ret指令時,進(jìn)行下面的兩步操作:

            1(IP) = ((ss)*16 +(sp))

            2(sp) = (sp)+2

            CPU執(zhí)行retf指令時,進(jìn)行下面四步操作:

            1(IP) = ((ss)*16) + (sp)

            2(sp) = (sp) + 2

            3(CS) = ((ss)*16) + (sp)

            4(sp) = (sp) + 2


            用匯編語法來解釋retretf指令,則:

            CPU執(zhí)行ret指令時,相當(dāng)于進(jìn)行:

            pop IP

             

            CPU執(zhí)行retf指令時,相當(dāng)于進(jìn)行:

            pop IP

            pop CS

             

             

             

            call指令

            CPU執(zhí)行call指令時,進(jìn)行兩步操作:

            (1)       將當(dāng)前的IPCSIP壓入棧中;

            (2)       轉(zhuǎn)移。

             

            call指令不能實(shí)現(xiàn)短轉(zhuǎn)移,除此之外,call指令實(shí)現(xiàn)轉(zhuǎn)移的方法和jmp指令的原理相同。

             

             

            依據(jù)位移進(jìn)行轉(zhuǎn)移的call指令

            call 標(biāo)號(將當(dāng)前的IP壓棧后,轉(zhuǎn)到標(biāo)號處執(zhí)行指令)

            CPU執(zhí)行此種格式的call指令時,進(jìn)行如下的操作:

            1(sp) = (sp)-2

                 ((ss)*16 +(sp)) = (IP)

            2(IP) = (IP)+16位位移。

            16位位移=“標(biāo)號”處的地址-call指令后的第一個字節(jié)的地址;

            16位位移的范圍為-32768~32767,用補(bǔ)碼表示;

            16位位移由編譯程序在編譯時算出。

             

            用匯編語法來解釋此種格式的call指令,則:

            CPU執(zhí)行指令“call 標(biāo)號”時,相當(dāng)于進(jìn)行:

            push IP

            jmp near ptr 標(biāo)號

             

             

             

            轉(zhuǎn)移的目的地址在指令中的call指令

            前面講的call指令,其對應(yīng)的機(jī)器指令中并沒有轉(zhuǎn)移的目的地址,而是相對于當(dāng)前IP的轉(zhuǎn)移位移。

             

            指令“call far ptr 標(biāo)號”實(shí)現(xiàn)的是段間轉(zhuǎn)移。

            CPU執(zhí)行此格式的call指令時,進(jìn)行如下的操作:

            1(sp)=(sp)-2

                    ((ss)*16+(sp)) = (CS)

                    (sp)=(sp)-2

                  ((ss)*16+(sp)) = (IP)

            2(CS)=標(biāo)號所在段的段地址

                 (IP)=標(biāo)號在段中的偏移地址

             

            用匯編語法來解釋此種格式的call指令,則:

            CPU執(zhí)行指令“call far ptr 標(biāo)號”時,相當(dāng)于進(jìn)行:

            push CS

            push IP

            jmp far ptr 標(biāo)號

             

             

             

            轉(zhuǎn)移地址在寄存器中的call指令

            指令格式:call 16位寄存器

            功能:

            (sp) = (sp)-2

            ((ss)*16+(sp)) = (IP)

            (IP) = (16位寄存器)

             

            用匯編語法來解釋此種格式的call指令,CPU執(zhí)行call 16reg時,相當(dāng)于進(jìn)行:

            push IP

            jum 16位寄存器

             

             

             

            轉(zhuǎn)移地址在內(nèi)存中的call指令

            有兩種格式:

            1) call word ptr 內(nèi)存單元地址

            相當(dāng)于:

            push IP

            jum word ptr 內(nèi)存單元地址

            2) call dword ptr 內(nèi)存單元地址

            相當(dāng)于:

            push CS

            push IP

            jmp dword ptr 內(nèi)存單元地址

             

             

            callret的配合使用

            如何將它們配合使用來實(shí)現(xiàn)子程序的機(jī)制。

            子程序的框架如下:

            標(biāo)號:

                          指令

                          ret

             

            具有子程序的源程序的框架如下:

            assume cs:code

            code segment

                   main: …                              ;主程序

                           …

                           call sub1                     ;調(diào)用子程序sub1

                           …

                           mov ax,4c00h

                           int 21h

                   sub1: ….                             ;子程序sub1開始

                           …

                           call sub2                     ;調(diào)用子程序sub2

                           …

                           ret                              ;子程序返回

                   sub2: ….                             ;子程序sub2開始

                           …

                           ret                              ;子程序返回

            code ends

            end maint

             

             

             

             

            mul指令

            mul是乘法指令。

            使用mul做乘法的時候:

            1) 兩個相乘的數(shù):兩個相乘的數(shù),要么都是8位,要么都是16位。

            如果是8位,一個默認(rèn)放在AL中,別一個放在8位寄存器或內(nèi)存單元中;

            如果是16位,一個默認(rèn)在AX中,另一個放在16位寄存器或內(nèi)存單元中。

            2) 結(jié)果:如果是8位乘法,結(jié)果默認(rèn)放在AX中;如果是16位乘法,結(jié)果高位默認(rèn)在DX中存放,低位在AX中存放。

             

            格式如下:

            mul reg

            mul 內(nèi)存單元

             

             

             

            模塊化程序設(shè)計

            callret指令共同支持了匯編語言編程中的模塊化設(shè)計。

            在實(shí)際編程中,程序的模塊化是必不可少的。

            因為實(shí)現(xiàn)的問題比較復(fù)雜,對現(xiàn)實(shí)問題進(jìn)行分析時,把它轉(zhuǎn)化成為相互聯(lián)系、不同層次的子問題,是必須的解決方法。

            callret指令對這種分析方法提供了程序?qū)崿F(xiàn)上的支持。

            利用callret指令,我們可以用簡捷的方法,實(shí)現(xiàn)多個相互聯(lián)系、功能獨(dú)立的子程序來解決一個復(fù)雜的問題。

             

             

             

            參數(shù)和結(jié)果傳遞的問題

            子程序一般都要根據(jù)提供的參數(shù)處理一定的事務(wù),處理后,將結(jié)果(返回值)提供給調(diào)用者。

            其實(shí),我們討論參數(shù)和返回值傳遞的問題,實(shí)際上就是在探討,應(yīng)該如何存儲子程序需要的參數(shù)和產(chǎn)生的返回值。

             

            ;說明:計算N3次方

            ;參數(shù):(bx)=N

            ;結(jié)果:(dx:ax)=N^3

            cube:mov ax,bx

                   mul bx

                   mul bx

                   ret

            注意,編程時的良好風(fēng)格,應(yīng)有有詳細(xì)的注釋。包含對子程序的功能、參數(shù)和結(jié)果的說明。

             

            用寄存器來存儲參數(shù)和結(jié)果是最常使用的方法。對于存放參數(shù)的寄存器和存放結(jié)果的寄存器,調(diào)用者和子程序的讀寫操作恰恰相反:調(diào)用者將參數(shù)送入?yún)?shù)寄存器,從結(jié)果寄存器中取到返回值;子程序從參數(shù)寄存器中取到參數(shù),將返回值送入結(jié)果寄存器。

             

             

             

            批量數(shù)據(jù)的傳遞

            寄存器的數(shù)量終究有限,我們不可能簡單地用寄存器來存放多個需要傳遞的數(shù)據(jù)。對于返回值,也有同樣的問題。

             

            在這種時候,我們將批量數(shù)據(jù)放到內(nèi)存中,然后將它們所在內(nèi)存空間的首地址放在寄存器中,傳遞給需要的子程序。對于具有批量數(shù)據(jù)的返回結(jié)果,也可用同樣的方法。

             

            除了用寄存器傳遞參數(shù)外,還有一種通用的方法是用棧來傳遞參數(shù)。

             

             

            寄存器沖突的問題

            一個一般化的問題,子程序中使用的寄存器,很可能在主程序中也要使用,造成了寄存器使用上的沖突。

            那么我們?nèi)绾蝸肀苊膺@種沖突呢?粗略地看,可以有兩個方案:

            1) 在編寫調(diào)用子程序的程序時,注意看看子程序中有沒有用到會產(chǎn)生沖突的寄存器,如果有,調(diào)用者使用別的寄存器;

            2) 在編寫子程序的時候,不要使用會產(chǎn)生沖突的寄存器。

            以上兩個方案,不具可行性,第一種給調(diào)用子程序的程序的編寫造成很大麻煩。第二種不可能實(shí)現(xiàn),子程序無法知道將來的調(diào)用情況。

             

            我們希望:

            1) 編寫調(diào)用子程序的程序的時候不必關(guān)心子程序到底使用了哪些寄存器;

            2) 編寫子程序的時候不必關(guān)心調(diào)用者使用了哪些寄存器;

            3) 不會發(fā)生寄存器沖突。

             

            解決這個問題的簡捷方法是,在子程序的開始將子程序中所有用到的寄存器中的內(nèi)容都保存起來,在子程序返回前再恢復(fù)。我們可以用棧來保存寄存器中的內(nèi)容。

             

            以后,我們編寫子程序的標(biāo)準(zhǔn)框架如下:

            子程序開始:子程序中使用的寄存器入棧

                                 子程序內(nèi)容

                                 子程序中使用的寄存器出棧

                                 返回(ret、retf

             

            要注意寄存器入棧和出棧的順序。

             

             

            實(shí)驗10 編寫子程序

            1、 顯示字符串

            問題:顯示字符串是現(xiàn)實(shí)工作中經(jīng)常要用到的功能,應(yīng)該編寫一個通用的子程序來實(shí)現(xiàn)這個功能。我們應(yīng)該提供靈活的調(diào)用接口,使調(diào)用者可以決定顯示的位置(行、列)、內(nèi)容和顏色。

            子程序描述

            名稱:show_str

            功能:在指定的位置,用指定的顏色,顯示一個用0結(jié)束的字符串。

            參數(shù):(dh)=行號(取值范圍0~24),(dl)=列號(取值范圍0~79),

                     (cl)=顏色,ds:si指向字符串的首地址

            返回:無

            應(yīng)用舉例:在屏幕的83列,用綠色顯示data段中的字符串。

             

            1) 子程序的入口參數(shù)是屏幕上的行號和列號,注意在子程序內(nèi)部要將它們轉(zhuǎn)化為顯存中的地址,首先要分析一下屏幕上的行列位置和顯存地址的對應(yīng)關(guān)系。

            2) 注意保存子程序中用到的相關(guān)寄存器。

            3) 空上子程序的內(nèi)部處理和顯存的結(jié)構(gòu)密切相關(guān),但是向外提供了與顯存結(jié)構(gòu)無關(guān)的接口。通過調(diào)用這個子程序,進(jìn)行字符串的顯示時可以不必了解顯存的結(jié)構(gòu),為編程提供了方便。在實(shí)驗中,注意體會這種設(shè)計思想。

             

            2、 解決除法溢出的問題

            問題:div指令可以做除法。當(dāng)進(jìn)行8位除法的時候,用al存儲結(jié)果的商,ah存儲結(jié)果的余數(shù);進(jìn)行16位除法的時候,用ax存儲結(jié)果的商,dx存儲結(jié)果的余數(shù)。可是,現(xiàn)在有一個問題,如果結(jié)果的商大于ahax所能存儲的最大值,那么將如何?

             

            當(dāng)CPU執(zhí)行div等除法指令的時候,如果發(fā)生結(jié)果數(shù)據(jù)超出了寄存器所能存儲的范圍,將引發(fā)CPU的一個內(nèi)部錯誤,這個錯誤被稱為:除法溢出。

             

            子程序描述

            名稱:divdw

            功能:進(jìn)行不會產(chǎn)生溢出的除法運(yùn)算,被除數(shù)為dword型,除數(shù)為word型,結(jié)果為dword型。

            參數(shù):(ax)=dword型數(shù)據(jù)的低16

                     (dx)=dword型數(shù)據(jù)的高16

                     (cx)=除數(shù)

            返回:(dx)=結(jié)果的高16位,(ax)=結(jié)果的低16

                     (cx)=余數(shù)

            應(yīng)用舉例:計算1000000/10F4240H/0AH

             

            3、 數(shù)值顯示

            問題:編程:將data段中的數(shù)據(jù)以十進(jìn)制的形式顯示出來。

            數(shù)據(jù)在內(nèi)存中都是二進(jìn)制信息,標(biāo)記了數(shù)值的大小。要把它們顯示到屏幕上,成為我們能夠讀懂的信息,需要進(jìn)行信息的轉(zhuǎn)化。

            比如,數(shù)值12666,在機(jī)器中存儲為二進(jìn)制信息:11000101111010B317AH),計算機(jī)可以理解它。而我們要在顯示器上讀到可以理解的數(shù)值12666,我們看到的應(yīng)該是一串字符:“12666”,由于顯卡遵循的是ASCII編碼,為了讓我們能在顯示器上看到這串字符,它在機(jī)器中應(yīng)以ASCII碼的形式存儲為:31H、32H、36H、36H、36H(字符“0~9”對應(yīng)的ASCII碼為30H~39H)。

             

            通過上面的分析可以看到,在概念世界中,有一個抽象的數(shù)據(jù)12666,它表示了一個數(shù)值的大小。在現(xiàn)實(shí)世界中它可以有多種表示形式,可以在電子機(jī)器中以高低電平(二進(jìn)制)的形式存儲,也可以在紙上、黑板上、屏幕上以人類的語言“12666”來書寫?,F(xiàn)在,我們面臨的問題就是,要將同一抽象的數(shù)據(jù),從一種表示形式轉(zhuǎn)化為另一種表示形式。

             

            要將數(shù)據(jù)用十進(jìn)制形式顯示到屏幕上,要進(jìn)行兩步工作:

            1) 將用二進(jìn)制信息存儲的數(shù)據(jù)轉(zhuǎn)變?yōu)槭M(jìn)制形式的字符串;

            2) 顯示十進(jìn)制形式的字符串。

             

            子程序描述

            名稱:dtoc

            功能:將word型數(shù)據(jù)轉(zhuǎn)變?yōu)楸硎臼M(jìn)制數(shù)的字符串,字符串以0為結(jié)尾符。

            參數(shù):(ax)=word型數(shù)據(jù)

                     ds:si指向字符串的首地址

            返回:無

             

            應(yīng)用舉例:編程,將數(shù)據(jù)12666以十進(jìn)制的形式在屏幕的83列,用綠色顯示出來。

             

            分析:要得到字符串“12666”,就是要得到一列表示該字符串的ASCII碼:31H32H36H36H、36H

            十進(jìn)制數(shù)碼字符對應(yīng)的ASCII=十進(jìn)制數(shù)碼值+30H。

            要得到表示十進(jìn)制數(shù)的字符串,先求十進(jìn)制數(shù)每位的值。

            例如,對于12666,先求得每位的值:12、6、6、6。再將這些數(shù)分別加上30H,便得到了表示12666ASCII碼串,31H32H、36H、36H36H。

            那么,怎樣得到每位的值呢?采用下列方法(除10取余法):

                         12666/10=1266……6

                             1266/10=126……..6

                        126/10=12………6

                         12/10=1………..2

                          1/10=0………..1

            可見,用1012666,共除5次,記下每次的余數(shù),就得到了每位的值。

            綜合以上分析,可得出處理過程如下:

            12666除以10,循環(huán)5次,記下每次的余數(shù);將每次的余數(shù)分別加30H,使得到了表示十進(jìn)制數(shù)的ASCII碼串。

            只要是除到商為0,各位的值就已經(jīng)全部求出。可以使用jcxz指令來實(shí)現(xiàn)相關(guān)的功能。

             

            posted on 2010-08-04 10:32 luqingfei 閱讀(24447) 評論(0)  編輯 收藏 引用 所屬分類: 匯編語言基礎(chǔ)學(xué)習(xí)

            導(dǎo)航

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            統(tǒng)計

            留言簿(6)

            隨筆分類(109)

            隨筆檔案(105)

            Blogers

            Game

            Life

            NodeJs

            Python

            Useful Webs

            大牛

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            欧美va久久久噜噜噜久久| 久久国产精品一区| 色青青草原桃花久久综合| 精品久久久久久无码人妻热| 狠狠色丁香久久综合婷婷| 国内精品久久久久伊人av| 色8久久人人97超碰香蕉987| 久久夜色精品国产噜噜麻豆| 综合人妻久久一区二区精品| 久久这里都是精品| 亚洲AV日韩精品久久久久久| 久久婷婷成人综合色综合| 91视频国产91久久久| 免费国产99久久久香蕉| 精品久久人人做人人爽综合| 久久久久女教师免费一区| 少妇久久久久久被弄到高潮| 免费无码国产欧美久久18| 精品无码久久久久久尤物| 一级做a爰片久久毛片人呢| 香蕉久久AⅤ一区二区三区| 亚洲国产精品无码久久SM| 韩国免费A级毛片久久| 久久精品国产精品亚洲| 狠狠综合久久AV一区二区三区| 成人妇女免费播放久久久| 久久www免费人成看国产片| 亚洲熟妇无码另类久久久| 久久99中文字幕久久| 青青青青久久精品国产h久久精品五福影院1421| 久久综合色之久久综合| 奇米综合四色77777久久| 久久国产精品偷99| 久久男人Av资源网站无码软件| 国内精品伊人久久久久网站| 99精品久久精品一区二区| 狠狠色综合久久久久尤物| 亚洲AV日韩AV永久无码久久| 久久青青国产| 久久综合狠狠综合久久激情 | 亚洲熟妇无码另类久久久|