0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

簡(jiǎn)單聊聊什么是段

程序員cxuan ? 來(lái)源:程序員cxuan ? 2023-02-20 09:31 ? 次閱讀

這是 x86 匯編連載系列第六篇文章,前五篇文章見(jiàn)文末。

一個(gè)小細(xì)節(jié)

從開(kāi)始到現(xiàn)在我們接觸到了兩種匯編指令的編寫(xiě)方式,一種是在 dosbox 上的 debug 模式下通過(guò) debug -a 的方式來(lái)編寫(xiě),如下圖所示:

8a6df0ba-b0b2-11ed-bfe3-dac502259ad0.png

這種方式能讓你在 dosbox 中直接編寫(xiě)匯編代碼,簡(jiǎn)單直接,不需要寫(xiě)偽指令,方便快捷。

還有一種方式需要我們?cè)?dosbox 外部編寫(xiě)匯編源文件,源文件中的代碼經(jīng)由 MASM 匯編編譯、LINK 指令鏈接后一種,如下圖所示:

8a8aa462-b0b2-11ed-bfe3-dac502259ad0.png

乍一看這兩種方式編寫(xiě)的匯編源代碼應(yīng)該都能正確的執(zhí)行,于是我們分別用兩種不同的方式寫(xiě)下了

8aaca7e2-b0b2-11ed-bfe3-dac502259ad0.png

這幾條指令。這三條指令很簡(jiǎn)單,我們的目的很明確,我們想把內(nèi)存地址為 ds:[1], ds[2], ds[3] 的數(shù)據(jù)分別送入 al,bl,cl 寄存器。下面我們執(zhí)行一下:

使用 debug 方式的截圖如下:

8ac43b78-b0b2-11ed-bfe3-dac502259ad0.png

如圖所示,在使用 debug 方式中,"[ ]" 內(nèi)的指令會(huì)被直接當(dāng)做內(nèi)存地址進(jìn)行 mov。

使用 masm 編譯器方式的截圖如下:

8adea3c8-b0b2-11ed-bfe3-dac502259ad0.png

如圖所示,當(dāng)我們使用 MASM 進(jìn)行編譯和鏈接后,[ ] 號(hào)中的 1 會(huì)被直接編譯為數(shù)值 01,而不是 [1] 這個(gè)內(nèi)存地址。這個(gè)是編譯規(guī)定,大家要記住這個(gè)細(xì)節(jié)。

也就是說(shuō),誠(chéng)如 [idata] 這種形式,debug 和 masm 匯編器對(duì)其有不同的解釋?zhuān)琩ebug 認(rèn)為 [1] 中的就是一個(gè)內(nèi)存地址,而 masm 認(rèn)為 [1] 就是一個(gè) idata 立即數(shù)。

話又說(shuō)回來(lái)了,如果我們想在匯編源文件中表示內(nèi)存地址,該怎么辦呢?

這就需要借助一個(gè)寄存器了 --- bx。

比如下面這段匯編代碼

8b01f364-b0b2-11ed-bfe3-dac502259ad0.png

首先將 ds 寄存器設(shè)置為 2000 ,也就是 ds = 2000h,然后把 0 放入 bx 中,最后的 mov al,[bx] 就會(huì)默認(rèn)從內(nèi)存地址ds:[0] 處提取數(shù)據(jù)進(jìn)行移動(dòng)。

這樣當(dāng)然是可以的,不過(guò)仍然比較繁瑣,我們不想要每次 mov 內(nèi)存數(shù)據(jù)還要經(jīng)過(guò) bx 中轉(zhuǎn),我們想要像 debug 那樣直接 mov ,該怎么做呢?其實(shí)也比較簡(jiǎn)單,直接顯示指出段寄存器:[內(nèi)存偏移]即可。

看下面這段匯編代碼:

8b1cc1c6-b0b2-11ed-bfe3-dac502259ad0.png

如果你想要通過(guò) MASM 的方式來(lái)取得 ds:[0] 處內(nèi)存地址的話,就需要顯示指定段寄存器,如果沒(méi)有顯示指定的話,默認(rèn)按照 01 數(shù)值來(lái)處理。

所以我們可以總結(jié)一下上面所探討的內(nèi)容(基于 MASM 匯編編譯器下)

mov al,[0] :將數(shù)值 0 送入 al 寄存器中,(al) = 0。

mov al,ds:[0]:(al) = ((ds) * 16 + 0) , 將內(nèi)存單元中的數(shù)據(jù)送入 al 中,段地址為 ds。

mov al,[bx]:(al) = ((ds) * 16 + bx) , 將內(nèi)存單元的數(shù)據(jù)送入 al 中,段地址為 ds。

mov al,ds:[bx] :和 mov al,[bx] 含義相同

