【C/C++ 匯編語言 Verilog】越界截斷——數據越界問題的多角度分析

0 前言

0.1 討論層級和范圍

  • 討論層級
    • 計算機底層:硬件層次與匯編指令層次
    • 信息與二進制位
  • 討論范圍
    • 信息的存儲與運算在匯編語言與Verilog HDL中的聯系與區別
    • 事實上,數據越界截斷問題,在計算機體系的任何層次,都可能發生,并且他們遵循的法則基本是一致的

0.2 其他說明

  • 信息與數據,本質上來講沒有區別,信息就是數據,數據就是信息。為方便起見,在本文中,全部都稱數據
  • 數據越界問題的分析,在實際應用中有以下用途
    • 在一開始設計的時候避免越界問題的發生
    • 在發生錯誤的時候有能力分析出其原因

1 一個概念

越界丟失法則:超過存儲能力的數據,會被截斷,從而導致丟失,也可以稱為越界截斷

這就好比,一個水桶一旦裝滿水,再灌水會溢出來,溢出的水就是丟失了
越界丟失

1.1 越界截斷

我們知道,數據在計算機中是以二進制信息存儲的,即一串一串的二進制數

01011101
01111000

對于上圖所示的,是兩個8位的二進制位串。

下面將通過演示說明,什么是越界截斷,對于8個二進制位來說,所能表示的最大數據就是8位全部是1

11111111

如果再給這個數值加1,那么就會數值就變成:

100000000

這是9位二進制數,但實際上計算機只能存儲8位,因此超過其所能承受的范圍,最高位的1將會被截斷,從而造成數據丟失

被截斷00000000

也就變成了:

00000000

這就是數據的越界截斷

有些讀者可能會誤以為越界丟失就是歸零,因此我再舉一個例子,以消除誤解。

對于8個二進制位來說,如果給他施加了達到10個二進制位的數字

1100101010

那么它的最高兩位將會丟失

被截斷00101010

也就變成了:

00101010

1.2 越界截斷建模——水溢出模型

數據的越界丟失,就好比水桶滿了,多出的水會溢出,但是水桶的水并不會消失,只是多出來的水丟失了
越界丟失

1.3 補充概念——溢出

當數據發生越界,超出了容器容納范圍時,我們稱發生了溢出

2 兩個方向

對于越界截斷現象,有兩個考慮的方向。

2.1 數據的存儲——水桶儲水模型

信息的存儲是指,將信息直接存儲起來
就好比將水放進水桶中
水放進水桶中

2.2 數據的運算——水處理模型

信息的運算是指,對傳輸過來的數據,進行運算(加、減、乘、除……),也就是數據的處理過程
就好比污水經過處理廠變成了凈水
污水處理
亦或者是一桶水倒入另外一桶水中,這樣的模型都是合理的,能夠幫助你理解這一過程
在這里插入圖片描述

3 三個過程

對于越界截斷現象,一般會發生在三個過程中。

3.1 初始量:設初值

包含數據類型、標識符的設定,以及賦初值的過程

3.1.1 Verilog

在Verilog語言中,初始化的方式如下

reg a = 1'b1;
reg b = 123;
reg c;
c = 1'b0;
  • 對于a和c來說,一個二進制位存儲一個二進制數,這是標準的
  • 對于b來說,顯然數據越界了,Verilog會執行越界丟失操作,留下沒越界的數字
    • 123用二進制表示是:0111_1011
    • 因此留下最后一位1,其余高位全部丟失

3.1.2 匯編語言

以8086CPU中16位寄存器AX為例,說明數據的初始化問題

mov AX,11H		 // ①
mov AX,1000001H  // ②
  • 對于①,將它顯然正確
  • 對于②,明顯越界,這是錯誤的指令,注意,是錯誤,可能不會被容錯直接報錯

3.1.3 C/C++等高級語言

int a = 1000100010000;
int b = 100;
  • 很明顯,a越界了,b是正確的
    a越界
    越界是錯誤的

問題:為什么會顯示右側這一串數字?C++是怎么運行出來的?
在回答這個問題之前,先來學習一下延展知識。

