色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

在堆嵌入式單片機編程中為什么大多時候要保證堆棧8字節對齊呢?

STM32嵌入式開發 ? 來源:CSDN ? 2023-08-28 10:48 ? 次閱讀

本文主要介紹了嵌入式單片機編程中,為什么大多時候要保證堆棧8字節對齊的問題。

字節對齊原則

1. 結構(struct)(或聯合(union)) 中的第一個數據成員放在 offset 為 0 的地方,以后每個數據成員存儲的起始位置,要從該成員大小或者成員的子成員大小(只要該成員有子成員,比如說是數組,結構體等)的整數倍開始(比如 int 型變量在 32 位編譯環境下為 4 字節,則要從 4 的整數倍地址開始存儲);

2. 如果一個結構里有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲.

如:struct a 里存有 struct b, b 里有 char, int , double 等元素,那 b 應該從 8 的整數倍開始存儲.;

3. 結構體的總大小,也就是 sizeof 的結果,必須是其內部最大成員的整數倍,不足的要補齊;

dd396a9e-433e-11ee-a2ef-92fbcf53809c.png

總大小為最大成員變量大小的整數倍,sizeof(AA) = 24;sizeof(BB) = 32。

#pragma pack():

在代碼前加一句 #pragma pack(1),會發現 sizeof(AA) = 17;sizeof(BB) = 24;

AA 是 8+4+1+4=17;

BB 是 5+4+8+4+2+1=24;

這就是理想中的沒有內存對齊的情況,所以 #pragma pack(1) 是告訴編譯器,所有的對齊都按照1的整數倍對齊,換句話說就是沒有對齊規則。

即#pragma pack(n)就是所有的對齊都按照n的整數倍對齊。

Vc,Vs等編譯器默認是 #pragma pack(8),所以測試我們的規則會正常;

gcc 默認是 #pragma pack(4),并且 gcc 只支持 1, 2, 4 對齊。套用三原則里計算的對齊值是不能大于 #pragma pack 指定的n值。

為什么要保證堆棧8字節對齊

AAPCS 規則要求堆棧保持 8 字節對齊。如果不對齊,調用一般的函數也是沒問題的。但是當調用需要嚴格遵守 AAPCS 規則的函數時可能會出錯。

例如調用 sprintf 輸出一個浮點數時,棧必須是 8 字節對齊的,否則結果可能會出錯。

實驗驗證:

dd545f52-433e-11ee-a2ef-92fbcf53809c.png


1.在 A 處設置斷點,讓程序全速運行至 A

2.在 MDK 中修改 MSP 的值使 MSP 滿足 8 字節對齊

3.全速運行程序,觀察 buf 中的字符為 1.234 結果正確

4.回到第 2 步,修改 MSP 使之只滿足 4 字節對齊而不滿足 8 字節對齊

5.全速運行程序,觀察 buf 中的字符為 -2.000 結果錯誤

該實驗證明了調用 sprintf 輸出一個浮點數必須要保證棧 8 字節對齊。

編譯器為我們做了什么

先看一個實驗:

dd672d62-433e-11ee-a2ef-92fbcf53809c.png


保證初始的時候堆棧是 8 字節對齊的;

1.在 A 處設置斷點;

2.全速運行至 A,觀察 MSP=0x2000025c,沒有 8 字節對齊;

3.略微修改一下 main 函數代碼如下,其他部分代碼不變;

dd810d90-433e-11ee-a2ef-92fbcf53809c.png


4.同樣在 A 處設置斷點;

5.全速運行至 A,觀察 MSP=0x200002d8,這次 8 字節對齊了; 這個實驗說明了如果編譯器發現了某個函數需要調用浮點庫時會自動調整編譯生成的匯編代碼,從而保證調用這些浮點庫函數時堆棧是8字節對齊的。

換句話說如果我們保證了棧初始的時候是8字節對齊的,那么編譯器可以保證以后調用浮點庫時堆棧仍是8字節對齊的。

os下應該怎樣設置任務堆棧

由上面的討論可知給任務分配棧時需要保證棧是 8 字節對齊的,不然在該任務中凡是調用 sprintf 的函數均會出錯,因為棧一開始就是不對齊的。

是否保證了棧初始是8字節對齊了就萬事大吉了呢。no!大家請看一種特殊的情況:

dd92f834-433e-11ee-a2ef-92fbcf53809c.png

mian函數的反匯編如下:

ddad50d0-433e-11ee-a2ef-92fbcf53809c.png



保證初始的時候堆棧是 8 字節對齊的;

1.在 A 處設置斷點;

2.全速運行至 A,觀察此時 MSP=0x200002e4 未對齊;

3.在 MDK 中將 SVC 的掛起位置 1;

4.在 B 處設置斷點;

5.全速運行至 B,觀察此時 MSP=0x200002b4 未對齊;

