官术网_书友最值得收藏!

第1章 QtSpim匯編程序開(kāi)發(fā)環(huán)境

1.1 QtSpim簡(jiǎn)介

QtSpim是支持完整MIPS32指令集的MIPS微處理器模擬器,支持MIPS宏匯編指令。它可以直接打開(kāi)并運(yùn)行MIPS匯編指令源程序(擴(kuò)展名為.s、.asm、.txt),支持MIPS匯編指令程序調(diào)試,但不支持執(zhí)行二進(jìn)制程序。界面如圖1-1所示,包含菜單欄、快捷鍵欄、寄存器顯示窗口、內(nèi)存顯示窗口、消息窗口等。

圖1-1 QtSpim界面布局

1.2 QtSpim菜單欄簡(jiǎn)介

1.2.1 File菜單

File菜單下含有的子菜單如圖1-2所示。

圖1-2 QtSpim File子菜單

(1)Load File:裝載MIPS匯編語(yǔ)言程序。單擊之后彈出如圖1-3所示的文件選擇窗口,支持裝載擴(kuò)展名為.s、.asm、.txt的匯編語(yǔ)言源文件。

圖1-3 QtSpim文件選擇窗口

(2)Recent Files:重新裝載最近使用過(guò)的匯編語(yǔ)言程序。

(3)Reinitialize and Load File:重新初始化模擬器并裝載匯編語(yǔ)言程序,該功能不同于Load File之處為它重新初始化模擬器。

(4)Save Log File:保存數(shù)據(jù)到日志文件。單擊之后彈出如圖1-4所示的數(shù)據(jù)保存窗口,供用戶(hù)選擇數(shù)據(jù)來(lái)源、文件保存路徑及名稱(chēng)。

圖1-4 QtSpim數(shù)據(jù)保存窗口

(5)Print:輸出窗口數(shù)據(jù)到打印機(jī)。單擊之后彈出如圖1-5所示的數(shù)據(jù)打印窗口,供用戶(hù)選擇需要打印的窗口數(shù)據(jù)。

圖1-5 數(shù)據(jù)打印窗口

(6)Exit:退出模擬器。

QtSpim只能裝載匯編語(yǔ)言源程序。若源程序有錯(cuò)誤,則在裝載過(guò)程中報(bào)錯(cuò),每次裝載時(shí)指出源程序中根據(jù)匯編順序出現(xiàn)的第一個(gè)錯(cuò)誤。

QtSpim不支持源程序編輯。因此必須利用其他文字編輯工具編輯匯編語(yǔ)言源程序,并保存為*.s、*.asm或*.txt文件之后再裝載到QtSpim。若裝載時(shí)發(fā)現(xiàn)源程序存在錯(cuò)誤,則必須重新在編輯器中訂正錯(cuò)誤并保存之后再重新裝載,直到?jīng)]有錯(cuò)誤為止。

1.2.2 Simulator菜單

Simulator菜單包含的子菜單如圖1-6所示。

圖1-6 QtSpim Simulator子菜單

(1)Clear Registers:將所有的通用寄存器清零。

(2)Reinitialize Simulator:重新初始化模擬器。

(3)Run Parameters:設(shè)置程序運(yùn)行時(shí)需輸入的參數(shù)。可以設(shè)置的參數(shù)如圖1-7所示。

圖1-7 運(yùn)行程序參數(shù)輸入窗口

(4)Run/Continue:運(yùn)行/繼續(xù)運(yùn)行程序。

(5)Pause:暫停運(yùn)行。

(6)Single Step:?jiǎn)尾竭\(yùn)行。

(7)Display Symbols:在消息窗口顯示代碼中含有的標(biāo)號(hào)及對(duì)應(yīng)的地址。

(8)Settings:設(shè)置模擬器界面以及微處理器相關(guān)參數(shù)。

1.2.3 其余菜單

