我剛開始學習ARM匯編。我目前正在使用“GNU 匯編程式版本 2.35.2 (arm-linux-gnueabihf)”的 32 位 Raspian。
這是我將 ascii 的一部分加載到暫存器中的簡單程式:
.global _start
_start:
ldr r1,=helloworld
ldr r2,[r1]
@prepare to exit
mov r0,#0
mov r7,#1
svc 0
.data
helloworld:
.ascii "HelloWorld"
我將它加載到 gdb 中,可以看到我的暫存器 r2 加載0x6c6c6548(在 ascii“lleH”中)。一個快速的 objdump 顯示:
Contents of section .data:
0000 48656c6c 6f576f72 6c64 HelloWorld
我有以下問題:
- 字串在記憶體中的樣子如何?換句話說,當位元組序出現時?加載到記憶體時會發生逆轉嗎?或者字串將按原樣加載到記憶體中,但在加載到暫存器時被反轉?
- 為什么下面程式的暫存器 r2 的內容
.word是 0x12345678 而不是 0x78563412 ?為什么沒有遵循位元組順序?
注意:.word使用代替.ascii
.global _start
_start:
ldr r1,=helloworld
ldr r2,[r1]
mov r0,#0
mov r7,#1
svc 0
.data
helloworld:
.word 0x12345678
編輯
第一個程式的記憶體轉儲顯示,即使記憶體中的字串也與源代碼和目標檔案中的順序相同:
>>> x/32xb 0x1008c
0x1008c: 0x48 0x65 0x6c 0x6c 0x6f 0x57 0x6f 0x72
0x10094: 0x6c 0x64 0x41 0x11 0x00 0x00 0x00 0x61
這表明ldr指令正在將讀取的記憶體轉換為小端格式,其中 LSB 保存記憶體中的第一個位元組。理解正確嗎?但這仍然不能回答為什么.word.
uj5u.com熱心網友回復:
Endianess 或位元組順序是組成數字的位元組在記憶體中表示的順序。
字串是一個位元組陣列。這個字串的每個位元組都受位元組序的影響,但是對于單個位元組,小位元組序和大位元組序的結果是一樣的。
對于您的第二個問題:位元組序僅影響存盤在記憶體中的資料。匯編器為您提供計算機程式的人類可讀表示。令牌0x12345678代表某個數字。當傳輸到記憶體時,這個令牌會以適當的位元組順序寫入記憶體。匯編器會處理這個問題。
您還將看到暫存器內容,就像0x12345678在除錯器中觀看程式的執行一樣。這是因為暫存器不是記憶體的一部分,也不被分成位元組。每個暫存器保存一個 32 位數字。CPU按照配置的位元組順序在暫存器和記憶體之間傳輸資料(見SETEND指令)并且沒有將暫存器分成位元組,就沒有有意義的方式為其分配位元組順序。除錯器只能顯示它的數值。這只是您在程式中分配給它的值。這太瘋狂了,嗯?
uj5u.com熱心網友回復:
.ascii 是一串位元組 .word 是一個 32 位專案的串列,而不是 8 位專案,它們是無與倫比的。你想要 .byte 嗎?
.ascii "Hello"
.align
.word 0x12345678
.byte 0x12,0x34,0x56,0x78
組裝和拆卸
00000000 <.text>:
0: 6c6c6548 cfstr64vs mvdx6, [ip], #-288 ; 0xfffffee0
4: 0000006f andeq r0, r0, pc, rrx
8: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
c: 78563412 ldmdavc r6, {r1, r4, sl, ip, sp}^
鏈接,復制到二進制檔案并轉儲
00000000 48 65 6c 6c 6f 00 00 00 78 56 34 12 12 34 56 78 |Hello...xV4..4Vx|
00000010
到目前為止,一切都符合預期,這并不令人意外。ascii 字串是一串位元組,我們按照宣告的順序查看它們。這個字是一個字,這是一個小端目標,0x12345678,0x78 是最低有效位元組,所以它在最低地址首先出現。為了將 .ascii 蘋果與蘋果進行比較,我們需要一個位元組串,因此首先宣告 0x12,就像首先宣告 'H' 一樣,所以我們首先在記憶體中看到它。
ldr r0,label0
ldr r1,label1
.ascii "Hello"
.align
label0:
.word 0x12345678
label1:
.byte 0x12,0x34,0x56,0x78
組裝和拆卸
00000000 <label0-0x10>:
0: e59f0008 ldr r0, [pc, #8] ; 10 <label0>
4: e59f1008 ldr r1, [pc, #8] ; 14 <label1>
8: 6c6c6548 cfstr64vs mvdx6, [ip], #-288 ; 0xfffffee0
c: 0000006f andeq r0, r0, pc, rrx
00000010 <label0>:
10: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
00000014 <label1>:
14: 78563412 ldmdavc r6, {r1, r4, sl, ip, sp}^
再次不出意外。反匯編器已嘗試將這些位元組轉換為指令并將它們顯示為字,因此我們分別看到 0x12345678 和 0x78563412,這些值將落在 r0 和 r1 中
鏈接并復制到二進制和 hexdump -C
00000000 08 00 9f e5 08 10 9f e5 48 65 6c 6c 6f 00 00 00 |........Hello...|
00000010 78 56 34 12 12 34 56 78 |xV4..4Vx|
0
我們沒有改變任何東西,所以輸出不會隨著資料項而改變。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/395671.html
