[英]Sorting ARM Assembly
我是新手。 我在理解內存ARM內存映射時遇到困難。
我找到了簡單排序算法的示例
AREA ARM, CODE, READONLY
CODE32
PRESERVE8
EXPORT __sortc
; r0 = &arr[0]
; r1 = length
__sortc
stmfd sp!, {r2-r9, lr}
mov r4, r1 ; inner loop counter
mov r3, r4
sub r1, r1, #1
mov r9, r1 ; outer loop counter
outer_loop
mov r5, r0
mov r4, r3
inner_loop
ldr r6, [r5], #4
ldr r7, [r5]
cmp r7, r6
; swap without swp
strls r6, [r5]
strls r7, [r5, #-4]
subs r4, r4, #1
bne inner_loop
subs r9, r9, #1
bne outer_loop
ldmfd sp!, {r2-r9, pc}^
END
並且此匯編程序應從C代碼中以這種方式調用
#define MAX_ELEMENTS 10
extern void __sortc(int *, int);
int main()
{
int arr[MAX_ELEMENTS] = {5, 4, 1, 3, 2, 12, 55, 64, 77, 10};
__sortc(arr, MAX_ELEMENTS);
return 0;
}
據我了解,此代碼在堆棧上創建整數數組,並調用在匯編中實現的_sortc
函數。 此函數從堆棧中獲取此值並對其進行排序,然后放回堆棧中。 我對嗎 ?
我想知道如何僅使用匯編來實現此示例。
例如定義整數數組
DCD 3, 7, 2, 8, 5, 7, 2, 6
BTW DCD聲明的變量存儲在內存中的位置?
如何以這種方式聲明的值進行運算? 請說明如何僅使用原始數據就不使用任何C代碼,甚至不使用堆棧就可以使用匯編來實現此目的。
我正在為ARM7TDMI
體系結構編寫
AREA ARM, CODE, READONLY
這標志着源代碼部分的開始。
使用類似的AREA myData, DATA, READWRITE
您可以在開始部分的地方開始定義data1 DCD 1,2,3
類的數據,這將編譯為三個單詞,連續字節中包含值1,2,3,標簽data1
指向第一個單詞的第一個字節。 (一些來自Google的AREA文檔)。
加載可執行文件后,這些文件將在物理內存中的位置取決於鏈接可執行文件的方式(鏈接器正在使用腳本文件來幫助他確定將哪個區域放置在何處,以及如何創建符號表以由可執行文件加載器進行動態重定位,通過編輯鏈接描述文件,您可以調整代碼和數據的放置位置,但通常不需要這樣做。
此外,鏈接器腳本和匯編器指令也會影響可用堆棧的大小以及它在物理內存中的映射位置。
因此,對於您的特定平台:谷歌用於Web上的內存映射,並檢查鏈接描述文件(開始時只需使用鏈接器選項來生成.map文件,以查看將代碼和數據定位在何處)。
因此,您可以在某個數據區域中聲明該數組,然后使用該數組,將符號data1
加載到寄存器中(“加載data1的地址”),然后使用該數組從該地址中獲取內存內容。
或者,您可以先將所有數字放入堆棧中(可能由可執行文件的OS加載程序將其設置為合理的值),然后使用堆棧指針在代碼中進行操作以訪問其中的數字。
您甚至可以將一些值DCD
到CODE
區域,因此這些字將在可執行加載程序映射為只讀的內存指令之間結束。 您可以讀取這些數據,但是寫入它們可能會導致崩潰。 當然,您不應該偶然地將它們作為指令執行(忘記在DCD
之前放置一些ret / jump指令)。
沒有堆棧
好吧,這很棘手,您必須小心不要使用任何呼叫/等。 並禁用中斷等。基本上任何需要堆棧的東西。
當人們編寫引導加載程序代碼時,通常他們會在前幾條指令中盡快設置一些臨時堆棧,因此他們可以在基本設置整個環境或加載操作系統之前使用基本的堆棧功能。 臨時堆棧的空間通常在代碼中/之后保留,或者根據重置后定義的機器狀態保留未使用的內存空間。
如果您精疲力盡,沒有操作系統,通常所有內存在重置后都是可寫的,因此您可以根據需要混合代碼和數據(只是在數據周圍跳躍,而不是偶然地執行它們),而無需使用AREA定義。
但是,無論您是要在某些OS的用戶空間中創建應用程序(因此,如堆棧和數據區之類的定義都很好並且可以方便地使用它們),還是要創建必須用於自行設置所有內容(更困難,因此我建議首先進入某些OS的用戶領域,使用clib初始化C包裝器也很方便,因此您可以從ASM調用printf
東西以方便輸出)。
如何使用以這種方式聲明的值進行操作
在機器碼中,值的聲明方式無關緊要。 重要的是,如果您有內存的地址,並且知道結構,那么如何將數據存儲在那里。 然后,您可以使用所需的任何說明,以所需的任何方式與他們合作。 因此,該asm示例的主體不會發生變化,如果您在ASM中分配數據,您將像C一樣將指針作為參數傳遞給它。
編輯:一些未經測試而盲目完成的示例,可能需要進一步修復語法才能適用於OP(或者甚至可能存在一些錯誤,並且根本無法使用,如果可以,請在評論中告訴我):
AREA myData, DATA, READWRITE
SortArray
DCD 5, 4, 1, 3, 2, 12, 55, 64, 77, 10
SortArrayEnd
AREA ARM, CODE, READONLY
CODE32
PRESERVE8
EXPORT __sortasmarray
__sortasmarray
; if "add r0, pc, #SortArray" fails (code too far in memory from array)
; then this looks like some heavy weight way of loading any address
; ldr r0, =SortArray
; ldr r1, =SortArrayEnd
add r0, pc, #SortArray ; address of array
; calculate array size from address of end
; (as I couldn't find now example of thing like "equ $-SortArray")
add r1, pc, #SortArrayEnd
sub r1, r1, r0
mov r1, r1, lsr #2
; do a direct jump instead of "bl", so __sortc returning
; to lr will actually return to called of this
b __sortc
; ... rest of your __sortc assembly without change
您可以通過C代碼將其調用為:
extern void __sortasmarray();
int main()
{
__sortasmarray();
return 0;
}
除其他外,我還使用了這種介紹性的ARM匯編語言來刷新我的ARM asm內存,但我仍然擔心這可能無法正常工作。
如您所見,我沒有更改__sortc
任何 __sortc
。 因為訪問堆棧內存或“ dcd”內存沒有區別,所以它是同一台計算機內存。 獲得特定單詞的地址后,您就可以使用該地址ldr / str它的值。 __sortc
接收數組中第一個單詞的地址以在兩種情況下進行排序,從那里開始只是用於存儲它,而沒有任何上下文說明如何在源中定義,分配,初始化存儲等。只要它是可寫的,就可以__sortc。
因此,我唯一與“ dcd”相關的事情是加載數組地址,並且快速搜索ARM示例表明它可以通過幾種方式來完成,這種add rX, pc, #label
方式是最佳的,但僅適用於+- 4K范圍? 還有偽指令ADR rX, #label
做同樣的事情,在范圍問題的情況下可能會切換到其他指令? 對於任何范圍,它看起來都像ldr rX, = label
形式,盡管我不確定它是偽指令還是它是如何工作的,請查看一些教程並反匯編機器代碼以查看其編譯方式。
學習所有ARM程序集的特性以及如何加載數組的地址取決於您,我目前不需要ARM ASM,因此我沒有深入研究這些細節。
並且應該有一些equ
方法來定義數組的長度,而不是從結束地址中的代碼中對其進行計算,但是我找不到任何示例,而且我也不會閱讀完整的Assembler文檔來了解其所有指令(在gas
我認為ArrayLength equ ((.-SortArray)/4)
將起作用)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.