Registers菜單用于設(shè)置寄存器內(nèi)容顯示數(shù)制,支持十六進(jìn)制、十進(jìn)制、二進(jìn)制三種不同數(shù)制。圖1-8表示采用十六進(jìn)制形式顯示寄存器數(shù)據(jù)。

圖1-8 寄存器數(shù)據(jù)顯示設(shè)置

Text Segment菜單用于設(shè)置代碼顯示窗口顯示的內(nèi)容,可選擇顯示的內(nèi)容如圖1-9所示。

圖1-9 Text Segment子菜單

代碼顯示窗口布局如圖1-10所示。

圖1-10 代碼顯示窗口布局

QtSpim模擬器在用戶(hù)代碼段增加了部分代碼實(shí)現(xiàn)程序運(yùn)行控制,且所有用戶(hù)代碼都存儲(chǔ)在0x00400000~0x00440000地址范圍內(nèi)。為方便核對(duì)用戶(hù)代碼在模擬器代碼段中的位置,注釋中顯示了用戶(hù)編寫(xiě)的匯編源代碼。

Data Segment菜單用于設(shè)置數(shù)據(jù)顯示窗口的顯示內(nèi)容以及顯示制式,可選擇顯示的內(nèi)容如圖1-11所示。

圖1-11 Data Segment子菜單

數(shù)據(jù)顯示窗口布局如圖1-12所示。指示用戶(hù)數(shù)據(jù)區(qū)地址范圍為0x1000 0000~0x1004 0000,用戶(hù)棧地址范圍為0x7fff f844~0x8000 0000,內(nèi)核數(shù)據(jù)區(qū)地址范圍為0x9000 0000~0x9001 0000。模擬器以字為單位顯示存儲(chǔ)空間中的十六進(jìn)制數(shù)據(jù)。

圖1-12 數(shù)據(jù)顯示窗口布局

需要注意的是:MIPS微處理器采用大字節(jié)序管理數(shù)據(jù),但是由于模擬器運(yùn)行在PC上,因此模擬器采用小字節(jié)序,這不影響數(shù)據(jù)處理結(jié)果。

Window菜單用于選擇需顯示的窗口以及窗口排列方式,可選擇的窗口如圖1-13所示,包括整型寄存器窗口、浮點(diǎn)型寄存器窗口、代碼窗口、數(shù)據(jù)窗口、控制臺(tái)窗口。

圖1-13 Window子菜單

1.3 QtSpim匯編、調(diào)試程序示例

1.3.1 QtSpim用戶(hù)程序入口

QtSpim為所有用戶(hù)程序提供了如圖1-14所示用戶(hù)程序入口代碼。該段代碼的功能為獲取程序運(yùn)行時(shí)命令行入口參數(shù),并調(diào)用用戶(hù)程序。

圖1-14 程序入口代碼段

1.3.2 QtSpim匯編查錯(cuò)

本節(jié)通過(guò)一個(gè)具體例子介紹QtSpim匯編查錯(cuò)過(guò)程。

若已知一匯編源程序需實(shí)現(xiàn)如下功能:根據(jù)輸入數(shù)據(jù)1、2、3,分別將32乘以2、4、8,并顯示不同情況下的乘積。偽代碼如圖1-15所示。

圖1-15 example偽代碼

用戶(hù)撰寫(xiě)的匯編語(yǔ)言代碼如圖1-16所示。

圖1-16 匯編語(yǔ)言代碼

當(dāng)把圖1-16所示程序裝載到QtSpim時(shí),彈出如圖1-17所示的錯(cuò)誤提示對(duì)話框。由于QtSpim不支持顯示漢字,所以提示框中有亂碼,即匯編源程序中所有漢字都顯示為亂碼。錯(cuò)誤之處由“∧”標(biāo)注,即代碼中的雙引號(hào)顯示為亂碼。由此可推測(cè)雙引號(hào)錯(cuò)誤地采用了中文全角標(biāo)點(diǎn)符號(hào)。提示消息中的line 4表示錯(cuò)誤之處在第4行,錯(cuò)誤類(lèi)型為不能識(shí)別的字符。