3.1.3.1 延展閱讀1:VS C++ 的內存查看方法

【VS C++ 2010】查看內存的方法詳解

學習完之后,再繼續往下進行

以下面的代碼為示例:

int main()
{int a = 100;int b = 100010001000;cout << "a = " << a << "  " << &a << endl;cout << "b = " << b << "  " << &b << endl;system("pause");return 0;
}

以下,我們都需要使用剛剛學到的知識,查看內存的情況

(1)對于正數

①不越界的正數

對于int a = 100;,顯然是不越界的,其內存情況為
不越界的a
這一點沒什么好說的

  • a的類型為int
  • 數值為100(十進制),被解釋為數字100
  • 存儲為二進制位串
  • 顯示為0x64(十六進制的64)

a的信息詳情

②越界的正數

對于十進制數據 1000_1000_1000,其十六進制為:17 49 0F 82 68

17490F8268

越界截斷可得,被保留下來的為:49 0F 82 68

被截斷490F8268

我們查看內存來驗證一下
驗證
內存上的存儲的確是這樣,將其換算為十進制,就是我們的輸出結果了
結果

(2)對于負數的越界

3.1.3.2 延展閱讀2:補碼的使用

補碼轉換人工求法【非常沒必要,計算機要做的事情為什么要人來做?不過做考試題還是有必要的……】:

  1. 求負數絕對值的原碼后減一【這個減一就很蠢,補碼的使用就是為了避免減法,你居然用減法來避免減法……,但是做考試題確實比用反碼的方法更快】
  2. 對上述結果全部取反
對于負數,計算機以補碼形式來存儲的本質

對于負數:

  1. 計算機先將其轉換為補碼形式
  2. 再進行存儲,如果越界,則會發送越界截斷
①不越界的負數

直接以補碼形式存儲

②越界的負數

先存儲為補碼,然后越界截斷,然后再存儲起來


3.1.4 小結

我通過三種語言的描述,來為你傳到這樣的信號:

  • 不同語言對于越界問題的處理方式是不同的,這是顯而易見的,他們所處的計算機系統層次不一樣,抽象程度也不一樣
  • 毫無疑問,在賦初值的時候就造成越界,這是設計的失敗,這是不可容忍的錯誤

總之,不要越界(后面的小節會講解它也是雙刃劍,可以**“變廢為寶”**)

3.1.4.1 延展閱讀3:在邊界內做事情

待完善部分,敬請期待

3.1.4.2 優化模型——水桶的水不能溢出

對于水桶儲水模型,請回看2.1節的內容,這里通過幾張圖來展示幾種可能的情況
幾種情況

3.1.4.3 一句話總結:做事不能越界

3.2 過程量:做運算

對于運算之后造成的越界問題,參考3.1.3節中的問題部分的解答即可

3.2.1 數學運算(加減乘除……)

不管是高級語言,還是匯編語言,在進行數學運算的時候都可能產生越界的問題——兩個數字都沒有越界,但是相加之后越界了

設計者一定要考慮并且避免這些問題的發生,否則可能會引發錯誤。

3.2.2 數據類型的強制轉換

3.2.2.1 手動強制轉換

數據的強制轉換也可能引發錯誤,比如:在java中,將int類型的數字轉換為byte類型,由高向低轉換,就可能引起數據的丟失。

例如下列Java代碼

int a = 300;
byte b = (byte)a;
System.out.println(b);

輸出為:
result
原因分析:
對于原數字,被保存為0x12C(十六進制前綴為“0x”),強制轉換為byte類型,則會發生越界截斷,將最高位的1截斷,變成了0x2C,也就是十進制的44

3.2.2.2 自動強制轉換

另外,在C/C++、Java中,有一類二元運算符,比如

  • +=
  • -=
  • *=
  • /=
    例如x += y,它的本質是x = x + y,由于y的數據類型并不確定,因此可能會產生錯誤,比如:
int x = 3;
x = x + 3.5;

這是不被允許的,x + 3.5是float類型,不能直接賦值給int類型,這時候需要進行強制轉換x = (int)(x + 3.5),得到的結果是6

