一文读懂汇编程序的多个分段的程序--详解
生活随笔
收集整理的這篇文章主要介紹了
一文读懂汇编程序的多个分段的程序--详解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
先貼上程序
首先要知道cpu是不知道到底哪里的數據是代碼 那里是數據那里是堆棧因此實現這些要靠程序員來告訴CPU
當然還有小小的匯編程序:匯編中的嵌套循環
下面是程序的分段詳解
開頭 assume cs:code,ds:data,ss:stack 假設程序分別有 代碼段 數據段 堆棧段 assume 假設 聲明一個數據段 data segmentdw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdata ends 聲明一個堆棧段 stack segmentdw 0,0,0,0,0,0,0,0stack ends 聲明一個代碼段 code segment ;代碼段的開始start: mov ax, stack ;程序的 ip指針會指向 start初;因為8086cpu不允許將數據直接送入段寄存器中因此使用通用寄存器進行mov ss, ax ;也就是相當于將stack中的數據送入到ss中mov sp, 20h ;因為數據和堆棧占用了32個字節的大小一次sp堆棧的指針指向32處mov ax,data ;通過寄存器ax將數據段的地址賦值給ds即段寄存器mov ds,axmov bx, 0mov cx,8 ;在循環的時候cx就是循環的計數器 每次循環就會將cx的數值進行減一直到為零為止s: push [bx] ;該語句說的是將ds中的數據進棧也就相當于使用push ds:[bx] (說明push 是對堆棧的操作也就是push和pop會對堆棧進行操作)具體見文下注釋;實現的過程就是將數據段中的數據壓入堆棧 ,也就是對ss:sp指向的數據進行操作add bx, 2loop s //跳到s處進行循環mov bx, 0mov cx,8s0: pop [bx]add bx,2loop s0mov ax, 4c00H ;加上下一句實現程序的返回int 21H code ends ;代碼段結束 end start //整段程序結束注釋:push-pop
堆棧操作指令 PUSH和POP格式: PUSH OPRD---- POP OPRD功能: 實現壓入操作的指令是PUSH指令;實現彈出操作的指令是POP指令.---- 說明: 1. OPRD為16位(字)操作數,可以是寄存器或存儲器操作數.----2. PUSH的操作過程是: (SP)<--(SP)-2,((SP))<--OPRD 即先修改堆棧指針SP(壓入時為自動減2),然后,將指定的操作數送入新的棧頂位置.此處的((SP))<--OPRD,也可以理解為:[(SS)*16+(SP)]<--OPRD 或 [SS:SP]<--OPRD3. 示例: PUSH DXPUSH BPPUSH CSPUSH DATA1PUSH ALFA[BX][SI]注意: 每進行一次壓入操作,都壓入一個字(16位).4. PUSH和POP指令對狀態標志位沒有影響。5. 什么是堆棧堆棧被定義為一種先進后出的數據結構,即最后進棧的元素將被最先彈出來.這很像許多人進入一條窄得只能容納一個人通過的小道,如果要從這條道往回退出 來的話,那么最先退出來的人是最后一個進入小道的人.知識小百科:
數據傳送指令 MOV格式: MOV OPRD1,OPRD2----功能: 本指令將一個源操作數送到目的操作數中,即OPRD1<--OPRD2.----說明: 1. OPRD1 為目的操作數,可以是寄存器、存儲器、累加器.---- OPRD2 為源操作數,可以是寄存器、存儲器、累加器和立即數.2. MOV 指令以分為以下四種情況:<1> 寄存器與寄存器之間的數據傳送指令示例: MOV AX,BXMOV DS,AXMOV BP,SI注意: 代碼段寄存器CS及指令指針IP不參加數的傳送,其中CS可以作為源操作數參加傳送,但不能作為目的操作數參加傳送.<2> 立即數到通用寄存器數據傳送指令立即數只能作源操作數使用,不能作目的操作數.示例: MOV AL,25MOV SI,OFFSET DATA1注意: 由于傳送的數據可能是字節,也可能是字,源操作數與目的操作數的類型應一致。<3> 寄存器與存儲器之間的數據傳送指令示例: MOV AL,BUFFERMOV AX,[SI]MOV LAST[BX+DI],DLMOV SI,ES:[BP]<4> 立即數到存儲器的數據傳送示例: MOV ALFA,24MOV DS:MEMS[BP],300AHMOV BYTE PTR[SI],15MOV LAST[BX][DX],0FFH3. 本指令不影響狀態標志位.4. MOV指令執行時的數據傳送方向.<1> 立即數只能作為源操作數,不允許作目的操作數,立即數也不通送至段寄存 器.<2> 通用寄存器可以與段寄存器,存儲器互相傳送數據,寄存器之間也可以互相 傳送.但CS段不能作為目的操作數.<3> 值得再次強調的是存儲器與存儲器之間不能進行數據直接傳送.若要實現 存儲單元間的數據傳送,可以借助于通用寄存器作為中介來進行. 加法指令 ADD(Addition)格式: ADD OPRD1,OPRD2----功能: 兩數相加----說明: 1. OPRD1為任一通用寄存器或存儲器操作數,可以是任意一個通用寄存器,而且還可 ---- 以是任意一個存儲器操作數.這給程序的編寫帶來了很大的方便. OPRD2為立即數,也可以是任意一個通用寄存器操作數.立即數只能用于源操作數2. OPRD1和OPRD2均為寄存器是允許的,一個為寄存器而另一個為存儲器也是允許的 ,但不允許兩個都是存儲器操作數.理由是指令代碼的尋址方式中規定了兩個操 作數(除立即數)至少有一個是寄存器操作數.3. 加法指令運算的結果對CF、SF、OF、PF、ZF、AF都會有影響.以上標志也稱為結 果標志.加法指令適用于無符號數或有符號數的加法運算.操作數可以是8位,也 可以是16位.4. 示例: ADD AL,25 ;(AL)<--(AL)+25 ADD BX,0A0AH ;(BX)<--(BX)+0A0AH ADD DX,DATA1[BX] ADD DI,CX ;(DI)<--(DI)+(CX)ADD BETA[BX],AX ADD BYTE PTR[BX],28 注意: 上述第一條指令及第六條指令為字節相加指令,其它四條均為字(雙字節) 相加指令.未加注解的三條指,都與存儲器操作數有關.第三條指指令中,存儲器操作 數是源操作數,采用變址尋址方式;第五條指令中,存儲器操作數是目的操 作數,采用變址尋址方式;第六條指令中存儲器操作數也是目的操作數,采 用寄存器間接尋址方式,當立即數與存儲器操作數做加法時, 類型必須一 致,故此處用BYTE PTR[BX],將存儲器操作數的類型重新指定為字節類型, 以保證兩個操作數類型一致. 數據傳送指令 MOV格式: MOV OPRD1,OPRD2----功能: 本指令將一個源操作數送到目的操作數中,即OPRD1<--OPRD2.----說明: 1. OPRD1 為目的操作數,可以是寄存器、存儲器、累加器.---- OPRD2 為源操作數,可以是寄存器、存儲器、累加器和立即數.2. MOV 指令以分為以下四種情況:<1> 寄存器與寄存器之間的數據傳送指令示例: MOV AX,BXMOV DS,AXMOV BP,SI注意: 代碼段寄存器CS及指令指針IP不參加數的傳送,其中CS可以作為源操作數參加傳送,但不能作為目的操作數參加傳送.<2> 立即數到通用寄存器數據傳送指令立即數只能作源操作數使用,不能作目的操作數.示例: MOV AL,25MOV SI,OFFSET DATA1注意: 由于傳送的數據可能是字節,也可能是字,源操作數與目的操作數的類型應一致。<3> 寄存器與存儲器之間的數據傳送指令示例: MOV AL,BUFFERMOV AX,[SI]MOV LAST[BX+DI],DLMOV SI,ES:[BP]<4> 立即數到存儲器的數據傳送示例: MOV ALFA,24MOV DS:MEMS[BP],300AHMOV BYTE PTR[SI],15MOV LAST[BX][DX],0FFH3. 本指令不影響狀態標志位.4. MOV指令執行時的數據傳送方向.<1> 立即數只能作為源操作數,不允許作目的操作數,立即數也不通送至段寄存 器.<2> 通用寄存器可以與段寄存器,存儲器互相傳送數據,寄存器之間也可以互相 傳送.但CS段不能作為目的操作數.<3> 值得再次強調的是存儲器與存儲器之間不能進行數據直接傳送.若要實現 存儲單元間的數據傳送,可以借助于通用寄存器作為中介來進行. 段定義偽操作 SEGMENT和ENDS格式: <段名>SEGMENT[<定位類型>],[<組合類型>],[<'類別名'>] ---- …:段體 <段名>ENDS 功能: SEGMENT和ENDS偽操作命令可用來把程序分成若干邏輯段,這些邏輯段按用途不同 ---- ,通常包括代碼段、數據段、堆棧和附加段,它分別裝入由CS、DS、SS和ES寄存器 所指定的物理段中。說明: 1. 定位類型 ---- 定位類型表示某段裝入內存時,對段的起始邊界有何要求,有以下四種選擇: BYTE:表示本段起始單元可以從任一地址開始,段間不留空隙,存儲器利用率最 高。 WORD:表示本段起始單元從一個偶字節地址開始,即段起始地址的最后一位二進 制數一定是0,如02152H、0A156H等。這種定位方式適合于數據項的類型 為字的數據段。PARA:這是隱含選擇,表示本段起始地址從一個字節的邊界開始。一個節為16個 字節,所以段的起始地址一定能被16整除,亦即是以0H結尾的地址,如 024D0H、07A20H等。 PAGE:表示本段起始地址從一個頁的邊界開始。一頁為256個字節,所以段的起 始地址一定能被256整除,以即是以00H結尾的地址,如02400H、07A00H等2. 組合類型(Combine Type)NONE:這是隱含選擇,表示本段與其他段無組合關系,每段都有自己的段基址PUBLIC:表示在滿足定位類型的前提下與其他模塊的同名段鄰接在一起,形成 一個新的邏輯段,公用一個段基址,所有偏移量調整為相對于新邏輯 段的起始地址。COMMON:表示產生一個覆蓋段。也就是說,當一兩個段連接時,把本段與其他 也用COMMON說明的同名段置成相同的起始地址,共享相同的存儲區。 共享存儲區的長度由其中最大的段確定。STACK:表示把所有同名段連接成一個連續段,自動初始化SS和SP,使SS 的內 容為該連續段的首地址,SP指向堆棧底部+1的存儲單元。MEMORY:表示本段在存儲器中應定位在所有其他段的最高地址。3. 類別名(Class) 類別名可以是任何合法的名字,必須用單引號括起來。 模塊定義偽操作 NAME和END格式: [NAME<模塊名>]---- ...END[標號]功能: 定義一個模塊說明: 模塊命名偽操作命令NAME可以省略。這時,該模塊的命名規則是:如果模塊中使 ---- 用了TITLE語句(列表輸出的頁標題命令),則TITLE語句中頁標題的前六個字符 就是模塊名;如果模塊中沒有使用TITLE語句,則該模塊的源程序文件名就是模塊 名。 加法指令 ADD(Addition)格式: ADD OPRD1,OPRD2----功能: 兩數相加----說明: 1. OPRD1為任一通用寄存器或存儲器操作數,可以是任意一個通用寄存器,而且還可 ---- 以是任意一個存儲器操作數.這給程序的編寫帶來了很大的方便. OPRD2為立即數,也可以是任意一個通用寄存器操作數.立即數只能用于源操作數2. OPRD1和OPRD2均為寄存器是允許的,一個為寄存器而另一個為存儲器也是允許的 ,但不允許兩個都是存儲器操作數.理由是指令代碼的尋址方式中規定了兩個操 作數(除立即數)至少有一個是寄存器操作數.3. 加法指令運算的結果對CF、SF、OF、PF、ZF、AF都會有影響.以上標志也稱為結 果標志.加法指令適用于無符號數或有符號數的加法運算.操作數可以是8位,也 可以是16位.4. 示例: ADD AL,25 ;(AL)<--(AL)+25 ADD BX,0A0AH ;(BX)<--(BX)+0A0AH ADD DX,DATA1[BX] ADD DI,CX ;(DI)<--(DI)+(CX)ADD BETA[BX],AX ADD BYTE PTR[BX],28 注意: 上述第一條指令及第六條指令為字節相加指令,其它四條均為字(雙字節) 相加指令.未加注解的三條指,都與存儲器操作數有關.第三條指指令中,存儲器操作 數是源操作數,采用變址尋址方式;第五條指令中,存儲器操作數是目的操 作數,采用變址尋址方式;第六條指令中存儲器操作數也是目的操作數,采 用寄存器間接尋址方式,當立即數與存儲器操作數做加法時, 類型必須一 致,故此處用BYTE PTR[BX],將存儲器操作數的類型重新指定為字節類型, 以保證兩個操作數類型一致.總結
以上是生活随笔為你收集整理的一文读懂汇编程序的多个分段的程序--详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 专题:区块链与数据共享(上)
- 下一篇: 适用于特殊类型自然语言分类的自适应特征谱