還可以更為精簡(jiǎn)的總結(jié)一點(diǎn):

MASM 匯編編譯器會(huì)將 [idata] 編譯為 idata,若想訪問(wèn)內(nèi)存地址,則必須顯示指定段地址或者使用 bx 進(jìn)行中轉(zhuǎn)。

上面這些內(nèi)容在本人其他文章中已經(jīng)涉及到了,不過(guò)講的不太細(xì)致,這篇文章算是細(xì)致的講了下。

段前綴

上面的內(nèi)容多次提到了一個(gè)名詞就是 段,段所表示的其實(shí)也是一段內(nèi)存空間,不過(guò)這種劃分的方式是由 CPU 來(lái)決定的,內(nèi)存并不會(huì)分為多個(gè)段。段的劃分是主要為了 CPU 能夠更方便的尋址,要想尋找段內(nèi)的每個(gè)地址和數(shù)據(jù),都需要有兩個(gè)概念:段基址和段內(nèi)偏移。

在匯編語(yǔ)言中,一般通過(guò) [bx] 來(lái)給出偏移地址,它的段基礎(chǔ)在 ds 中,ds 是默認(rèn)的段寄存器。

不過(guò),只有一個(gè) ds 段顯然是無(wú)法應(yīng)對(duì)復(fù)雜程序的尋址方式的,所以還可能會(huì)有多個(gè)段,如下所示:

8b37e7f8-b0b2-11ed-bfe3-dac502259ad0.png

上面列舉了四種不同的段寄存器和尋址方式。

第一條指令把段基址為 ds,偏移地址為 bx 的內(nèi)存地址的內(nèi)容送入 ax ,長(zhǎng)度為 2 個(gè)字節(jié)單元,也就是一個(gè)字,16 位。

第二條指令把段基址為 cs,偏移地址為 bx 的內(nèi)存地址的內(nèi)容送入 ax ,長(zhǎng)度為 2 個(gè)字節(jié)單元,一個(gè)字,16 位。

第三條指令把段基址為 ss,偏移地址為 bx 的內(nèi)存地址的內(nèi)容送入 ax ,長(zhǎng)度為 2 個(gè)字節(jié)單元,一個(gè)字,16 位。

第四條指令把段基址為 es,偏移地址為 bx 的內(nèi)存地址的內(nèi)容送入 ax ,長(zhǎng)度為 2 個(gè)字節(jié)單元,一個(gè)字,16 位。

由于 ds、cs、ss、es 都是顯示指出的,所以 ds、cs、ss、es 又被稱(chēng)為段前綴。

一段安全的存儲(chǔ)空間

我們寫(xiě)出的程序經(jīng)過(guò)編譯連接后,會(huì)由操作系統(tǒng)分配內(nèi)存空間,我們并不知道哪些內(nèi)存空間是有用的,哪些內(nèi)存空間是保留的,哪些內(nèi)存空間是可以使用的,由于有些內(nèi)存空間存儲(chǔ)著重要的系統(tǒng)數(shù)據(jù)或代碼,所以我們最好不要隨意的向內(nèi)存空間寫(xiě)入數(shù)據(jù),這是很危險(xiǎn)的,比如下面這幾條指令:

8b4daac0-b0b2-11ed-bfe3-dac502259ad0.png

之前為了方便,我們沒(méi)有判斷 1000:[0] 這個(gè)內(nèi)存空間有沒(méi)有存放重要代碼或數(shù)據(jù)就將數(shù)據(jù)寫(xiě)入其中,這種做法是錯(cuò)誤的,如果 1000:[0] 處剛好存放著文件系統(tǒng)的起始代碼,那么 mov ds:[0],al 就會(huì)將其改寫(xiě),引發(fā)系統(tǒng)崩潰。

再看一段程序:

8b67ed54-b0b2-11ed-bfe3-dac502259ad0.png

我們編寫(xiě)好代碼后,進(jìn)行編譯鏈接,debug 這段代碼:

8b80817a-b0b2-11ed-bfe3-dac502259ad0.png

當(dāng)我們執(zhí)行完 mov ds:[26h],ax 后,說(shuō)什么也執(zhí)行不下去了。

并不是我不想執(zhí)行了,而是系統(tǒng)不讓我執(zhí)行了,因?yàn)橄到y(tǒng)死機(jī)了。。。。。。大家可以試試。

所以,在不清楚這段內(nèi)存空間是干什么的時(shí)候,最不好要隨意向內(nèi)存空間寫(xiě)入數(shù)據(jù)。由于內(nèi)存空間是由操作系統(tǒng)直接分配的,所以要想向一段內(nèi)存空間寫(xiě)入數(shù)據(jù)的話,要使用操作系統(tǒng)給我們分配的內(nèi)存空間。