對于上述二元運算符來說,這個強制轉換是自動進行的

int x = 20;
x += 3.5;

對于第二條語句,并不等價于x = x + 3.5而是等價于x = (int)(x + 3.5)

3.3 結束量:得結果

3.3.1 直接輸出

對于得到的結果,直接輸出,那么就是越界丟失之后的結果,沒什么好說的。

如果直接在輸出函數的參數內進行運算,那么越界與否取決于實際的環境,看情況而定,數據的結果一定要在范圍內!

3.3.2 結果被保存到其他變量中

如果運算得到的結果被保存到了其他變量中,如果將大的數據,保存到小容器中,顯然會越界

4 雙刃劍——越界截斷的利弊分析

4.1 避開弊端

從專業詞語來說,越界丟失更適合稱為越界截斷,越界的部分將會被計算機截斷,從而造成了丟失
幾種情況
毫無疑問,數據的丟失是可怕的,因此,大多數情況下,尤其是程序員,要盡可能的避免發生越界截斷

4.2 壞事變好:應用越界截斷——補碼的使用

從哲學的角度來說,任何事情都有兩面性,如果我們利用好越界截斷,也能讓它發揮巨大的作用。

計算機有加法器,但是它不擅長減法,于是

  • 補碼+越界截斷

就完成了減法轉換為加法這一壯舉!

例如:45 + (-22) = 23
在計算機中,以補碼形式存儲,用補碼進行加減
45的補碼:

00101101

-22的補碼:

11101010

補碼相加:

100010111

發生越界截斷:

被截斷00010111

得到:

00010111

也就是23的補碼

**但是,務必注意:**使用補碼進行運算,運算結果也一定要在范圍內,否則依然是錯誤。

5 注意事項:先確定正確的界限,才能分析越界截斷

比如下面這個例子,如果你把它的界限弄錯,那么你可能會得到錯誤的結果。

char a = 100;
char b = 28;
char c = a+b;
cout << dec << (int)c << endl;unsigned char d = a+b;
cout << dec << (int)d << endl;

會輸出
輸出
顯然,a+b并不會越界

10000000

但是,同樣是char類型,一個是有符號數,一個是無符號數,輸出的結果卻不一樣。

這是因為

  • 對于有符號數來說,它的界限的7位,因為要除去符號位
  • 對于無符號數來說,它的界限是8位,不需要除去符號位

說到這里,你也就明白,數據的界限是討論越界截斷的前提

因此設計者要綜合考慮很多問題,這也是計算機科學家的基本素養。

6 綜合闡述

  • 任何計算機程序都是由各種數據構成的
  • 各種數據又擁有不同的數據類型

因此:數據只要在對應數據類型的范圍內,就不會發生錯誤

最終結果就是,保證數據在數據類型的范圍內運行即可,對于補碼運算而言,中間過程發生越界是沒有問題的,但是結果不能越界,上面一大堆分析完全可以不用看(不要打我……分析有助于你未來思考更深入的問題,光記住結論是走不遠的)。

7 延展閱讀匯總

待補充

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384781.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384781.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384781.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

進程常用指令 (從創建到回收 包含守護)

進程 常用命令及基本介紹 ps -ef 查看所有進程信息 &#xff08;一般需要配合管道使用&#xff09; ps aux 查看進程信息 且顯示進程狀態 狀態&#xff1a; R 運行態 正在運行或可運行 D 等待態 不可中斷 S 等待態 可中斷 T 停止態 Z 僵尸態 可追加&#xff1a; 前臺運…

【VS C++ 2010】查看內存的方法詳解

1 示例代碼 對于以下代碼&#xff1a; int main() {int a 100010001000;int b 100;cout << "a " << a << " " << &a << endl;cout << "b " << b << " " << &b…

二級C選擇知識點(部分)