6.繼續全速執行,觀察 buf 中的字符為: -2.000 出錯了;

這個實驗說明了即使保證棧初始是 8 字節對齊的,編譯器也只能保證在調用 sprintf 那個時刻棧是 8 字節對齊的,但不能保證任意時刻棧都是 8 字節對齊的,如果恰巧在 MSP 沒有 8 字節對齊的時刻發生了中斷,而中斷中又調用了 sprintf,這種情況下仍會出錯。

Cortex-M3 內核為我們做了什么

Cortex-M3 內核提供了一種硬件機制來解決上述這種中斷中棧不對齊問題。

CM3 中可以把 NVIC 配置控制寄存器的 STKALIGN 置位,來保證中斷中的棧 8 字節對齊。

具體實現過程如下:當發生中斷時由硬件自動檢測 MSP 是否 8 字節對齊,如果對齊了,則不進行任何操作,如果沒有對齊,則自動將 MSP 減 4 這樣便對齊了,同時將 xPSR 的第 9 位置位來記錄這個 MSP 的非正常的變化,在中斷返回若發現 xPSR 的第 9 位是置位的則自動將 MSP 加 4 調整回原來的值。

實驗驗證:

ddc6380c-433e-11ee-a2ef-92fbcf53809c.png



mian函數的反匯編如下:

ddda4aea-433e-11ee-a2ef-92fbcf53809c.png



1.在 A 處設置斷點;

2.全速運行至 A,觀察此時 MSP=0x200002e4 未對齊;

3.在 MDK 中將 SVC 的掛起位置 1,同時將 0xE000ED14 處的值由 0x00000000 改為 0x00000200(即將 NVIC 配置控制寄存器的 STKALIGN 置位)

4.在 B 處設置斷點;

5.全速運行至 B,觀察此時 MSP=0x200002b0 對齊了;

6.觀察中斷返回時的 MSP=0x200002e4 調整回來了;

7.繼續全速執行,觀察 buf 中的字符為:1.234 正確;

這個實驗說明了將NVIC配置控制寄存器的STKALIGN置位可以保護中斷時棧仍是8字節對齊

總結

綜上所述,為了能夠安全的使用嚴格遵守AAPCS規則的函數(比如sprintf)需要做到以下幾點:

保證MSP在初始的時候是8字節對齊的

如果用到OS的話,需要保證給每個任務分配的棧是保持8字節對齊的

如果用的是基于CM3內核的處理器,需將NVIC配置控制寄存器的STKALIGN置位。






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    19396

    瀏覽量

    230712
  • 寄存器
    +關注

    關注

    31

    文章

    5363

    瀏覽量

    120915
  • 存儲器
    +關注

    關注

    38

    文章

    7525

    瀏覽量

    164159
  • SVC控制器
    +關注

    關注

    0

    文章

    2

    瀏覽量

    5245
  • 嵌入式單片機

    關注

    0

    文章

    10

    瀏覽量

    2280