圖1-17 引號(hào)錯(cuò)誤提示對(duì)話框

圖1-18中指出錯(cuò)誤行號(hào)為第5行,錯(cuò)誤類(lèi)型為語(yǔ)法錯(cuò)誤。

圖1-18 錯(cuò)誤行提示

將全角雙引號(hào)修改為半角雙引號(hào)之后再裝載,錯(cuò)誤消失。按F5鍵或單擊圖1-19中的Run/Continue或單擊圖1-20中的三角形可運(yùn)行程序。

圖1-19 Run菜單

圖1-20 Run快捷鍵

QtSpim再次報(bào)如圖1-21所示的錯(cuò)誤,并指出錯(cuò)誤原因?yàn)橹噶钏饕藳](méi)有定義的符號(hào)。指令為jal main,即符號(hào)main沒(méi)有定義。由此可知用戶(hù)程序沒(méi)有定義標(biāo)號(hào)main。

圖1-21 程序入口main錯(cuò)誤

用戶(hù)程序的第一條指令原來(lái)采用top標(biāo)注,因此需要將程序中所有出現(xiàn)的top都修改為main。再次裝載程序并運(yùn)行,不再報(bào)同類(lèi)錯(cuò)誤。出現(xiàn)如圖1-22所示的Console窗口,說(shuō)明程序可以運(yùn)行,但是功能是否正確,還需要進(jìn)一步測(cè)試。

圖1-22 顯示輸入提示

此時(shí)程序代碼如圖1-23所示。

圖1-23 匯編糾錯(cuò)后的代碼

1.3.3 QtSpim查看程序存儲(chǔ)映像

程序存儲(chǔ)映像主要分為三部分:數(shù)據(jù)段存儲(chǔ)映像、代碼段存儲(chǔ)映像、棧存儲(chǔ)映像。圖1-23所示的匯編程序沒(méi)有用到棧,因此只需觀察數(shù)據(jù)段存儲(chǔ)映像和代碼段存儲(chǔ)映像。

數(shù)據(jù)段存儲(chǔ)映像通過(guò)數(shù)據(jù)窗口觀察,已知數(shù)據(jù)窗口顯示的用戶(hù)數(shù)據(jù)段內(nèi)容如圖1-24所示。由于用戶(hù)代碼沒(méi)有定義數(shù)據(jù)段起始地址,因此數(shù)據(jù)段起始地址由裝載程序分配為0x10010000,對(duì)照用戶(hù)數(shù)據(jù)段定義(如圖1-25所示),可知jumptable的起始地址為0x10010000。jumptable包含的標(biāo)號(hào)地址分別為0x00400024、0x00400060、0x00400068、0x00400070。由此可知,main指示的地址為0x00400024,case1指示的地址為0x00400060,case2指示的地址為0x00400068,case3指示的地址為0x00400070。緊接著為字符串"\n\n Input a value from 1 to 3:"的ASCII碼,且4個(gè)字符為一組顯示,如0x49200a0a表示字符串"\n\n I"逆序組合的ASCII碼,即0x49→I、0x20→space、0x0a→\n、0x0a→\n。字符串末地址為0x1001002d,末尾字符空格的ASCII碼為0x20。

圖1-24 用戶(hù)數(shù)據(jù)段數(shù)據(jù)

圖1-25 用戶(hù)數(shù)據(jù)段定義

數(shù)據(jù)段存儲(chǔ)映像如表1-1所示。

表1-1 數(shù)據(jù)段存儲(chǔ)映像

代碼段存儲(chǔ)映像通過(guò)代碼顯示窗口查看。代碼顯示窗口看到的用戶(hù)代碼段數(shù)據(jù)如圖1-26所示。

圖1-26 代碼顯示窗口數(shù)據(jù)