二級C 循環隊列是隊列的順式存儲結構 雙向鏈表是鏈表的順式存儲結構 普通鏈表是鏈式存儲結構 非線性結構可采用順式也可采用鏈式 線性結構是只有一個根結點 每個節點最多有一個 帶鏈隊列可以不連續 且隊頭指針可大于也可小于隊尾指針 在鏈表中 雙向鏈表和循環鏈表都有兩個…

【匯編語言】上機實驗 win7/8/10 64位系統 進入32位DOS模式 實現dubug/edit/masm/link功能

1 軟件下載和安裝 下載并安裝DOSBox軟件&#xff0c;注意&#xff0c;不要裝在C盤上&#xff0c;裝在其他盤上 【備注】軟件直接百度搜索即可下載Debug.exe文件 【備注】百度搜索“Debug 64位 下載” 對于下載后得到的debug.exe文件 將這個文件拷貝到磁盤根目錄下&#xff0c…

ntohs(), ntohl() , htons(), htonl(), inet_ntoa(), inet_pton(), atoi()匯總

在C/C寫網絡程序的時候&#xff0c;往往會遇到字節的網絡順序和主機順序的問題。這是就可能用到htons(), ntohl(), ntohs()&#xff0c;htons()這4個函數。 網絡字節順序與本地字節順序之間的轉換函數&#xff1a; htonl()--"Host to Network Long" ntohl()--"N…

【數字邏輯 Verilog】全面剖析數據選擇器——從基礎到拓展,從理論到設計的實現,從表面到本質

0 前言 0.1 使用環境 EDA工具&#xff1a;Vivado 2017.4硬件描述語言&#xff1a;Verilog HDL 0.2 涉及知識 數字邏輯Verilog 1 基礎模塊&#xff1a;一位四選一數據選擇器 1.1 設計部分&#xff1a;層次建模 1.1.1 需求分析 設計一個一位的四選一數據選擇器&#xff0…

exec函數族(部分 最常用的)

進程調用exec函數族執行某個程序 進程當前程序被執行程序替換 讓父子進程執行不同的程序 父進程創建子進程 子進程調用exec函數族 父進程不受影響 #include<unistd.h> int execl(const char *path, const char *arg, ...) int execlp(const char *file, const cha…

【計算機網絡】手動配置hosts文件解決使用GitHub和Coursera網站加載慢/卡的問題

目錄0 前言1 打開hosts1.1 以管理員身份運行記事本1.2 打開hosts2 找到實際地址2.1 打開cmd2.2 找到網址3 替換地址3.1 修改hosts文件3.2 刷新4 后續內容的完善0 前言 本文是針對純小白讀者&#xff0c;沒有涉及到任何的專業知識&#xff0c;你只需要按照步驟操作即可。 同時…

【匯編語言】鏡像遷移能力之一通百通——由代碼段和CS:IP的原理,掌握一類寄存器的使用

0 前言 你應該知道8086CPU的物理地址形成方式及其原理&#xff0c;才能完成本文的學習。 1 內存的分段 對于內存&#xff0c;人們人為地將其劃分為一段一段的&#xff0c;比如代碼段和數據段等&#xff0c;特別注意&#xff0c;這是人為劃分的結果&#xff0c;方面人類使用&…

線程間通信————同步

同步 是指多個任務按照約定的先后次序 相互配合完成一件事情 信號量&#xff1a; 由信號量決定 線程是繼續執行 還是阻塞等待 信號量代表某種資源 其值表示系統中該資源的數量 信號量是一個受保護的量 只能通過特定的三種操作來訪問 初始化 P操作&#xff08;申請資源&…

【計算機組成原理 數字邏輯 Verilog】32位加法器的實現:支持整數的加減運算

目錄0 前言0.1 使用環境0.2 知識點0.3 注意事項1 建模&#xff1a;1位加法器1.1 構建基礎模型1.1.1 一位加法器1.1.1.1 科技黑箱&#xff1a;外部端口與功能1.1.1.2 揭秘黑箱&#xff1a;內部結構與模塊1.1.2 從頂層模塊提取低層模塊&#xff1a;取反功能選擇器1.1.2.1 科技黑箱…

線程間通信————互斥