原文標題:對堆棧 8 字節對齊問題的討論

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    AAPCS規則要求堆棧保持8字節對齊(轉)

    我們保證了棧初始的時候8字節對齊的,那么編譯器可以保證以后調用浮點庫時
    發表于 01-19 11:43

    請問F28335字節對齊能不能改為1字節

    大家好,C2000成員TMS320F28335CCS3.3下是2字節對齊的,能不能改為1字節對齊?怎么改
    發表于 08-20 06:41

    align為什么8字節對齊

    我知道數據儲存的起始地址%對齊字節(N)=0才行,但是我不明白有兩點問題1:UCOSIII的系統的浮點數打印任務的堆棧大小
    發表于 04-23 00:21

    請問嵌入式單片機之間的關系是什么?

    時間回到十五年前,大部分人搞嵌入式,其實是做單片機,那時單片機資源少(我曾用過128字節RAM的MCU,仔細扣每一
    發表于 06-24 14:35

    詳解STM32單片機堆棧

    學習STM32單片機時候,總是能遇到“堆棧”這個概念。分享本文,希望對你理解堆棧有幫助。 對于了解一點匯編編程的人,就可以知道,
    發表于 01-12 11:30

    【原創】嵌入式系統中大小端和對齊問題

    作者:黃忠老師(張飛實戰電子高級工程師)C語言是一種高級語言,大多數情況下C語言的代碼是和具體的處理器體系結構無關的。然而,嵌入式系統的編程
    發表于 07-30 09:34

    8單片機全速USB集成128 k字節Flash ROM和8192字節的RAM

    LC87F17C8A是一個8單片機和USB全速主機/設備控制器。128 k字節閃速存儲器/ 8192字節的RAM / 48-pin。
    發表于 04-06 09:15 ?3次下載
    <b class='flag-5'>8</b>位<b class='flag-5'>單片機</b>全速USB集成128 k<b class='flag-5'>字節</b>Flash ROM和8192<b class='flag-5'>字節</b>的RAM

    什么是嵌入式單片機?嵌入式單片機詳情匯總

    嵌入式單片機,即嵌入式微控制器,指以微控制器為核心控制單元的嵌入到對象體系的專用計算機系統,是應用十分廣泛的一種
    發表于 11-13 09:39 ?6116次閱讀

    什么是嵌入式編程

    什么是嵌入式編程?對于嵌入式系統,許多人很容易將它與單片機編程混淆。其實,嵌入式
    發表于 06-29 11:05 ?1.1w次閱讀
    什么是<b class='flag-5'>嵌入式</b><b class='flag-5'>編程</b>

    單片機or嵌入式linux

    最近很多童鞋投票并咨詢如何從單片機轉做嵌入式Linux開發。看來讀者圈單片機,RTOS的不少。盡管我目前從事Linux/Android方面的嵌入
    發表于 11-01 16:26 ?17次下載
    <b class='flag-5'>單片機</b>or<b class='flag-5'>嵌入式</b>linux

    單片機到底是不是嵌入式

    01 問題很多同學一直糾結:我是學單片機還是學嵌入式?還有人說單片機也是
    發表于 11-04 11:21 ?14次下載
    <b class='flag-5'>單片機</b>到底是不是<b class='flag-5'>嵌入式</b>?

    是否要從單片機轉為嵌入式Linux

    最近很多童鞋投票并咨詢如何從單片機轉為嵌入式Linux開發。看來讀者圈單片機,RTOS的不少。盡管小編目前從事Linux/Android方面的
    發表于 11-13 20:51 ?11次下載
    是否要從<b class='flag-5'>單片機</b>轉為<b class='flag-5'>嵌入式</b>Linux

    基于51單片機設計N字節十六進制除法——以6字節除以3字節為例

    基于51單片機設計N字節十六進制除法——以6字節除以3字節為例1、思路借用十進制除法豎計算的思路,作十六進制的除法豎
    發表于 11-23 16:51 ?7次下載
    基于51<b class='flag-5'>單片機</b>設計N<b class='flag-5'>字節</b>十六進制除法——以6<b class='flag-5'>字節</b>除以3<b class='flag-5'>字節</b>為例

    STM32 終極字節對齊解析

    一、全局變量對齊問題:基本上用戶定義的變量是幾個字節就是幾字節對齊,這個比較好理解。uint8_t定義變量地址
    發表于 11-23 18:06 ?11次下載
    STM32 終極<b class='flag-5'>字節</b><b class='flag-5'>對齊</b>解析

    【M3內核篇】關于“堆棧指針的最低兩位永遠是0,這意味著堆棧總是4字節對齊的”的理解

    堆棧指針的最低兩位永遠是0,這意味著堆棧總是4字節對齊的”理解在看到《Cortex-M3權威指南》堆棧指針的這句話剛開始一直摸不著頭腦,通
    發表于 12-01 14:36 ?11次下載
    【M3內核篇】關于“<b class='flag-5'>堆棧</b>指針的最低兩位永遠是0,這意味著<b class='flag-5'>堆棧</b>總是4<b class='flag-5'>字節</b><b class='flag-5'>對齊</b>的”的理解
    主站蜘蛛池模板: adc网址在线观看| 久久热免费视频| 冈本视频黄页正版| 国语自产视频在线| 老太婆性BBWBBW| 少妇的肉体AA片免费观看| 亚洲免费人成在线视频观看| 97人妻中文字幕免费视频| 二级毛片免费观看全程| 狼群资源网中文字幕| 校园男男高h小黄文| YELLOW在线观看高清视频免费 | 俄罗斯18xv在线观看| 国语对白嫖老妇胖老太| nu77亚洲综合日韩精品| 一二三四在线观看高清电视剧| 亚洲AV无码久久流水呻蜜桃久色 | 国产精品嫩草99AV在线| 免费精品美女久久久久久久久久| 新妺妺窝人体色WWW| 东北疯狂xxxxbbbb中国| 嫩草www视频在线观看高清| 亚洲免费在线观看| 国产精品色无码AV在线观看| 被同桌摸出水来了好爽的视频 | 99热国产这里只有精品9九| 激情床戏视频片段有叫声| 午夜国产视频| 成人毛片免费观看视频大全| 精品国产品国语在线不卡| 欧美特级特黄AAAAA片| 中文国产乱码在线人妻一区二区| 国产亚洲精品99一区二区| 天天爽夜夜爽| 国产 日韩 欧美 综合 激情| 欧洲老妇人bb| adc网址在线观看| 青青久久久| 成人国产三级在线播放| 人妻夜夜爽天天爽三区麻豆AV网站| 无限资源好看片2019免费观看|