簡體   English   中英

在ARM cortex m0中,第一條指令是什么?

[英]In ARM cortex m0, what is the first instruction?

我正在嘗試學習使用cortex m0處理器。 我有一個stm32f0開發板,可以讓我查看每個地址的每一位並輕松上傳一個新的二進制文件。 我一直在閱讀一些學習很多規則和功能的手冊,但仍然不知道程序計數器在重置時的起始位置,它所期望的參數類型,我甚至不知道如何編寫類似添加的內容或二進制形式的str / ldr。 我讀過的手冊中遺漏了這些基本知識嗎?

它說m0有一個完整的下降堆棧,但似乎建議起點位於另一端(0x00000000)。 如果一個向量表可以用非專業人士的術語來解釋那就太棒了。

完整大小的臂(cortex-A等)地址0x00000000例如是自身執行的重置指令,有點奇怪,你經常會看到一個地址列表,但這就是他們這樣做的方式。 對於cortex-m,它們不僅使用地址列表,而且硬件設計符合EABI,因為它允許您將C函數名稱放在表中而不必進行少量組裝(除了向量表之外)本身)。

所以例如使用gnu匯編程序。

;@-----------------------
.cpu cortex-m0
.thumb
;@-----------------------

.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl notmain
    b hang
.thumb_func
hang:   b .

在深入研究之前,您需要訪問目前位於infocenter.arm.com的內容,然后在架構下,然后armv6-m獲取armv6-m架構參考手冊(ARM ARM for the v6m)。 這些鏈接已經存在了很長時間,但自然可以改變,他們確實稱之為並且區分了建築參考手冊和技術參考手冊。 體系結構參考手冊通常涵蓋該體系結構中的系列。 TRM通常涵蓋特定核心的特定核心或修訂號。 可能值得在信息中心頁面的其他地方獲得。

我正在考慮我所假設的armv6m ARM ARM的rev C:ARM DDI 0419C

在文檔中搜索“向量表”,找到可能或可能不在同一部分的內容:

表B1-4向量表格式

此表顯示地址空間中的偏移量為0時為SP_main。 這是主堆棧指針的重置值。

之后,表中的字偏移是異常編號,在arm世界中字是4個字節,因此異常編號1在地址空間中偏移4,異常2在8處,依此類推。

這總需要我一段時間才能找到。 也在armv6m手臂上。

B1.5.2例外號碼定義

重置異常號1的地方是nmi,依此類推。 我們關心重置。

所以這意味着在ARMS ADDRESS SPACE的地址0x00000000處我們可以選擇預先加載堆棧地址,如果我們想在bootstrap代碼中也設置堆棧,但是我們不必這樣做,一個地方必須這樣做但是不是都。

然后在ARMS ADDRESS SPACE中的地址0x00000004處,我們放置了重置處理程序的地址。

所以在組裝,編譯和鏈接我的例子中的代碼之后我得到了

Disassembly of section .text:

08000000 <_start>:
 8000000:       20001000        andcs   r1, r0, r0
 8000004:       08000041        stmdaeq r0, {r0, r6}
 8000008:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800000c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000010:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000014:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000018:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800001c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000020:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000024:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000028:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800002c:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000030:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000034:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 8000038:       08000047        stmdaeq r0, {r0, r1, r2, r6}
 800003c:       08000047        stmdaeq r0, {r0, r1, r2, r6}

08000040 <reset>:
 8000040:       f000 f80a       bl      8000058 <notmain>
 8000044:       e7ff            b.n     8000046 <hang>

08000046 <hang>:
 8000046:       e7fe            b.n     8000046 <hang>

你可以看到,在gnu匯編程序放置.thumb_func的情況下,在標簽之前使該標簽成為一個函數或地址,因此可以調用bx或blx指令,因此需要設置bx或blx需要正確分支的lsbit( bl不在乎)。 鏈接器自動修復向量表中的地址。 例如,在偏移0x40處復位獲得0x41。

現在為什么這個代碼不是為地址0x00000000構建的?! 那是因為你必須超越arm文檔到芯片供應商文檔,arm不制作芯片他們制作處理器核心和一些邏輯來支持它們,你去st或nxp或ti或任何人找到其余的故事特別是地址空間中的bootflash在哪里。 毫無疑問,在這種情況下,正常啟動的臂地址空間中的地址0x08000000處的壓力被映射到0x00000000,一些芯片將具有多個啟動閃存並且取決於帶(輸入引腳連接高或低或各種組合)一個閃存或另一個閃存將永遠或在一段時間內映射到地址零。