互斥 臨界資源 一次只允許一個任務&#xff08;進程&#xff0c;線程)訪問的共享資源 臨界區 訪問臨界資源的代碼 互斥機制 mutex互斥鎖 任務訪問臨界資源前申請鎖 訪問完后釋放鎖 互斥鎖初始化 #include <pthread.h> int pthread_mutex_init(pthread_mutex_t *mute…

【Verilog HDL】門級描述 / 數據流描述 / 行為級描述——通過四選一多路選擇器,實現對于不同層級描述方式的整體性認知

目錄0 前言1 輸出端口的設計1.1 門級描述和數據流描述1.2 行為級描述2 三種描述方式的整體架構2.1 門級描述2.2 數據流描述2.3 行為級描述2.4 補充&#xff1a;獨立的語句2.5 小結3 理解三種描述方式的本質3.1 門級描述3.2 數據流描述3.3 行為級描述4 理解不同抽象層級描述方式…

線程創建-結束-回收 教程

ps aux -L 查看線程信息 且顯示進程狀態 使用進程的缺點: 進程切換 系統開銷較大 開銷大的原因 &#xff1a;切換時需要頻繁刷新 cache(類似于緩沖區) 和TLB linux不區分線程 進程 線程其實也屬于進程 只不過是特殊的進程 是一種可以共享地址空間的進程 使用線程的優點&#x…

【匯編語言】匯編實驗IDE(集成開發環境):RadASM的安裝和使用說明

0 前言 本文適合8086CPU的指令集。 對于重要的專業基礎課程&#xff0c;匯編語言&#xff0c;做實驗是必不可少的&#xff0c;但是由于匯編語言本身的缺陷&#xff0c;現代計算機并不能直接運行匯編語言程序&#xff0c;因此&#xff0c;一般老師會要求我們 使用虛擬機&…

【匯編語言】理解8086CPU中,不同類型的寄存器和匯編指令規則的聯系(會繼續更新)

0 前言 你是否因為匯編指令繁雜的規則而苦惱呢&#xff1f;作者本人也很煩&#xff0c;因為往往教材中只告訴我們規則&#xff0c;卻不告訴我們為什么&#xff0c;沒有原因就直接記憶&#xff0c;負擔太大&#xff0c;后期靈活運用也增添阻力&#xff0c;因此&#xff0c;我經…

System V IPC之信號燈

信號燈也叫信號量 用于進程/線程同步或互斥的機制 信號燈的類型 1.Posix 無名信號燈 2.Posix 有名信號燈 3.System V 信號燈 信號燈的含義 計數信號燈&#xff08;1和2都是&#xff09; System V信號燈是一個或多個計數信號燈的集合&#xff08;可操作集合中的多個信號燈&…

【VS 2017 C語言 匯編語言】如何使用VS 2017,通過反匯編查看C語言代碼對應的32位x86匯編語言 VS 2017單步調試的使用

0 前言 本文適用于VS的大多數版本&#xff0c;本文以VS 2017為例進行講解。 1 編輯C語言代碼 首先&#xff0c;在VS編譯器中&#xff0c;創建項目&#xff0c;敲一段C語言代碼&#xff0c;這個過程不解釋了&#xff0c;如果不會請百度。 #include <stdio.h> #include…

System V IPC之共享內存

共享內存是一種最為高效的進程間通信方式&#xff0c;進程可以直接讀寫內存&#xff0c; 而不需要任何數據的拷貝 共享內存在內核空間創建&#xff0c; 可以被進程映射到用戶空間訪問 由于多個進程可同時訪問共享內存 &#xff0c; 因此需要同步和互斥機制配合使用 共享內存的使…

【匯編語言】結合C語言,使用VS 2017調試模式下的反匯編工具學習32位x86匯編指令

0 前言 簡要說明x86系列指令集的整體概況與變化。 我給到你補充學習內容&#xff1a;使用VS學習匯編語言的教程 1 8086CPU到現代CPU的變化 做一些了解即可&#xff0c;不是絕對的&#xff0c;取決于設計工藝以及用途&#xff0c;不同計算機不一樣也正常。 1.1 CPU位數與地…