各部分含義如圖1-27所示。每條MIPS32匯編指令都是4字節(jié),因此兩條相鄰MIPS匯編指令地址之差為4。獲取用戶(hù)代碼在內(nèi)存中的映像:一種方法為對(duì)照代碼顯示窗口中注釋部分的用戶(hù)匯編程序源代碼獲取用戶(hù)代碼區(qū)域;另一種方法為查找標(biāo)號(hào)main的地址獲得用戶(hù)代碼起始地址,即在反匯編指令中找到指令jal 0x00400024[main],該指令指出0x00400024為標(biāo)號(hào)main的地址。代碼顯示窗口反匯編指令中采用包含標(biāo)號(hào)和地址的算術(shù)運(yùn)算式表示相對(duì)偏移地址,如指令“blez$2,—24[main-0x0040 003c]”,指出—24通過(guò)main-0x0040 003c計(jì)算而來(lái)。由于main表示0x0040 0024,因此main-0x0040 003c為—24。可以利用該方法核算其他絕對(duì)地址和相對(duì)地址是否正確,還可以通過(guò)代碼顯示窗口核對(duì)宏匯編指令與匯編指令的對(duì)應(yīng)關(guān)系。需要注意的是,QtSpim采用跳轉(zhuǎn)目標(biāo)地址減去當(dāng)前指令地址計(jì)算條件跳轉(zhuǎn)指令的跳轉(zhuǎn)距離(相對(duì)偏移地址),而不是采用跳轉(zhuǎn)目標(biāo)地址減去緊跟當(dāng)前指令的下一條指令地址。也就是說(shuō),QtSpim模擬器計(jì)算條件跳轉(zhuǎn)指令跳轉(zhuǎn)距離采用的方法與實(shí)際MIPS微處理器不一致。第2章介紹的MARS MIPS模擬器不存在這個(gè)問(wèn)題。

圖1-27 代碼顯示窗口數(shù)據(jù)的含義

圖1-23所示的程序代碼段存儲(chǔ)映像如表1-2所示。

表1-2 程序的代碼段存儲(chǔ)映像

1.3.4 QtSpim調(diào)試查錯(cuò)

匯編代碼編寫(xiě)完成,裝載運(yùn)行之后若發(fā)現(xiàn)不是預(yù)期結(jié)果,需調(diào)試程序。下面仍然針對(duì)圖1-23所示的程序闡述QtSpim調(diào)試程序方法。

首先直接運(yùn)行程序,并在Console輸入1~3之間的數(shù)據(jù),此時(shí)Console顯示如圖1-28所示結(jié)果,并報(bào)如圖1-29所示的錯(cuò)誤。

圖1-28 顯示結(jié)果

圖1-29 運(yùn)行結(jié)束出錯(cuò)

圖1-23所示程序要求當(dāng)用戶(hù)輸入2時(shí),輸出128(32×4)。但是此時(shí)輸出0,表明程序初始的被乘數(shù)$s0可能為0,因此在輸出之前設(shè)置一個(gè)斷點(diǎn)。斷點(diǎn)設(shè)置方法為在代碼顯示窗口相應(yīng)行右擊,在如圖1-30所示的窗口中單擊Set Breakpoint。

圖1-30 斷點(diǎn)設(shè)置取消窗口

本程序輸入2時(shí),顯示0,因此找到如圖1-31所示case2對(duì)應(yīng)語(yǔ)句并設(shè)置斷點(diǎn)。

圖1-31 設(shè)置case2斷點(diǎn)

重新設(shè)置PC,使PC指向main處并運(yùn)行程序。具體步驟為:在寄存器窗口選中PC寄存器,右擊,在如圖1-32所示窗口選擇Change Register Contents,如圖1-33所示,在彈出窗口輸入程序入口地址0x00400024。

圖1-32 修改寄存器窗口

圖1-33 修改PC值

再次單擊運(yùn)行,程序從頭開(kāi)始運(yùn)行,并且碰到斷點(diǎn)停下來(lái),彈出如圖1-34所示窗口,用戶(hù)可以選擇繼續(xù)運(yùn)行(Continue)、單步執(zhí)行(Single Step)、放棄(Abort)等。

圖1-34 斷點(diǎn)彈出窗口

若單擊放棄,觀察寄存器窗口發(fā)現(xiàn)如圖1-35所示$s0=0。這說(shuō)明前面指令沒(méi)有正確初始化寄存器$s0的值為32。因此需要在前面加入初始化$s0的匯編指令。

圖1-35 寄存器值

程序起始地址處加入宏匯編指令li$s0,32,變?yōu)閳D1-36所示代碼。再次裝載并運(yùn)行程序,將得到正確的顯示結(jié)果。

圖1-36 起始代碼修改

最后還有一處圖1-29所示運(yùn)行結(jié)束錯(cuò)誤,錯(cuò)誤原因?yàn)樵噲D執(zhí)行非法指令。這是由于程序沒(méi)有利用系統(tǒng)功能調(diào)用退出,導(dǎo)致繼續(xù)往下執(zhí)行。因此,需要加入系統(tǒng)功能調(diào)用退出程序。結(jié)尾處加入系統(tǒng)功能調(diào)用之后的代碼如圖1-37所示。用戶(hù)再重新初始化并裝載該程序代碼,并測(cè)試不同輸入1、2、3,發(fā)現(xiàn)都可以正常地顯示結(jié)果。如果輸入數(shù)據(jù)不在1~3的范圍內(nèi),則重新要求用戶(hù)輸入。至此程序調(diào)試結(jié)束。

圖1-37 結(jié)束代碼修改

在程序差錯(cuò)調(diào)試示例中,介紹了如何設(shè)置斷點(diǎn)、如何修改寄存器的值,下面再簡(jiǎn)要介紹經(jīng)常用到的程序調(diào)試技術(shù),包括單步執(zhí)行和修改內(nèi)存單元的值等。

QtSpim單步執(zhí)行菜單如圖1-38所示,該命令一次執(zhí)行一條指令。當(dāng)需要查看逐條指令執(zhí)行是否正確時(shí),可以采用該命令。

圖1-38 單步執(zhí)行菜單

修改內(nèi)存單元值在數(shù)據(jù)顯示窗口,用戶(hù)根據(jù)變量的定義計(jì)算出變量存儲(chǔ)地址,然后再選中該存儲(chǔ)地址單元,右擊,在如圖1-39所示的窗口中選擇Change Memory Contents,就可以在如圖1-40所示彈出窗口輸入新的值,從而修改內(nèi)存單元的值。需要注意的是:內(nèi)存單元數(shù)據(jù)修改以字為邊界對(duì)齊,如果僅修改某個(gè)字節(jié)或某個(gè)半字的值,則需保持其他存儲(chǔ)單元的內(nèi)容不變。圖1-40修改地址為0x10010014的字型數(shù)據(jù)。修改之前數(shù)據(jù)段內(nèi)的值如圖1-42(a)所示,修改之后如圖1-42(b)所示。圖1-41前三個(gè)字節(jié)不變,僅改變最低地址字節(jié),修改之后的數(shù)據(jù)段如圖1-42(c)所示。

圖1-39 內(nèi)存單元數(shù)據(jù)子窗口

圖1-40 內(nèi)存單元字?jǐn)?shù)據(jù)修改窗口

圖1-41 內(nèi)存單元字節(jié)數(shù)據(jù)修改窗口

圖1-42 數(shù)據(jù)段內(nèi)存數(shù)據(jù)修改前后對(duì)比

主站蜘蛛池模板: 龙川县| 刚察县| 镇坪县| 潞城市| 武功县| 万源市| 新兴县| 巴林左旗| 敦化市| 定陶县| 南投县| 正安县| 鸡东县| 威信县| 北安市| 南靖县| 新宾| 凯里市| 怀柔区| 日土县| 赤城县| 柳州市| 龙井市| 雷州市| 芦山县| 进贤县| 徐州市| 渭南市| 开江县| 昌都县| 云霄县| 婺源县| 福泉市| 司法| 思茅市| 绥化市| 高雄市| 杂多县| 西林县| 马边| 阜南县|