在編寫**的過程中,算術溢位是一件讓人十分頭疼的事。因此在**中檢測是否溢位是一件很有必要的事,那麼該如何檢測算術運算中的溢位呢?
以c語言中的算術乘法為例,可以使用以下的**檢測是否有溢位:
//判斷a與b的乘積是否溢位,是返回-1,否返回0
int overflow(int a,int b)
在函式中,首先計算a與b的乘積temp,然後再計算temp除以b。如果得到的結果是a的話,那麼就沒有溢位,否則運算過程中發生了溢位。誠然,該函式可以有效地檢測算術乘法是否溢位,但是對於cpu來說,除法的開銷相對於加法、移位等操作來說是非常大的,因此我們應該嘗試避免。
在這裡,我們嘗試使用組合語言來判斷算術運算中的溢位。
首先,讓我們來了解一些背景知識。
組合語言中set指令根據條件碼的組合,將乙個位元組設定為0或1。 指令
同義指令
效果設定條件
sete d
setz
d ← zf
equal / zero
setne d
setnz
d ← ~zf
not equal / not zero
sets d
d ← sf
negative
setns d
d ← ~sf
nonnegative
setg d
setnle
d ← ~(sf ^ of) & ~zf
greater (signed >)
setge d
setnl
d ← ~(sf ^ of)
greater or equal (signed >=)
setl d
setnge
d ← sf ^ of
less (signed <)
setle d
setng
d ← (sf ^ of) | zf
less or equal (signed <=)
seta d
setnbe
d ← ~cf & ~zf
above (unsigned >)
setae d
setnb
d ← ~cf
above or equal (unsigned >=)
setb d
setnae
d ← cf
below (unsigned <)
setbe d
setna
d ← cf | zf
below or equal (unsigned <=)
在這裡,我們的目標是讀取到of這個標誌位。但是在上表中,並不能單獨地把of標誌位存到暫存器中。仔細觀察後可以發現,上表中可以設定sf^of(setl)和sf(sets)這兩個標誌位,而(sf^of)^sf=of!因此,我們只需要將使用setl和sets指令設定兩個暫存器的值,然後再將這兩個暫存器中的值異或就可以得到of標誌位的值。
話不多說,讓我們開始吧!
首先編寫signedoverflow.c檔案:
int signedoverflow(int a,int b)
使用gcc -og -s signedoverflow.c
命令產生的彙編檔案如下:
.file "signedoverflow.c"
.text
.globl signedoverflow
.def signedoverflow; .scl 2; .type 32; .endef
.seh_proc signedoverflow
signedoverflow:
.seh_endprologue
movl %ecx, %eax
imull %edx, %eax
ret.seh_endproc
.ident "gcc: (x86_64-posix-seh-rev0, built by mingw-w64 project) 7.3.0"
然後我們在此基礎上實現檢測溢位的函式:
.file "signedoverflow.c"
.text
.globl signedoverflow
.def signedoverflow; .scl 2; .type 32; .endef
.seh_proc signedoverflow
signedoverflow:
.seh_endprologue
movl %ecx, %eax
imull %edx, %eax ;計算%edx與%ecx的乘積
sets %r10b ;設定%r10b暫存器的值為sf
setl %r11b ;設定%r11b暫存器的值為sf^of
xorb %r10b, %r11b ;異或%r10b與%r11b,得到of,結果存在%r11b中
movl $0, %eax ;將返回值置為0
movl $-1, %r10d ;將%r10d的值置為-1
testb %r11b, %r11b ;測試%r11b(of)
cmovne %r10d, %eax ;如果%r11b不為0,將返回值置為-1
ret ;函式返回
.seh_endproc
.ident "gcc: (x86_64-posix-seh-rev0, built by mingw-w64 project) 7.3.0"
編寫完成後,使用gcc -og -c signedoverflow.s
生成signedoverflow.o目標檔案。
再編寫測試函式main.c:
#include //判斷a與b的乘積是否溢位,是返回-1,否返回0
int signedoverflow(int a,int b);
int main()
使用gcc -og main.c signedoverflow.o
得到可執行檔案a.exe。執行a.exe得到結果:
-1
0
大功告成! 在雲中更快地開發和部署
通過 ibm 進行企業雲應用程式開發和交付,使您的工作更為簡單。我們細心處理 細節,使您可以集中精力進行創新。使用我們經過驗證的應用程式模式,更快地構建應用程式。或者,使用我們的開發人員套件 英文 建立您自己的模式。使用以上任何一種方法,您都可以快速部署到公共雲或私有雲。我們還對 devops 進行...
讀書技巧 如何最快地汲取營養
網上看到時寒冰寫的這篇關於讀書技巧的文章。其觀點實用易懂,推薦伯友閱讀。以下是作者的觀點 一 高效率的讀書方式 讀書是獲取知識 活躍思維 提高自我的捷徑。我從小讀書深受表哥的影響,以古今文學名著為主。那個時候差不多能夠讀到的書,也基本上都是文學類的 文學是那個時候的主流,作家最吃香,連人找物件都強調...
算術左移後溢位判斷
取一位元組為例,能表示的數字從 128 127 先看正數,比如 9,就是 0000 1001,最高位 符號位 和資料最高位都是 0.左移得到 0001 0010 也就是 18 再看負數 9,就是 0000 1001 也就是 1111 0110 1 即 1111 0111,最高位 符號位 和資料最高位...