『壹』 什麼是補碼加減運算溢出判別溢出有哪幾種方法並我說明工作原理。
通常有三種表述方式(說法):
(1)
兩個符號相同的補碼數相加,如果和的符號與加數的符號相反,或兩個符號相反的補碼數相減,差的符號與減數的符號相同,都屬於運算結果溢出。這種判別方法比較復雜,要區別加還是減兩種不同運算情況,還要檢查結果的符號與其中一個操作數的符號的同異,故很少使用;
(2)
兩個補碼數相加減時,若最高數值位向符號位送的進位值與符號位送向更高位的進位值不相同,也是運算結果溢出。
(3)
在採用雙符號位(如定點小數的模4補碼)運算時,若兩個符號位的得值不同(01或10)則是溢出。01表明兩個正數相加,結果大於機器所能表示的最大正數,稱為"上溢";10表明兩個負數相加,結果小於機器所能表示的最小負數,稱為"下溢";雙符號位的高位符號位,不管結果溢出否,均是運算結果正確的符號位,這個結論在乘法運算過程中是很有實際意義的。請注意,在採用雙符號位的方案中,在寄存器和內存儲器存儲數據時,只需存一位符號,雙符號位僅用在加法器線路部分。
再次強調,這三種不同說法是對同一個事實的略有區別的表述,實現時用到的線路可以有所區別,但問題的實質是完全一樣的。
『貳』 FreeRTOS操作系統常式:任務棧溢出檢測
* 1. 學習FreeRTOS的任務棧溢出檢測方法一(模擬棧溢出)。
* 2. FreeRTOS的任務棧溢出檢測方法一說明:
* a. FreeRTOSConfig.h文件中配置宏定義:
* #define configCHECK_FOR_STACK_OVERFLOW 1
* b. 在任務切換時檢測任務棧指針是否過界了,如果過界了,在任務切換的時候會觸發棧溢出鉤子函數。
* void vApplicationStackOverflowHook( TaskHandle_t xTask,
* signed char *pcTaskName );
* 用戶可以在鉤子函數裡面做一些處理。本實驗是在鉤子函數中列印出現棧溢出的任務。
* c. 這種方法不能保證所有的棧溢出都能檢測到。比如任務在執行的過程中發送過棧溢出。任務切換前
* 棧指針又恢復到了正常水平,這種情況在任務切換的時候是檢測不到的。又比如任務棧溢出後,把
* 這部分棧區的數據修改了,這部分棧區的數據不重要或者暫時沒有用到還好,如果是重要數據被修
* 改將直接導致系統進入硬體異常。這種情況下,棧溢出檢測功能也是檢測不到的。
* d. 本實驗就是簡單的在任務vTaskUserIF中申請過大的棧空間,模擬出一種棧溢出的情況,溢出後觸
* 發鉤子函數,因為我們將溢出部分的數據修改了,進而造成進入硬體異常。
#define configCHECK_FOR_STACK_OVERFLOW 1
/*
*********************************************************************************************************
* 函 數 名: StackOverflowTest
* 功能說明: 任務棧溢出測試
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
static void StackOverflowTest(void)
{
int16_t i;
uint8_t buf[2048];
(void)buf; /* 防止警告 */
/*
1. 為了能夠模擬任務棧溢出,並觸發任務棧溢出函數,這里強烈建議使用數組的時候逆著賦值。
因為對於M3和M4內核的MCU,堆棧生長方向是向下生長的滿棧。即高地址是buf[2047], 低地址
是buf[0]。如果任務棧溢出了,也是從高地址buf[2047]到buf[0]的某個地址開始溢出。
因此,如果用戶直接修改的是buf[0]開始的數據且這些溢出部分的數據比較重要,會直接導致
進入到硬體異常。
2. 棧溢出檢測是在任務切換的時候執行的,我們這里加個延遲函數,防止修改了重要的數據導致直接
進入硬體異常。
3. 任務vTaskTaskUserIF的棧空間大小是2048位元組,在此任務的入口已經申請了棧空間大小
------uint8_t ucKeyCode;
------uint8_t pcWriteBuffer[500];
這里再申請如下這么大的棧空間
-------int16_t i;
-------uint8_t buf[2048];
必定溢出。
*/
for(i = 2047; i >= 0; i--)
{
buf[i] = 0x55;
vTaskDelay(1);
}
}
/*
*********************************************************************************************************
* 函 數 名: vApplicationStackOverflowHook
* 功能說明: 棧溢出的鉤子函數
* 形 參: xTask 任務句柄
* pcTaskName 任務名
* 返 回 值: 無
*********************************************************************************************************
*/
void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
printf("任務:%s 發現棧溢出\r\n", pcTaskName);
}
實驗目的:
* 1. 學習FreeRTOS的任務棧溢出檢測方法二(模擬棧溢出)。
* 2. FreeRTOS的任務棧溢出檢測方法二說明:
* a. FreeRTOSConfig.h文件中配置宏定義:
* #define configCHECK_FOR_STACK_OVERFLOW 2
* b. 在任務切換時檢測任務棧指針是否過界了,如果過界了,在任務切換的時候會觸發棧溢出鉤子函數。
* void vApplicationStackOverflowHook( TaskHandle_t xTask,
* signed char *pcTaskName );
* 用戶可以在鉤子函數裡面做一些處理。本實驗是在鉤子函數中列印出現棧溢出的任務。
* c. 任務創建的時候將任務棧所有數據初始化為0xa5,任務切換時進行任務棧檢測的時候檢測末尾
* 的16個位元組是否都是0xa5,通過這種方式來檢測任務棧是否溢出了。相比方法一,這種方法的速度
* 稍慢些,但是這樣就有效的避免了方法一裡面的部分情況。不過依然不能保證所有的棧溢出都能檢測
* 到,比如任務棧末尾的16個位元組沒有用到,即沒有被修改,但是任務棧已經溢出了,這種情況是檢
* 測不到的。另外任務棧溢出後,任務棧末尾的16個位元組沒有修改,但是溢出部分的棧區的數據修改
* 了,這部分棧區的數據不重要或者暫時沒有用到還好,如果是重要數據被修改將直接導致系統進入硬
* 件異常。這種情況下,棧溢出檢測功能也是檢測不到的。
* d. 本實驗就是簡單的在任務vTaskUserIF中申請過大的棧空間,模擬出一種棧溢出的情況,溢出後觸
* 發鉤子函數,因為我們將溢出部分的數據修改了,進而造成進入硬體異常。
#define configCHECK_FOR_STACK_OVERFLOW 2
函數內容和上面一樣:
static void StackOverflowTest(void)
void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
『叄』 定點數加減運算的溢出判定,可以通過______和______的方法判定。
定點數加減運算的溢出判定,可以通過___單符號位判溢方法 ___和___雙符號位進位判溢方法 ___的方法判定。
定點數加減
目前計算機普遍使用補碼實現定點數的加減運算。
1.加減運算方法:
根據補碼的設計規則,任意的絕對值相同的負數和正數,負數是正數的反碼加1,所以絕對值相同的負數和正數相加,剛剛好結果就是為全0(最高位進一位,拋棄)。然後對照下補碼表,可以發現基於這種設計,兩數相加時可以直接將符號位也參與運算,得出的結果也包含符號位。
2.溢出判斷:
(1)單符號位判溢方法
相加溢出的情況只有兩種:
正數和正數相加,結果為負數,發生溢出。
負數和負數相加,結果為正數,發生溢出。
為什麼正數和負數相加不會溢出呢?是因為正數和負數的最值的絕對值都是相同的,正負相加結果一定在絕對值之內。
相減只是將加數取補碼再相加,所以知道相加溢出就夠了。
(2)進位判溢方法(單符號位)
由補碼表觀察可以知道:
不溢出的情況:
一個絕對值較大的負數和絕對值較小的正數相加,最高有效位(即最高的數值位)不會發生溢出,因此符號位也沒有進位。
一個絕對值較小的負數和絕對值較大的正數相加,最高有效位溢出,且使得符號位由1變10(0)進位。
溢出的情況:
上面已經知道:
正數和正數相加,結果為負數,發生溢出。→這種情況是最高有效位進位,而符號位由0變1無進位。
負數和負數相加,結果為正數,發生溢出。→這種情況是最高有效位不進位,而符號位由1變10(0)進位。
所以當最高有效位和符號位的進位不同時,就表明發生了溢出。
(3)雙符號位進位判溢方法
採用雙符號位(00、11)進行相加,上面已經知道:
所以當最高有效位和符號位的進位不同時,就表明發生了溢出。
→符號位進位,最高有效位不進位就變成了11+11=10(110)。此時為負溢出。
→符號位不進位,最高有效位進位就變成了00+1=01。此時為正溢出。
『肆』 針對定點小數加法運算,分析 產生溢出的原因,並給出兩種溢出的方法
(1)產生「溢出」的原因:
當最高有效數值位的運算進位與符號位的運算進位不一致時,將產生運算「溢出」。 當最高有效位產生進位而符號位無進位時,產生上溢; 當最高有效位無進位而符號位有進位時,產生下溢。
(2)「溢出」檢測方法:
為了判斷「溢出」是否發生,可採用兩種檢測的方法。
第一種方法:採用雙符號位法, 稱為「變形補碼」或「模4補碼」,可使模2補碼所能表示的數的范圍擴大一倍
第二種溢出檢測方法:採用「單符號位法」。當最高有效位產生進位而符號位無進位時,產生上溢;
『伍』 兩個無符號數相乘,怎樣判斷是否溢出
對於2個無符號數判斷溢出用進位標志CF判斷
有符號的整數用OF判斷
『陸』 在定點 運算中,為了判斷溢出是否發生,可採用雙符號位檢測法,不論溢出與否
溢出判斷,一般用雙符號位進行判斷:
符號位00
表示正數
11
表示負數
結果的符號位為01時,稱為上溢;為10時,稱為下溢
設x和y是4位的有符號數,x=7,y=-7,符號位為雙符號位
用補碼求x+y,x-y
[x]補+[y]補=00
111+11
001=0
0000結果不溢出
[x-y]補=[x]補+[-y]補=00
111+00
111=0
1110結果上溢出。
同理,可以判斷x,y為其他位數的補碼運算溢出。