那么話又說(shuō)回來(lái)了,操作系統(tǒng)給我們分配了哪些空間可以安全的寫(xiě)入數(shù)據(jù)呢?

在一般的 PC 機(jī),DOS 方式下,DOS 和其他合法程序一般都不會(huì)使用0:200 ~ 0:2ff(00200h ~ 002ffh)這段 256 個(gè)字節(jié)的空間,可以認(rèn)為這段內(nèi)存區(qū)域是安全的。

不過(guò)為了謹(jǐn)慎起見(jiàn),我們寫(xiě)入的時(shí)候,最好使用 debug -d 來(lái)看一下這段內(nèi)存區(qū)域有沒(méi)有存儲(chǔ)數(shù)據(jù)。

段前綴的使用

考慮一個(gè)問(wèn)題,如何將內(nèi)存 ffff:0 ~ ffff:b 單元中的數(shù)據(jù)復(fù)制到 0:200 ~ 0:20b 單元中?

需要考慮以下幾點(diǎn):

0:200 ~ 0:20b 其實(shí)就是 200:0 ~ 200:b ,這就是對(duì)同一段內(nèi)存空間的兩種不同的描述。

上面是兩段不同的內(nèi)存空間,所以需要兩個(gè)段基址,通過(guò)一個(gè)寄存器 dl 來(lái)進(jìn)行中轉(zhuǎn),把 ffff:0 ~ ffff:b 地址空間的數(shù)據(jù)復(fù)制到 dl 中,然后把 dl 中的數(shù)據(jù)再?gòu)?fù)制到 0:200 ~ 0:20b 中。

一共復(fù)制 (b - 0) + 1 = 12 次。

開(kāi)碼!

8ba2a192-b0b2-11ed-bfe3-dac502259ad0.png

從上面代碼可以看到,我們顯示使用了兩種段前綴 ds 和 es ,這就是一個(gè)段前綴的使用案例。

我們分別將 0ffffh 和 200h 賦給了 ds 和 es 寄存器,然后設(shè)置 cx 循環(huán)次數(shù)為 12 次,s 是一個(gè)偽指令,表示循環(huán)的開(kāi)始處,每個(gè)循環(huán)中都會(huì)把 0ffff:[bx] 中的數(shù)據(jù)賦值給 dl ,因?yàn)檫@是一個(gè)內(nèi)存地址,所以使用 8 位寄存器就可以接收,然后將 dl 中的數(shù)據(jù)賦值給 200:[bx] 處,再執(zhí)行循環(huán)。

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5254

    瀏覽量

    119277
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4674

    瀏覽量

    67810
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1602

    瀏覽量

    48915

原文標(biāo)題:簡(jiǎn)單聊聊什么是段

