.NET Emit 入門教程:第六部分:IL 指令:9:詳解 ILGenerator 指令方法:運算操作指令(指令篇結束)

来源:https://www.cnblogs.com/cyq1162/p/18133417
-Advertisement-
Play Games

在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...


前言:

經過前面幾篇的學習,我們瞭解到指令的大概分類,如:

參數載入指令,該載入指令以 Ld 開頭,將參數載入到棧中,以便於後續執行操作命令。

參數存儲指令,其指令以 St 開頭,將棧中的數據,存儲到指定的變數中,以方便後續使用。

創建實例指令,其指令以 New 開頭,用於在運行時動態生成並初始化對象。

方法調用指令,該指令以 Call 開頭,用於在運行時調用其它方法。

支條件指令,該指令通常以 Br、或 B、C 開頭,用於在運行分支條件時跳轉指令。

類型轉換指令,該指令通常以 Cast、Conv 開頭或box結尾,用於在運行時對類型進行轉換。

本篇介紹運算操作指令,介紹完後,將結束指令篇。

第六部分:IL指令完整大綱目錄如下:

.NET Emit 入門教程:第六部分:IL 指令:1:概要介紹

.NET Emit 入門教程:第六部分:IL 指令:2:詳解 ILGenerator 輔助方法

.NET Emit 入門教程:第六部分:IL 指令:3:詳解 ILGenerator 指令方法:參數載入指令

.NET Emit 入門教程:第六部分:IL 指令:4:詳解 ILGenerator 指令方法:參數存儲指令

.NET Emit 入門教程:第六部分:IL 指令:5:詳解 ILGenerator 指令方法:創建實例指令

.NET Emit 入門教程:第六部分:IL 指令:6:詳解 ILGenerator 指令方法:方法調用指令

.NET Emit 入門教程:第六部分:IL 指令:7:詳解 ILGenerator 指令方法:分支條件指令

.NET Emit 入門教程:第六部分:IL 指令:8:詳解 ILGenerator 指令方法:類型轉換指令

.NET Emit 入門教程:第六部分:IL 指令:9:詳解 ILGenerator 指令方法:運算操作指令(指令篇結束)

運算操作指令介紹:

在.NET Emit 編程中,運算操作指令是一類關鍵的IL(Intermediate Language)指令,用於在動態生成的代碼中執行各種數學運算、位操作和比較操作。

這些指令允許開發人員對操作數進行加法、減法、乘法、除法、邏輯與、邏輯或、邏輯非、位與、位或、位異或、左移、右移以及比較等操作。

通過運算操作指令,開發人員能夠在動態生成的代碼中實現各種算術運算、邏輯運算和位操作,從而更靈活地處理數據和實現複雜的邏輯。

這些指令為動態代碼生成提供了強大的功能,使得開發人員能夠根據需要生成高效且功能豐富的代碼。

運算操作指令的分類:

讓我們按照分類逐一介紹各種指令以及它們的詳細用途。

  1. 算術運算指令:

    • add(加法):將兩個值相加,並將結果推送到計算棧上。主要用於執行整數和浮點數的加法操作。
    • sub(減法):將一個值減去另一個值,並將結果推送到計算棧上。用於執行整數和浮點數的減法操作。
    • mul(乘法):將兩個值相乘,並將結果推送到計算棧上。用於執行整數和浮點數的乘法操作。
    • div(除法):將一個值除以另一個值,並將結果推送到計算棧上。用於執行整數和浮點數的除法操作。
  2. 邏輯運算指令:

    • and(與):對兩個整數進行按位與操作,並將結果推送到計算棧上。用於執行邏輯與操作。
    • or(或):對兩個整數進行按位或操作,並將結果推送到計算棧上。用於執行邏輯或操作。
    • xor(異或):對兩個整數進行按位異或操作,並將結果推送到計算棧上。用於執行邏輯異或操作。
  3. 位操作指令:

    • shl(左移):將一個整數向左移動指定的位數,並將結果推送到計算棧上。用於執行左移操作。
    • shr(右移):將一個整數向右移動指定的位數,並將結果推送到計算棧上。用於執行算術右移操作。
    • not(非):對一個整數進行按位取反操作,並將結果推送到計算棧上。用於執行按位取反操作。
  4. 比較操作指令:

    • ceq(相等比較):比較兩個值是否相等,並將結果推送到計算棧上。用於執行相等比較操作。
    • clt(小於比較):比較一個值是否小於另一個值,並將結果推送到計算棧上。用於執行小於比較操作。
    • cgt(大於比較):比較一個值是否大於另一個值,並將結果推送到計算棧上。用於執行大於比較操作。

這些指令提供了豐富的功能,可以用於執行各種數學運算、邏輯運算、位操作和比較操作,從而實現各種複雜的編程邏輯。在動態生成的代碼中,開發人員可以根據具體需求使用這些指令來實現所需的功能。

接下來,我們對一個指令分類,分別給出一個示例,來介紹它們的基本用法。

對於運行指令,有兩個指令尾碼:

_ovf: 進行溢出檢查。

_un:無符號。

例如:

多數指令都帶有這兩個尾碼,理解這兩個尾碼的意思,可以快速理解所有該尾碼指令。 

1、算術運算指令:

Add 指令:

示例代碼:

 MethodBuilder methodBuilder = tb.DefineMethod("MathTo", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(int),typeof(int) });

 ILGenerator il = methodBuilder.GetILGenerator();

 il.Emit(OpCodes.Ldarg_0);
 il.Emit(OpCodes.Ldarg_1);
 il.Emit(OpCodes.Add_Ovf_Un);

 il.Emit(OpCodes.Ret);     // 返回該值

對應代碼:

其它指令使用方式一樣,省去重覆舉例。

Add 指令對應C#代碼:+
Sub 指令對應C#代碼:-
Mul 指令對應C#代碼:*
Div 指令對應C#代碼:/

2、邏輯運算指令:

 示例代碼:

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.And);

il.Emit(OpCodes.Ret);     // 返回該值

對應代碼:

使用方式和算術指令運行其實一致:

 And 指令對應C#代碼:&
  Or  指令對應C#代碼:|
 Xor  指令對應C#代碼:^

3、位操作指令:

Shl 指令:左移指令,Shift Left 的簡寫

示例代碼:

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4,2);
il.Emit(OpCodes.Shl);

il.Emit(OpCodes.Ret);     // 返回該值

對應代碼: 

使用方式,需要在第二個參數,指定要位移的位數。

右移操作的方式和左移一樣。

Not 指令:按位取反

示例代碼:

MethodBuilder methodBuilder = tb.DefineMethod("MathTo", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(int) });

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Not);

il.Emit(OpCodes.Ret);     // 返回該值

對應代碼:

右移操作的方式和左移一樣,而 Not 指令則不需要第二個參數:

Shl 指令對應C#代碼:<<
Shr 指令對應C#代碼:>>
Not 指令對應C#代碼:~

4、比較操作指令:

Ceq 指令:比較兩個值

 示例代碼:

var dynamicMethod = new DynamicMethod("ConvertTo", typeof(bool), new Type[] { typeof(int), typeof(float) }, typeof(AssMethodIL_Condition));

ILGenerator il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ceq);

il.Emit(OpCodes.Ret);     // 返回該值

var result = dynamicMethod.Invoke(null, new object[] { 11, 11 });
Console.WriteLine(result);
Console.Read();

對應代碼:

運行結果:

其它兩個指令使用方式和 Ceq 一致:

Ceq 指令對應C#代碼:==
Clt 指令對應C#代碼:<
Cgt 指令對應C#代碼:>

如何實現 >= 或 <=

由於沒有對應的指令,所以需要用點小技巧組合,來實現該代碼:

用Clt + Ceq 指令實現:>=

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Clt);

il.Emit(OpCodes.Ldc_I4, 0);
il.Emit(OpCodes.Ceq);

il.Emit(OpCodes.Ret);     // 返回該值

對應代碼:

用Cgt + Ceq 指令實現:<=

ILGenerator il = methodBuilder.GetILGenerator();

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Cgt);

il.Emit(OpCodes.Ldc_I4, 0);
il.Emit(OpCodes.Ceq);

il.Emit(OpCodes.Ret);     // 返回該值

對應代碼:

性能小細節提醒:

平時我們寫代碼,涉及 >= 或 <= 的整數字判斷時候:

比如:a>=2(需要兩條指令),可以寫成 a>3(只要一條指令)。

總結:

在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。

這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。

通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯。

在實際應用中,我們可以利用這些指令來實現諸如加密演算法、數值計算、邏輯判斷、數據壓縮等功能。

通過深入理解和熟練運用這些運算操作指令,開發人員可以提高動態代碼生成的效率和靈活性,從而更好地滿足各種編程需求。

同時,對ILGenerator指令方法的進一步學習也能夠幫助開發人員更加靈活地控制動態生成的代碼,實現更複雜的功能和邏輯。

本篇之後,將進入第七部分:實戰項目

版權聲明:本文原創發表於 博客園,作者為 路過秋天 本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。
個人微信公眾號
Donation(掃碼支持作者):支付寶:
Donation(掃碼支持作者):微信:

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天電腦重啟之後,發現 visual studio 2022 的智能提示與報錯經常性不好用,不光不能在正常時候提示代碼錯誤信息,甚至在編譯過後也不提示錯誤。反覆重啟,剛開始正常,隔一會兒就會提示什麼什麼功能不可用,點開打開詳情,提示:StreamJsonRpc.ConnectionLostExcep ...
  • 通常情況下,PDF文件是不可編輯的,但PDF表單提供了一些可編輯區域,允許用戶填寫和提交信息。PDF表單通常用於收集信息、反饋或進行線上申請,是許多行業中數據收集和交換的重要工具。 PDF表單可以包含各種類型的輸入控制項,如文本框、覆選框、下拉菜單、單選按鈕等。本文將介紹如何使用C# 和一個免費.NE ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...