皮質m0(和m1)是基於皮質m3的armv6m,而m4是基於armv7m的。 巨大的區別后者支持拇指指令集的thumb2擴展(以前未定義的指令成為兩個半字指令32位指令的前半部分,不要與32位臂模式指令混淆)並且有大約150個左右的新thumb2指令添加到皮質m3然后皮質m4有一個浮點單位的一小部分(只有一個浮點大小,可能是單個)和所有隨附的指令(基本上是coproessor指令重新定義)。 這使得cortex-m0的生活更容易,只有16位指令(是的,bl實際上是在文檔中定義為兩個獨立的指令,如果你願意,你可以分別編碼)。

目前armv6m ARM ARM還包含指令集定義

第A5章Thumb指令集編碼

看着

A6.7.17 CMP (immediate)

(再次,我的部分編號可能不會保持不變或將來匹配,他們的文檔通常不會改變太多或從一個到另一個,但你永遠不會知道)。

首先要注意的是編碼

Encoding T1 All versions of the Thumb instruction set.

這意味着支持拇指的每個人都支持這個指令(從armv4回到現在)

那么語法

CMP <Rn>,#<imm8>

統一語法可能與此文檔語法不同,也理解ARM有自己的工具鏈,因此定義的語法特定於其匯編程序。 匯編語言不是匯編程序專門定義的標准,匯編程序是解析它的程序。 Gnu匯編程序是一個單獨的東西,不必遵循這個文檔,它主要是這樣,但arm也啟動了這個統一的語法,允許一定比例的匯編語言匯編到thumb,thumb2擴展和arm指令集而無需重寫,如果你沒有指定三者中的哪一個,你仍然可以很快地綁住你的雙手。

您可以在此指令中看到高位必須是00101位15:11,這就是處理器知道這是比較立即的方式。 Rn是寄存器r0到r7,無論你使用哪一個(要訪問r8到r15,你必須使用其他mov指令允許16位指令,他們必須將大多數指令保存到較低的7個寄存器以保存指令編碼中的位) 。 然后低8位是從0到255的直線常數值(其他手臂/拇指立即編碼不是那么直接,拇指與手臂使用不同的編碼,所以你必須閱讀手冊)。

我強烈建議如果你想看到編碼然后用匯編語言匯編然后反匯編,讓希望調試的工具鏈為你工作,然后嘗試對你看到的內容進行逆向工程並將其與手冊相匹配。 頭部刮擦器是奇怪的地址,但是這些是有記錄的(雖然不一定是你希望的)然后是任何相對的pc,當你用它做什么時,電腦是兩個指令,它不是真的有管道,但是反向兼容性並設置一個標准,即arm / thumb標准是前面的兩條指令。 因此,當計算或逆向工程計算pc相對地址時,這就是數學總是關閉4個字節的原因。

與大多數處理器一樣,程序員或至少您信任的程序員借用其代碼就是設置堆棧指針的程序員。 你可以把它放在你想要的地方,arm核心本身,也不知道芯片供應商將如何處理實現,也不知道編譯器真的知道或想知道所有可能的芯片,所以你程序員必須告訴工具鏈,然后告訴臂處理器你想要堆棧的位置。 傳統上使用降序堆棧,您希望從高地址開始。 首先看一下pop和push指令以及偽代碼,看看arm首先按寄存器數量遞減4次(推送),然后寫入這些地址,然后在出路時調整sp。 因此,如果你的ram以0x2001FFFF結束,你可以安全地將你的堆棧指針放在0x20020000,推送的第一件事就是0x2001FFFC。 (好吧不是第一件事,但堆棧的底部是那里)其他非臂處理器工作方式不同,有不同的規則,有些你根本無法得到堆棧指針,有些你可以,但重置值是正確的,有些像你需要擔心的武器。 完整大小的手臂你有多個堆棧指針可以管理,你也可以讓堆棧上升或下降雖然我不會因為你可以反對谷物。

對於所有Cortex-M,存儲器映射中的前兩個字(分別在地址0和4處)應該是您的初始堆棧指針和您想要開始執行的第一條指令的地址。

通常,您將堆棧放在可用的最高RAM地址,並使用鏈接描述文件在地址4的程序入口點的地址中查找。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM