ARM 汇编基础教程番外篇 ——配置实验环境
?
From:https://zhuanlan.zhihu.com/p/29145513
?
win10 arm 匯編環境
Windows 平臺下搭建 ARM 匯編集成環境:https://jingyan.baidu.com/article/4b52d70288bfcdfc5c774ba5.html
?
要調試 ARM 程序,我們需要:
- 能運行 ARM 程序的運行環境。
- 支持 ARM 架構的調試器。
本篇教程將基于 x86 平臺的 Ubuntu 20,介紹如何搭建 ARM 的交叉編譯、運行和調試環境。
?
?
?
交叉編譯環境
?
Ubuntu 20 的源中提供了多個 arm-gcc 的軟件包,以 gcc 5 為例可以通過 "apt search"?命令找到 "gcc-5-arm-linux-gnueabi"?和 "gcc-5-arm-linux-gnueabihf"?兩個軟件包。這兩個軟件包安裝的編譯工具是一樣的,只是與浮點數相關的默認編譯選項不同。由于我們虛擬的環境沒有 FPU,只需要安裝 "gcc-5-arm-linux-gnueabi"?就可以了。
安裝完成后可以在 "/usr/bin/arm-linux-gnueabi-*" 找到相關的編譯工具鏈,包含常用的 gcc、as 和 ld 等。
只要使用如下兩條命令,就可以實現對 ARM 匯編的編譯:
$ arm-linux-gnueabi-as [source file] –o [object file] $ arm-linux-gnueabi-ld [object file] –o [executable file]可以使用如下命令編譯經典的 "hello world"?程序,用于后續章節的實驗:
$ arm-linux-gnueabi-gcc-5 hello.c –g –o hello -static示例截圖:
?
?
arm-linux-gcc 安裝方法
?
From:Ubuntu 18.04安裝arm-linux-gcc交叉編譯器 :https://www.cnblogs.com/tansuoxinweilai/p/11602830.html
方法 一:
我們都知道 Ubuntu 有一個專門用來安裝軟件的工具 apt,我們可以用它來全自動安裝 arm-linux-gcc。
首先 Ctrl+Alt+T 彈出終端,使用如下命令進行 arm-linux-gcc 的安裝:
sudo apt-get install gcc-arm-linux-gnueabihf使用如下命令進行 arm-linux-g++ 的安裝:
sudo apt-get install g++-arm-linux-gnueabihf如果要卸載時使用如下命令進行移除,arm-linux-gcc 的卸載:
sudo apt-get remove gcc-arm-linux-gnueabihfarm-linux-g++ 的卸載:
sudo apt-get remove g++-arm-linux-gnueabihf?
方法 二:
64 位的 Ubuntu 系統,那就安裝64位的arm-linux-gcc交叉編譯器,直接安裝就能成功:
例如:arm-linux-gcc-4.6.4-arm-x86_64.tar.bz2??
下載地址:https://pan.baidu.com/s/1xuh8M8bQHfZt_w6h4vRKeg??提取碼:uk85?
1. 先把下載好的安裝包移動到根目錄下的tmp目錄中( /tmp )
2. 使用 tar 命令解壓安裝包,即在Terminal中輸入以下命令:( 前面的 sudo 表示使用 root 權限執行該命令 )
注意是大寫的字母 C,此命令會把安裝包解壓到根目錄下的 opt 的 TuxamitoSoftToolchains里面(/opt/TuxamitoSoftToolchains)
如圖逐層查看找到 gcc-4.6.4 所在的位置:/opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi
3. 解壓完成后,再在(/usr/local)中創建一個新目錄 arm,即在 Terminal 中輸入以下命令:
sudo mkdir /usr/local/arm創建 arm 目錄成功后,還需要給它解放全部權限,即在 Terminal 中輸入以下命令:
sudo chmod 777 /usr/local/arm4. 在解壓出來的目錄中找到并把整個 gcc-4.6.4目錄復制到剛剛建好的arm目錄中,命令如下:
先 cd 切換到 gcc-4.6.4 所在目錄(切換后先ls看一下有沒有 gcc-4.6.4 目錄):
cd /opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi/再執行 cp 復制命令,-r 表示整個目錄以及里面的任何東西
sudo cp -r gcc-4.6.4 /usr/local/arm5.打開(/etc/profile)配置環境變量和庫變量,目的是以后可以在任何位置使用該交叉編譯器,命令如下:
sudo vi /etc/profile用 vi 或者 vim 打開后,在文件最后添加兩行,并輸入以下代碼:第一行是添加執行程序的環境變量,第二行是庫文件的路徑
export PATH=$PATH:/usr/local/arm/gcc-4.6.4/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/gcc-4.6.4/lib然后保存退出即可。
6. 使用 source 命令重新加載生效該配置文件
source /etc/profile7.檢驗是否安裝成功,在 Terminal 輸入以下命令輸出版本信息:
arm-linux-gcc -v結果如圖所示:得到剛剛安裝的4.6.4版
再隨便寫一個 1.c 文件,能編譯成功說明已經完美安裝。例如:
arm-linux-gcc 1.c -o pp再 file 命令查看編譯后的是不是 arm 的可執行文件:
file pp可以看到編譯后的可執行文件是在 32-bit 的 ARM 架構上運行的。
?
注意:有些做完上述步驟還是不能用arm-linux-gcc的話,出現如下圖所示錯誤:
這和時候需要在 “/home/用戶名” 目錄下的 ".bashrc" 隱藏文件下加上和 “/etc/profile” 一樣的兩句
export PATH=$PATH:/usr/local/arm/gcc-4.6.4/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/gcc-4.6.4/lib這個 ".bashrc" 是一個隱藏文件,需要? ls -a 命令才能看見!用戶名就是你自己的linux登錄賬號。
同樣用 vi或者vim打開它,在最后添加兩行:
?
?
?
運行環境
?
QEMU 來創建一個,[教程在這]:https://blog.csdn.net/zerokkqq/article/details/79621769
?
1. qemu-user-static
最簡單的運行環境是使用 qemu-user-static 模擬運行靜態編譯的可執行程序。
我們可以使用如下命令模擬運行上一節創建的 hello 程序:
# 首先安裝 qemu-user-static,若已安裝可以忽略這一步 $ sudo apt install qemu-user-static # 直接執行 hello 程序 $ qemu-arm-static hello # 啟動 gdbserver 等待 gdb 連接 $ qemu-arm-static –g [gdbserver port] hello上述命令運行后會啟動一個 qemu 自帶的 gdbserver,監聽你通過 "-g"?選項指定的端口。可以在另一個窗口中啟動 gdb 進行遠程調試(遠程調試的細節,將在第三章介紹)。
?
Linux 下 ARM 程序的編譯運行及調試:https://www.jianshu.com/p/dc8e263d6466
-
安裝 qemu
sudo apt-get install qemu qemu-arm-static qemu-kvm-extras
-
arm 程序的編譯運行
- 編譯:arm-linux-gcc -o hello-arm hello.c
- 運行:qemu-arm hello-arm
-
安裝 gdb-multiarch
sudo apt-get install gdb-multiarch
-
arm 程序的調試
- 利用 gdb 對 qemu-arm 運行的程序進行遠程 gdb 調試,首先是在終端中輸入如下指令等待調試:qemu-arm -g 1234 hello-arm
- 再打開另外一個終端,并在其中利用 arm-linux-gdb 進入調試器,并通過端口 1234 連接到 qemu-arm 等待調試的程序:gdb-multiarch hello-arm
?
?
2. 虛擬 Raspberry
ARM匯編學習(一)搭建ARM匯編模擬環境(?圖文教程?):https://www.veryarm.com/65170.html
qemu-user-static 的方式比較簡單,但功能也很局限,Azeria-labs 的教程中介紹了另一種方法,使用 qemu 創建一臺虛擬樹莓派。首先你需要安裝 qemu-system :
$ sudo apt install qemu-system為了虛擬一臺樹莓派,你還需要下載專為樹莓派定制的debian鏡像(raspbian)和支持樹莓派的內核文件。
raspbian鏡像下載地址:https://www.raspberrypi.org/downloads/raspbian/
樹莓派內核下載地址:https://github.com/dhruvvyas90/qemu-rpi-kernel
?
Raspbian 的鏡像有兩個版本,一個帶圖形界面的完整版和一個沒有圖形界面的 lite 版本,對于我們的實驗而言 lite 版本就足夠了。內核文件有多個,選擇內核版本最新的那個就可以了。下載完上述文件后,創建一個“arm_vm”目錄,將上述文件一起放置在該目錄下。然后執行如下命令:
$ unzip <image-file>.zip $ fdisk –l <image-file>你應該可以看到,類似如下內容:
Disk 2017-08-16-raspbian-stretch-lite.img: 1.7 GiB, 1854418944 bytes, 3621912 sectorsUnits: sectors of 1 * 512 = 512 bytesSector size (logical/physical): 512 bytes / 512 bytesI/O size (minimum/optimal): 512 bytes / 512 bytesDisklabel type: dosDisk identifier: 0xee397c53Device Boot Start End Sectors Size Id Type2017-08-16-raspbian-stretch-lite.img1 8192 93813 85622 41.8M c W95 FAT32 (LBA)2017-08-16-raspbian-stretch-lite.img2 94208 3621911 3527704 1.7G 83 Linux注意標紅的部分,可以看到文件系統從94208扇區開始。我們將這個值乘以512,本例中為“94208 * 512=48234496”,這就是文件系統其實位置的偏移字節數,在下面的命令中我們會用到:
$ sudo mkdir /mnt/raspbian $ sudo mount -v -o offset=48234496 -t ext4 [path-of-your-img-file.img] /mnt/raspbian $ sudo vi /mnt/raspbian/etc/ld.so.preload 將上述文件中的所有內容用“#”注釋掉,保存修改并退出。 $ sudo vi /mnt/raspbian/etc/fstab如果fstab文件中有出現mmcblk0字符串,那么將“/dev/mmcblk0p1”替換為“/dev/sda1”,將“/dev/mmcblk0p2”替換為“/dev/sda2”,保存后退出。至此,系統配置的修改完成,可以將“/mnt/raspbian”卸載掉。
$ sudo umount /mnt/raspbian你可以進入“arm_vm”目錄,使用如下腳本啟動虛擬機:
#!/usr/bin/env bashqemu-system-arm -kernel kernel-qemu-4.4.34-jessie \ -cpu arm1176 \ -m 256 \ -M versatilepb \ -serial stdio \ -append "root=/dev/sda2 rootfstype=ext4 rw" \ -drive format=raw,file=2017-08-16-raspbian-stretch-lite.img \ -redir tcp:5022::22 \# 為ssh預留 -redir tcp:3011::3011 \# 為gdbserver預留,用于遠程調試 -no-reboot 1> /dev/null 2>&1 &虛擬機啟動后默認的登錄密碼是“raspberry”。為了更方便的使用虛擬機,我們需要開啟ssh服務,并設置開機啟動。
$ sudo service ssh start $ sudo update-rc.d ssh enable此時,你應該已經可以使用如下命令,通過ssh訪問虛擬機了:
$ ssh pi@127.0.0.1 -p 5022我們可以使用scp命令通過ssh,將上一節編譯的hello程序上傳到虛擬機中執行:
scp -P 5022 hello pi@127.0.0.1:/tmp進入虛擬機的tmp目錄,可以看到我們上傳的hello程序嘗試執行,應該會輸出久違的“hello world!”,說明我們的交叉編譯環境搭建是正確的。至此我們的虛擬樹莓派環境搭建完畢。
?
?
調試環境
調試環境的搭建是最重要的也是坑最多的。為了模擬真實IoT安全實戰中遠程調試的場景,我們將介紹如何交叉編譯gdbserver并上傳至虛擬機進行遠程調試。為了獲得類似pwndbg那樣強大的調試效果,我們將介紹如何安裝使用專為IoT安全設計的gef增強腳本。
?
1. gdb-multiarch
在使用gdb進行調試之前,我們需要先安裝gdb-multiarch。顧名思義,它是gdb支持多中硬件體系架構的版本。之所以要安裝gdb-multiarch,是因為Ubuntu默認安裝的gdb只支持x86/x64架構,你可以啟動gdb然后輸入命令“set
architecture arm”查看,gdb會提示錯誤。
?
2. 編譯 gdbserver
在分析IoT設備的安全性時,我們往往需要上傳gdbserver進行遠程調試。在我們的實驗環境中(事實上我們的Raspbian系統自帶gdb),我們也可以模擬搭建一個遠程調試環境。首先,我們需要獲取gdb的源碼(包含了gdb源碼和gdbserver源碼),版本需要與我們本地的gdb版本一致,因為gdbserver需要與gdb版本保持一致,否則容易出現非預期的問題。你可以在這個地址,找到gdb各版本的源碼:http://ftp.gnu.org/gnu/gdb/。
?
下載解壓后進入“gdb-<version>/gdb/gdbserver”目錄,使用如下命令編譯安裝:
$CC="arm-linux-gnueabi-gcc-5" CXX="arm-linux-gnueabi-g++-5" ./configure --target=arm-linux-gnueabi --host="arm-linux-gnueabi" --prefix="setup-directory" $ make install然后,在你通過“--prefix”選項指定的路徑下,就可以找到編譯完成的gdbserver了。使用file命令查看,應該可以看到類似如下輸出:
$ file arm-linux-gnueabi-gdbserver arm-linux-gnueabi-gdbserver:ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=32ad2025951ee428276ac2fbadb199bfd39e2278, not stripped使用scp將gdbserver上傳到我們的虛擬樹莓派中并啟動:
$ ln -s arm-linux-gnueabi-gdbserver gdbserver $ gdbserver 0.0.0.0:2333 hello Process hello created; pid = 702 Listening on port 2333至此,我們的遠程調試環境搭建完畢,下一節,我們將引入gef增強腳本。
?
3. gef 增強腳本
gef是一個支持多種硬件體系結構的gdb增強腳本,非常適合IoT安全領域應對多變的硬件平臺。你可以參考github主頁(https://github.com/hugsy/gef)的README,進行安裝配置。不過需要注意的是,gef依賴的第三方模塊keystone-engine需要手動安裝,因為pip源提供的安裝是無效的。建議先通過pip安裝,如果安裝后gef的部分功能仍無法使用,可以卸載通過pip安裝的第三方模塊,在github上(https://github.com/keystone-engine/keystone)下載最新源碼,手動編譯安裝(參見:http://www.keystone-engine.org/docs/)。
安裝完成后開啟gdb調試,你將看到類似如下的界面:
首先設置目標硬件體系架構為arm:
gef> set architecture arm
我們使用gef-remote命令連接gdbserver,如果使用gdb自帶的“target remote”命令會出現一些非預期的問題(參見:https://github.com/hugsy/gef/issues/7)。
gef> gef-remote –q 127.0.0.1:2333
你應該能看到類似如下的輸出:
至此,我們的調試環境配置完畢了。
?
?
擴展閱讀
?
[1] gef官方文檔,http://gef.readthedocs.io/en/master/
[2] gdb調試利器,http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html
[3] gdb中應該知道的幾個調試方法,https://coolshell.cn/articles/3643.html
本文由看雪翻譯小組 ljcnaix 原創 轉載請注明來自看雪社區
?
?
?
ARM匯編 與 ARM GNU匯編 區別
?
ARM 匯編 與 ARM GNU匯編 區別:https://blog.csdn.net/tabactivity/article/details/90054443
?
一、ARM匯編開發的兩種的方式
ARM 匯編開發,有兩種開發方式,一種是使用 ARM 匯編,一種是使用 ARM GNU 匯編。兩種匯編開發,使用的匯編指令是完全一樣的,區別是宏指令,偽指令,偽操作不一樣。其實兩種開發方式的區別在于所使用的編譯工具不一樣。
對于 ARM 匯編,使用的是 ARM 公司開發的編譯器,而 ARM GNU 匯編,是使用 GNU 為 ARM 指令集開發的編譯器,也就是arm-gcc。
?
二、ARM的編譯開發環境
兩種常用的 ARM 的編譯開發環境
-
DS5:ARM 提供的集成開發軟件。使用的是 ARM 提供的工具鏈進行程序編譯
-
GNU 開發環境: 由 GNU 的匯編器 as,交叉編譯器 gcc,和 鏈接器ld 等組成
?
三、偽操作,宏指令,偽指令
- 偽操作:ARM 匯編語言程序里的一些特殊指令助記符,其作用主要是完成匯編程序做各種準備工作,在源程序進行匯編時由匯編程序處理,而不是在計算機運行期間由機器執行。如程序段的定義,就屬于偽操作。
- 宏指令:一段獨立的程序代碼,可插在源程序中,通過偽操作來定義。
- 偽指令:ARM 匯編語言程序里的一些特殊指令助記符,不在處理器運行期間執行,在匯編時,被合適的ARM的機器指令代替,從而實現真正的指令操作。
?
四、ARM 匯編偽操作
| 偽操作 | 語法格式 | 作用 |
| GBLA | GBLA ?Varible | 聲明一個全局的算術變量,并將其初始化為0 |
| GBLL | GBLL ?Varible | 聲明一個全局的邏輯變量,并將其初始化成{FALSE} |
| GBLS | GBLS ?Varible | 聲明一個全局的字符串變量,并將其初始化成空串 |
| LCLA | LCLA ?Varible | 聲明一個局部的算術變量,并將其初始化為0 |
| LCLL | LCLL ?Varible | 聲明一個局部的邏輯變量,并將其初始化成{FALSE} |
| LCLS | LCLS ?Varible | 聲明一個局部的字符串變量,并將其初始化成空串 |
| SETA | SETA ?Varible ?expr | 給一個全局或局部算術變量賦值 |
| SETL | SETL ?Varible ?expr | 給一個全局或局部邏輯變量賦值 |
| SETS | SETS ?Varible ?expr | 給一個全局或局部字符串變量賦值 |
| RLIST | name LIST {list of registers} | 為一個通用寄存器列表定義名稱 |
| CN | name CN expr | 為一個協處理器的寄存器定義名稱 |
| CP | name CP expr | 為一個協處理器定義名稱 |
| DN/SN | name DN/SN expr | DN/SN為一個雙精度/單精度的VFP寄存器定義名稱 |
| FN | name FN ?expr | 為一個FPA浮點寄存器定義名稱 |
| LTORG | LTONG | 聲明一個數據緩沖池(文字池)的開始 |
| MAP | MAP expr {, base-register} | 定義一個結構化的內存表(storage map)的首地址 |
| FIELD | {label} ?FIELF ?expr | 定義一個結構化內存表中的數據域 |
| SPACE | {label} ?SPACE ?expr | 分配一塊連續內存單元,并用0初始化 |
| DCB | {label} ?DCB ?expr {,expr}.. | 分配一塊字節內存單元,并用expr初始化 |
| DCD/ DCDU | {label} DCD/DCDU expr {,expr}… | 分配一塊字內存單元, 并用expr初始化 |
| DCDO | {label} ?DCDO ?expr {,expr}… | 分配一塊字對齊的字內存單元, 并用expr初始化 |
| DCFD/DCFDU | {label} ? DCFD{U} ? fpliteral ,{,fpliteral}… | 為雙精度的浮點數分配字對齊的內存單元 |
| DCFS/DCFSU | {label} ? ?DCFS{U} ?fpliteral ,{,fpliteral}… | 為單精度的浮點數分配字對齊的內存單元 |
| DCI | {label} DCI expr, {expr}… | ARM代碼分配一段字對齊的內存單元,填充expr(二進制指令碼),THUMB代碼中,分配一段半字對齊的半字內存單元。 |
| DCQ/ DCQU | {label} DCQ{U} ?{-} literal, {, {-} literal}… | 分配一段以雙字(8個字節)為單位的內存 |
| DCW/DCWU | {label} DCW{U} ?{-} literal, {, {-} literal}… | DCW用于分配一段半字對齊的半字內存單元 |
?
-
1、AREA:創建一段新的程序代碼或數據區。? ? ? ??
?? ??? ?格式 : ??AREA ?name, {,attr,} …
? ? ? ? 其中,name是程序段名, atrr是段名屬性
? ? ? ? 對于屬性,有以下一些:
? ? ? ? ? ? ? ? CODE: 用于定義代碼段,默認為是READONLY
? ? ? ? ? ? ? ? DATA: 用于定于數據段,默認為READWRITE
? ? ? ? ? ? ? ? READONLY: 指定本段的內容只讀
? ? ? ? ? ? ? ? READWRITE: ?指定本段的內容可讀可寫
? ? ? ? ? ? ? ? ALIGN: ?指定對齊為2次冪
? ? ? ? ? ?COMMON: 定義通用的段。不包含任何用戶的代碼和數據。各源文件中同名的COMMON屬性段共享同一段存儲單元 - 2、ALIGN:指定對齊
? ? ? ? ? ? ALIGN ?4 ?表示4字節地址對齊
? ? ? ? ? ? ALIGN ?8 ?表示8字節地址對齊
? ? ? ? ? ? 注意:在AREA中使用和單獨使用ALIGN的區別,在于格式和對齊的計算不一樣。 - 3、ENTRY:指定匯編程序的入口。
? ? ? ? 一個程序至少有一個入口點,也可以有多個入口點,但是在一個源文件中,最多只能有一個ENTRY。
? ? ? ? 當多個源文件均有ENTRY時,由鏈接器指定程序真正的入口。 - 4、END:表示源程序的結束。所以匯編語言源文件必須以END結束,匯編器遇到END, 將結束編譯。
- 5、EXPORT
? ? ? ? 格式: EXPORT ?標號 ?[,WEAK]
? ? ? ? 聲明一個全局標號,其他源文件可以使用這個標號。WEAK表示碰上其他同名標號時,其他標號優先。 -
6、IMPORT
? ? ? ? 格式: ??IMPORT 標號,[,WEAK]
? ? ? ? 表示該引用的標號在其他源文件中,單要在當前文件中引用。
? ? ? ? WEAK表示找不到該標號時,也不報錯,一般該標號置為0,如果是B 或BL指令用到該標號,該指令置為nop。
? ? ? ? 該標號會加入到當前源文件的符號表中。 - 7、EXTERN:和 IMPORT 一樣,不同在于,如果當前文件沒有引用該標號,該標號不會加入到當前源文件的符號表中。
- 8、GET ( 或 INCLUDE ):將一個源文件包含到當前的源文件中
- 9、EQU:對一個常量標號賦值
? ? ? ? 格式: ?name ??EQU ??expression
? ? ? ? 其中: name符號名, expression寄存器相關或者程序相關的固定值
? ? ? ? 如:num ??EQU ??2 ?; ?為符號賦予數字2
? ? ? ? EQU,等同于C語言中用#define定義一個常量 - 10、SPCAE:用于分配一片連續內存單元,并用0初始化。SPACE 可用 % 代替。
? ? ? ? 格式: {label} SPACE expr
? ? ? ? label : 是一個標號, 可選
? ? ? ? expr: ??分配的內存字節數
? ? ? ? 如:stack SPACE 100 ; 分配100個字節內存單元,并用0初始化。標號stack是這片空間的起始地址 - 11、DCB:用于分配段字節內存單元,并用偽操作中的expr初始化。
? ? ? ? 格式: {label} DCB expr {,expr}
? ? ? ? label: 是一個標號,可選
? ? ? ? expr: 可以是-128~255的數值或者字符串
? ? ? ? 如:string ?DCB ?"HELLO" ??;為HELLO字符串分配空間, string是這塊空間的起始地址 - 12、DCD 及 DCDU:用于分配段字內存單元(分配的內存都是字對齊,DCDU并不嚴格字對齊),并用偽操作中的expr初始化。 DCD 可用 & 代替。
? ? ? ? 格式: {label} DCD expr, {,expr}
? ? ? ? label: 是一個標號,可選,表示這塊內存單元的首地址
? ? ? ? expr: 數字表達式或程序中的標號
? ? ? ? 如:data DCD ?1,2,3,4 ????;分配字對齊的字單元空間,初始化為1,2,3,4
?
?
五、ARM匯編偽指令
?
ARM偽指令包括: ADR, ADRL,LDR ,NOP
THUMB偽指令包括:ADR, LDR, NOP
| 偽指令 | 語法格式 | 作用 |
| ADR | ADR{cond} register, expr | 將基于PC或基于寄存器的地址值讀取到寄存器中。小范圍的地址讀取 |
| ADRL | ADRL{cond} register, expr | 將給予PC或基于寄存器的地址值讀取到寄存器中。中等范圍的地址讀取 |
| LDR | LDR {cond} register, =[expr|label] | 將一個32位的立即數或者一個地址值讀取到寄存器中。大范圍的地址讀取 |
| NON | NOP | 在匯編時,被替換成空操作 |
?
六、ARM GNU 編譯環境
?
| 偽操作 | 語法格式 | 作用 |
| .byte | .byte expr {,expr}… | 分配一段字節內存單元,并用expr初始化 |
| .hword/.short | .hword expr {,expr}… | 分配一段半字內存單元,并用expr初始化 |
| .ascii | .ascii expr {,expr}… | 定義字符串expr |
| .asciz/.string | .asciz expr {,expr}… | 定義字符串expr(會增加/0為結束符) |
| .floar/.single | .float expr {,expr}… | 定義32bit IEEE浮點數expr |
| .double | .doubel expr {,expr}… | 定義64bit IEEE浮點數expr |
| .word/.long/.int | .word expr {,expr}… | 分配一段字內存單元,并用expr初始化 |
| .fill | .fill ?repeat {,size} {,value} | 分配一段字節內存單元,用sieze長度value填充repeat次 |
| .zero | .zero size | 分配一段字節內存單元,并用0填充內存 |
| .space/.skip | .space size, {,value} | 分配一段內存單元,用value將內存初始化 |
| .section | .section expr | 定義一個段 |
| .text | .text {subsection} | 代碼段, |
| .data | .data{subsection} | 數據段 |
| .bss | .bss{subsection} | bss段 |
| .cond 16/.thumb | .code 16/.thumb | 表示之后的匯編指令使用THUMB指令集 |
| .code 32/.arm | .code 32/.arm | 表示之后的匯編指令使用ARM指令集 |
| .end | .end | 標記匯編文件的結束 |
| .include | .include "filename" | 將一個源文件包含到當前源文件中 |
| .align/.balign | .align {alignment} {,fill},{max} | 通過填充字節使當前位置滿足一定的對齊格式 |
?
七、兩種開發環境的區別
?
兩種開發環境下的匯編代碼,有較多不同的點,主要是符號及偽操作的不同。
| ARM匯編的偽操作符 | GNU匯編的偽操作符 |
| INLCUDE | .include |
| NUM ? ?EQU ? 25 | .equ ?NUM, ?25 |
| EXPORT | .global |
| IMPORT | .extern |
| DCD | .long |
| IF: ?DEF: | .ifdef |
| ELSE | .else |
| ENDIF | .endif |
| OR | | |
| SHL | << |
| RN | .req |
| GBLA | .global |
| NUM ?SETA 16 | .equ ? NUM , 16 |
| MACRO | .macro |
| MEND | .endm |
| END | .end |
| AREA WORD, CODE, READONLY | .text |
| AREA BLOCK, DATE, READWRITE | .data |
| CODE32 | .arm |
| CODE16 | .thumb |
| LTORG | .ltorg |
| % | .fill |
| ENTRY | ENTRY: |
| ldr x0,=0xff | ldr x0,=0xff |
原文鏈接:http://www.lujun.org.cn/?p=3943
?
?
?
?
總結
以上是生活随笔為你收集整理的ARM 汇编基础教程番外篇 ——配置实验环境的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Inspeckage,安卓动态分析工具
- 下一篇: 《MFC初探》之变量类型