文章出處:【微信號(hào):cxuangoodjob,微信公眾號(hào):程序員cxuan】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    簡(jiǎn)單聊聊什么是功率因數(shù)

    在交流系統(tǒng)中,電源提供正弦電壓波形,負(fù)載則主導(dǎo)電流波形。在加熱器或白熾燈泡等最簡(jiǎn)單的“阻性”負(fù)載中,電流波形與電壓波形形狀一致,并且相位(時(shí)間軸)也保持一致。
    發(fā)表于 07-14 16:55 ?933次閱讀
    <b class='flag-5'>簡(jiǎn)單</b>的<b class='flag-5'>聊聊</b>什么是功率因數(shù)

    高通產(chǎn)品的進(jìn)來(lái)聊聊

    高通產(chǎn)品的進(jìn)來(lái)聊聊,共享一下資源.
    發(fā)表于 01-03 14:32

    為什么加入程序code會(huì)反而減小呢?

    今天在調(diào)試程序的過(guò)程中發(fā)現(xiàn)個(gè)挺有趣的問(wèn)題:請(qǐng)大神們過(guò)來(lái)討論一下,我就不選最佳了,讓系統(tǒng)自己選。畢竟是跟大神們聊聊天而已。為什么加入程序code會(huì)反而減小呢?能說(shuō)下真實(shí)理解么
    發(fā)表于 06-16 09:03

    聊聊CMSIS

    這次我們來(lái)聊聊CMSIS。之前在Kile環(huán)境下創(chuàng)建STM32工程的時(shí)候,對(duì)有些文件的加入總不是很了解,書(shū)上或網(wǎng)上建立工程的教程對(duì)于這些文件的加入也是一筆帶過(guò),或者直接不說(shuō)。對(duì)于類(lèi)似名叫
    發(fā)表于 08-24 07:50

    聊聊對(duì)按鍵掃描軟件結(jié)構(gòu)的理解

    按鍵掃描,我想應(yīng)該是比較簡(jiǎn)單的單片機(jī)應(yīng)用了,但是有時(shí)候看起來(lái)簡(jiǎn)單的東西反而不好寫(xiě)。本文拿大部分人覺(jué)得簡(jiǎn)單的按鍵掃描聊聊我工作至今對(duì)于軟件結(jié)構(gòu)的理解。嗯,對(duì)的,是結(jié)構(gòu),不是架構(gòu),暫時(shí)不敢
    發(fā)表于 12-02 06:27

    聊聊基于STM32F103的紅外循跡避障小車(chē)的Proteus仿真

    紅外循跡及紅外避障實(shí)現(xiàn)較簡(jiǎn)單,無(wú)論是51單片機(jī)還是STM32單片機(jī),其例程隨處可見(jiàn)。但是完全可以運(yùn)行的Proteus仿真,開(kāi)源的并不多,更不要說(shuō)基于STM32單片機(jī)的仿真。下面跟大家聊聊基于STM32F103的紅外循跡避障小車(chē)的Proteus仿真。
    發(fā)表于 01-05 06:46

    聊聊復(fù)位電路

    時(shí)鐘電路我第一篇博客已經(jīng)說(shuō)講過(guò)了,今天我們來(lái)聊聊復(fù)位電路。當(dāng)然,復(fù)位電路博大精深,并...
    發(fā)表于 01-17 07:50

    聊聊存儲(chǔ)器的相關(guān)知識(shí)

    虛擬地址物理地址等眾多地址及MMU相關(guān)知識(shí)先聊聊存儲(chǔ)器STM32單片機(jī)存儲(chǔ)器關(guān)于編譯器生成的文件數(shù)據(jù)在存儲(chǔ)器上的存儲(chǔ)結(jié)構(gòu)物理地址、虛擬地址、線性地址和邏輯地址物理地址虛擬地址邏輯地址線性地址這些地址
    發(fā)表于 02-11 07:51

    碼LCD驅(qū)動(dòng)簡(jiǎn)單原理是什么

    時(shí)鐘的冒號(hào)“:”,這樣如果使用IO口直接掃描顯示,則會(huì)減小PCB面積,降低成本。但是,本方案不合適驅(qū)動(dòng)太多的(占用IO太多),也不合適非常低功耗的場(chǎng)合。碼LCD驅(qū)動(dòng)簡(jiǎn)單原理:如圖1所示。LCD是一種...
    發(fā)表于 02-18 07:54

    聊聊光敏傳感器最簡(jiǎn)單的使用

    描述的可能也有不清楚的地方,有問(wèn)題的小伙伴可以私聊我,一起學(xué)習(xí)共同進(jìn)步。今天發(fā)現(xiàn)了一個(gè)很有意思的傳感器——光敏傳感器,它可以判斷光線的亮暗,當(dāng)然亮暗是個(gè)相對(duì)的說(shuō)法,它可以自己設(shè)定閾值,今天來(lái)聊聊
    發(fā)表于 02-24 07:50

    簡(jiǎn)單聊聊伺服電機(jī)啟動(dòng)電流的問(wèn)題

      現(xiàn)在EPU和EMA應(yīng)用越來(lái)越廣泛,作為液壓領(lǐng)域的從業(yè)者,對(duì)電機(jī)有個(gè)基本的了解是有必要的。  今天簡(jiǎn)單聊聊伺服電機(jī)啟動(dòng)電流的問(wèn)題。  1 電機(jī)啟動(dòng)電流相比于正常工作電流是大是???為什么?  2
    發(fā)表于 03-16 17:38

    一文了解多個(gè)的相關(guān)程序

    上回我們簡(jiǎn)單認(rèn)識(shí)了一下什么是,前綴和一安全的空間是哪里,但是程序中不會(huì)僅有一個(gè),復(fù)雜程
    的頭像 發(fā)表于 03-08 14:28 ?525次閱讀

    簡(jiǎn)單聊聊MCAL的最小工程

    英飛凌的芯片在汽車(chē)電子里用得可謂是頗多,最近剛好在摸TC3系列的CAN模塊,來(lái)簡(jiǎn)單聊聊MCAL的最小工程。
    的頭像 發(fā)表于 03-21 09:25 ?2440次閱讀

    聊聊Redis的使用案例

    今天我們來(lái)聊聊 Redis 的使用案例。
    的頭像 發(fā)表于 12-13 14:13 ?413次閱讀

    聊聊半導(dǎo)體產(chǎn)品的8大封裝工藝

    今天我們聊聊半導(dǎo)體產(chǎn)品的封裝工藝,一提到“封裝”,大家不難就會(huì)想到“包裝”,但是,封裝可不能簡(jiǎn)單的就認(rèn)為等同于包裝的哦
    的頭像 發(fā)表于 02-23 14:42 ?2661次閱讀
    <b class='flag-5'>聊聊</b>半導(dǎo)體產(chǎn)品的8大封裝工藝