《匯編語言:基于X86處理器》第7章 整數運算(3)

本章將介紹匯編語言最大的優勢之一:基本的二進制移位和循環移位技術。實際上,位操作是計算機圖形學、數據加密和硬件控制的固有部分。實現位操作的指令是功能強大的工具,但是高級語言只能實現其中的一部分,并且由于高級語言要求與平臺無關,所以這些指令在一定程度上被弱化了。本章將展示一些對移位操作的應用,包括乘除法的優化。

并非所有的高級編程語言都支持任意長度整數的運算。但是匯編語言指令使得它能夠加減幾乎任何長度的整數。本章還將介紹執行壓縮十進制整數和整數字符串運算的專用指令。

7.5 ASCI和非壓縮十進制運算

(7.5節討論的指令只能用于32位模式編程。)到目前為止,本書討論的整數運算處理的都是二進制數。雖然CPU用二進制運算,但是也可以執行ASCI十進制串的運算。使用后者進行運算,對用戶而言既便于輸入也便于在控制臺窗口顯示,因為不用進行二進制轉換假設程序需要用戶輸人兩個數,并將它們相加。若用戶輸人3402和1256,則程序輸出如下所示:

輸入第一個數:3402

輸入第二個數:1256

和 數: 4658

有兩種方法可以計算并顯示和數:

1)將兩個操作數都轉換為二進制,進行二進制加法,再將和數從二進制轉換為ASCII數字串。

2)直接進行數字串的加法,按序相加每對ASCI數字(2+6、0+5、4+2、3+1)。和數為ASCII數字串,因此可以直接顯示在屏幕上。

第二種方法需要在執行每對ASCI數字相加后,用特殊指令來調整和數。有四類指令用于處理 ASCII加法、減法、乘法和除法,如下所示:

AAA

(執行加法后進行 ASCI 調整)

AAM

(執行乘法后進行 ASCI 調整)

AAS

(執行減法后進行 ASCII 調整)

AAD

(執行除法前進行 ASCII 調整)

ASCII 十進制數和非壓縮十進制數 非壓縮十進制整數的高4位總是為零,而ASCII十進制數的高4位則應該等于0011b。在任何情況下,這兩種類型的每個數字都占用一個字節。下面的例子展示了3402用這兩種類型存放的格式:

盡管ASCI運算執行速度比二進制運算要慢很多,但是它有兩個明顯的優點:

●不必在執行運算之前轉換串格式。

●使用假設的十進制小數點,使得實數操作不會出現浮點運算的舍入誤差的危險。

ASCII 加減法運行操作數為ASCI格式或非壓縮十進制格式,但是乘除法只能使用非壓縮十進制數。

7.5.1 AAA 指令

在 32位模式下,AAA(加法后的ASCI調整)指令調整ADD或ADC指令的二進制運算結果。設兩個ASCI數字相加,其二進制結果存放在AL中,則AAA將AL轉換為兩個非壓縮十進制數字存人AH和AL。一旦成為非壓縮格式,通過將AH和AL與30h進OR運算,很容易就能把它們轉換為 ASCII碼。

下例展示了如何用AAA指令正確地實現ASCI數字8加2。在執行加法之前,必須把AH清零,否則它將影響AAA執行的結果。最后一條指令將AH和AL轉換為ASCI數字:

mov ah, 0
mov al, '8'							;AX = 0038h
add al, '2'							;AX = 006Ah
aaa									;AX = 0100h(結果進行ASCII調整)
or ax, 3030h						;AX = 3130h ='10'(轉換為ASCII碼)

使用 AAA 實現多字節加法

現在來查看一個過程,其功能為實現包含了隱含小數點的ASCII十進制數值相加。由于每次數字相加的進位標志位都要傳遞到更高位,因此,過程的實現要比想象的更復雜一些。下面的偽代碼中,acc代表的是一個8位的累加寄存器:

esi (index)=length of first number - 1
edi (index)=length of first number
ecx =lengthoffirst number
set carry value to 0
Loopacc = first number[esi]add previous carry to accsave carry in carrylacc += second_number[esi]OR the carry with carry1sum[edi] = accdec edi
Until ecx == 0
Store last carry digit in sum

進位值必須總是被轉換為ASCI碼。將進位值與第一個操作數相加時,就需要用AAA來調整結果。程序清單如下:

;ASCII_add.asm   ASCII加法
;對有隱含固定小數點的串執行ASCII運算。INCLUDE Irvine32.incDECIMAL_OFFSET = 5								;距離串右側的偏移量
.data
decimal_one BYTE '100123456789765'		        ;1001234567.89765
decimal_two BYTE '900402076502015'		        ;9004020765.02015
sum BYTE (SIZEOF decimal_one + 1) DUP(0), 0.code
main PROC;從最后一個數字位開始mov esi, SIZEOF decimal_one - 1mov edi, SIZEOF decimal_onemov ecx, SIZEOF decimal_onemov bh, 0										;進位值清零
L1:	mov ah, 0											;執行加法前清除AHmov al, decimal_one[esi]						;取第一個數字add al, bh										;加上之前的進位值aaa												;調整和數AH=進位值mov bh, ah										;將進位保存到carry1or bh, 30h										;將其轉換為ASCII碼add al, decimal_two[esi]						;加第二個數字aaa												;調整和數AH=進位值or bh, ah										;進位值與 carry1進行 OR運算or bh, 30h										;將其轉換為ASCII 碼or al, 30h										;將AL轉換為ASCII碼mov sum[edi], al								;將AL保存到sumdec esi											;后退一個數字dec edi												loop L1mov sum[edi], bh								;保存最后的進位值;顯示和數字符串。mov edx, OFFSET sumcall WriteStringcall CrlfINVOKE ExitProcess,0
main ENDP
END main

程序輸出如下所示,和數沒有顯示十進制小數點:

7.5.2 AAS 指令

32位模式下,AAS(減法后的ASCII調整)指令緊隨SUB或SBB指令之后,這兩條指令執行兩個非壓縮十進制數的減法,并將結果保存到AL中。AAS指令將AL轉換為ASCII碼的數字形式。只有減法結果為負時,調整才是必需的。比如,下面的語句實現ASCI碼數字8減去9:

;7.5.2.asm  7.5.2 AAS 指令
;下面的語句實現ASCI碼數字8減去9:.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
val1 BYTE '8'
val2 BYTE '9'.code
main PROCmov ah, 0mov al, val1					;AX = 0038hsub  al, val2					;AX = 00FFhaas								;AX = 0FF09hpushf							;保存進位標志位or al, 30h						;AX = 0FF39hpopf							;恢復進位標志位INVOKE ExitProcess,0
main ENDP
END main

執行SUB指令后,AX等于00FFh。AAS指令將AL轉換為09h,AH減1等于FFh并且把進位標志位置1。

7.5.3 AAM 指令

32位模式下,MUL執行非壓縮十進制乘法,AAM(乘法后的ASCII調整)指令轉換由其產生的二進制乘積。乘法只能使用非壓縮十進制數。下面的例子實現5乘以6,并調整AX中的結果。調整后,AX=0300h,非壓縮十進制表示為30:

;7.5.3.asm  7.5.3 AAM指令
;下面的例子實現5乘以6,并調整AX中的結果。
;調整后,AX=0300h,非壓縮十進制表示為30:.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
ascVal BYTE 05h, 06h.code
main PROCmov bl, ascVal						;第1個操作數mov al, [ascVal+1]					;第2個操作數mul bl								;AX=001Eh aam									;AX=0300h INVOKE ExitProcess,0
main ENDP
END main

7.5.4 AAD 指令

32位模式下,AAD(除法之前的ASCII調整)指令將AX中的非壓縮十進制被除數轉換為二進制,為執行DIV指令做準備。下面的例子把非壓縮0307h轉換為二進制數,然后除以5。DIV指令在AL中生成商07h,在AH中生成余數02h:

;7.5.4.asm  7.5.4 AAD指令
;下面的例子把非壓縮0307h轉換為二進制數,然后除以5。
;DIV指令在AL中生成商07h,在AH中生成余數02h:.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
quotient BYTE ?
remainder BYTE ?.code
main PROCmov ax, 0307h					;被除數aad								;AX = 0025hmov bl, 5						;除數div bl							;AX=0207hmov quotient, almov remainder, ahINVOKE ExitProcess,0
main ENDP
END main

7.5.5 本節回顧

1.編寫一條指令,將 AX中的一個兩位非壓縮十進制整數轉換為十進制的 ASCII碼。

答:or ax, 3030h

2.編寫一條指令,將 AX中的一個兩位 ASCII碼十進制整數轉換為非壓縮十進制形式

答:and ax, 0F0Fh

3.編寫有兩條指令的序列,將 AX中的一個兩位 ASCII 碼十進制整數轉換為二進制。

答:and ax, 0F0Fh ;轉換為非壓縮形式

aad

4.編寫一條指令,將 AX中的一個無符號二進制整數轉換為非壓縮十進制數。

答:aam

7.6 壓縮十進制運算

(7.6節討論的指令僅用于32位編程模式。)壓縮十進制數的每個字節存放兩個十進制數字,每個數字用4位表示。如果數字個數為奇數,則最高的半字節用零填充。存儲大小可變:

bcd1 QWORD 2345673928737285h		;十進制數 2345673928737285
bcd2 DWORD 12345678h				;十進制數12345678
bcd3 DWORD 08723654h				;十進制數8723654
bcd4 WORD 9345h						;十進制數9345
bcd5 WORD 0237h						;十進制數237
bcd6 BYTE 34h						;十進制數34

壓縮十進制存儲至少有兩個優勢:

●數據幾乎可以包含任何個數的有效數字。這使得以很高的精度執行計算成為可能

●實現壓縮十進制數與 ASCII碼之間的相互轉換相對簡單。

DAA(加法后的十進制調整)和DAS(減法后的十進制調整)這兩條指令調整壓縮十進制數加減法的結果。可惜的是,目前還沒有與乘除法有關的相似指令。在這些情況下,相乘或相除的數必須是非壓縮的,執行后再壓縮。

7.6.1 DAA 指令

32位模式下,ADD或ADC指令在AL中生成二進制和數,DAA(加法后的十進制調整)指令將和數轉換為壓縮十進制格式。比如,下述指令執行壓縮十進制數35加48。二進制和數(7Dh)被調整為83h,即35和48的壓縮進制和數。

mov al, 35h			
add al, 48h			;AL=7Dh
daa					;AL=83h(調整后的結果)

DAA的內部邏輯請參閱Intel指令集參考手冊。示例 下面的程序執行兩個16位壓縮十進制整數加法,并將和數保存在一個壓縮雙字中。加法要求和數變量的存儲大小比操作數多一個數字:

;AddPacked.asm   7.6.1  DAA指令   壓縮十進制示例
;下面的程序執行兩個16位壓縮十進制整數加法,并將和數保存在一個壓縮雙字中。
;加法要求和數變量的存儲大小比操作數多一個數字:INCLUDE Irvine32.inc.data
packed_1 WORD 4536h
packed_2 WORD 7207h
sum DWORD ?.code
main PROC;初始化和數與索引:mov sum, 0mov esi, 0;低字節相加。mov al, BYTE PTR packed_1[esi]add  al, BYTE PTR packed_2[esi]daamov BYTE PTR sum[esi], al;高字節相加,包括進位標志位。inc esimov al, BYTE PTR packed_1[esi]adc  al, BYTE PTR packed_2[esi]daamov BYTE PTR sum[esi], al;若還有進位,則加上該進位值。inc esimov al, 0adc  al, 0mov BYTE PTR sum[esi], al;用十六進制顯示和數,mov eax, sumcall WriteHexcall Crlfexit;INVOKE ExitProcess,0
main ENDP
END main

顯然,這個程序包含重復代碼,因此建議使用循環結構。本章的一道習題將會要求編寫一個過程,實現任意大小的壓縮十進制整數加法。

7.6.2 DAS指令

32位模式下,SUB或SBB指令在AL中生成二進制結果,DAS(減法后的十進制調整)指令將其轉換為壓縮十進制格式。比如,下面的語句計算壓縮十進制數85減48,并調整結果:

mov bl, 48h							
mov al, 85h							
sub al, bl						;AL = 3Dh
das								;AL = 37h (調整后)

DAS的內部邏輯請參閱Intel指令集參考手冊.

7.6.3 本節回顧

1.舉例說明,什么情況下DAA指令會把進位標志位置1?

答:當壓縮十進制加法的和數大于99時,DAA將進位標志位置1,例如:

;7.6.3_1.asm  7.6.3   本節回顧
;1.舉例說明,什么情況下DAA指令會把進位標志位置1?.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.code
main PROCmov al, 56hadd  al, 92h				;AL = E8hdaa							;AL = 48h, CF = 1INVOKE ExitProcess,0
main ENDP
END main

2.舉例說明,什么情況下DAS指令會把進位標志位置1?

答:若從小的壓縮十進制整數中減去大的壓縮十進制整數,則DAS將進位標志位置1.例如:

;7.6.3_2.asm  7.6.3   本節回顧
;2.舉例說明,什么情況下DAS指令會把進位標志位置1?.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.code
main PROCmov al, 56hsub  al, 92h				;AL = C4hdas							;AL = 64h, CF = 1INVOKE ExitProcess,0
main ENDP
END main

3.兩個長度為"字節的壓縮十進制整數相加時,和數應該保留多少字節?

答:和數應該保留n+1個字節。

7.7 本章小結

與前面章節介紹的位元指令一樣,移位指令也是匯編語言最顯著的特點之一。一個數移位就意味著把它的位元進行右移或左移。

SHL(左移)指令把目標操作數的每一位都向左移動,最低位用0填充。SHL最大的作用之一是快速實現與2的冪相乘。任何操作數左移位即為乘以2"。SHR(右移)指令則把每一位都向右移動,最高位用0填充。任何操作數右移位即為除以2"。

SAL(算術左移)和SAR(算術右移)是特別為有符號數移位設計的指令。

ROL(循環左移)指令把每一位向左移動,并將最高位復制到進位標志位和最低位。ROR(循環右移)指令把每一位向右移動,并將最低位復制到進位標志位和最高位。

RCL(帶進位循環左移)指令把每一位都左移,并先將進位標志位復制到移位結果的最低位,再將最高位復制到進位標志位。RCR(帶進位循環右移)指令把每一位都右移,并將最低位復制到進位標志位,而進位標志位則復制到結果的最高位。

x86處理器可使用的SHLD(雙精度左移)和SHRD(雙精度右移)指令對大數的移位非常有用。

32位模式下,MUL指令實現一個8位、16位或32位的操作數與AL、AX或EAX相乘64位模式下,一個數還可以實現與RAX寄存器相乘。IMUL指令執行有符號數乘法,它有三種格式:單操作數、雙操作數和三操作數。

32位模式下,DIV指令實現8位、16位或32位操作數的除法。64位模式下,還可以實現 64位除法。IDIV指令執行有符號數乘法,其格式與DIV指令相同。

CBW(字節轉字)指令把AL的符號位擴展到AH寄存器。CDO(雙字轉四字)指令把EAX的符號位擴展到EDX寄存器。CWD(字轉雙字)指令把AX的符號位擴展到DX寄存器。

擴展加減法是指加減任意大小的數,ADC和SBB指令可以用于實現這種加減運算ADC(帶進位加法)指令實現源操作數與進位標志位的內容和目的操作數相加。SBB(帶借位減法)指令實現目的操作數減去源操作數和進位標志位的值。

ASCII十進制數每個字節存放一個數字,并編碼為ASCI形式。AAA(加法后的ASCII調整)指令將ADD或ADC指令的二進制結果轉換為ASCII十進制。AAS(減法后的ASCII調整)指令將SUB或SBB指令的二進制結果轉換為ASCII十進制。所有這些指令都只能用于32位模式。

非壓縮十進制數每個字節存放一個十進制數字,表現為二進制數值。AAM(乘法后的ASCII 調整)指令轉換的是MUL指令執行非壓縮十進制數乘法所生成的二進制結果。AAD(除法前的 ASCI 調整)指令在執行 DIV指令之前,將非壓縮十進制被除數轉換為二進制。所有這些指令都只能用于32位模式。

壓縮十進制數每個字節存放兩個十進制數字。DAA(加法后的十進制調整)指令轉換的是 ADD或 ADC指令執行壓縮十進制加法所生成的二進制結果。DAS(減法后的十進制調整)指令轉換的是SUB或SBB指令執行壓縮十進制減法所生成的二進制結果。所有這些指令都只能用于 32 位模式,

7.8 關鍵術語

7.8.1 術語

7.8.2 指令、運算符和偽指令


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

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

相關文章

應用筆記|數字化儀在醫學SS-OCT中的應用

引言近些年來,OCT(光學相干斷層掃描,Optical Coherence Tomography)作為一種非破壞性3D光學成像技術逐漸在醫學眼科設備中流行起來。OCT可提供實時一維深度或二維截面或三維立體的圖像,分辨率可達微米(μm&…

Ubuntu 22.04與24.04 LTS版本對比分析及2025年使用建議

Ubuntu 22.04與24.04 LTS版本對比分析及2025年使用建議 在2025年的技術環境下,Ubuntu 22.04和24.04 LTS各有優勢,選擇哪一個取決于具體應用場景和用戶需求。經過對系統內核、桌面環境、軟件生態、生命周期支持等多方面因素的綜合分析,本報告將…

Linux進程的生命周期:狀態定義、轉換與特殊場景

前言 在Linux系統中,進程是資源分配和調度的基本單位,而進程狀態則是理解進程行為的關鍵。從運行中的任務(TASK_RUNNING)到僵尸進程(EXIT_ZOMBIE),每個狀態都反映了進程在內核調度、資源等待或父…

神經網絡簡介

大腦的基本計算單位是神經元(neuron)。人類的神經系統中大約有860億個神經元,它們被大約10^14-10^15個突觸(synapses)連接起來。下面圖表的左邊展示了一個生物學的神經元,右邊展示了一個常用的數學模型。每…

多路由協議融合與網絡服務配置實驗(電視機實驗)

多路由協議融合與網絡服務配置實驗文檔 一、實驗用途和意義 (一)用途 本實驗模擬企業復雜網絡環境,整合 OSPF、RIPv2 動態路由協議,結合 DHCP、FTP、Telnet 服務配置及訪問控制策略,實現多區域網絡互聯、服務部署與…

在指定conda 環境里安裝 jupyter 和 python kernel的方法

在 Conda 的指定環境中安裝 Jupyter 和 Python Kernel 是一個常見操作,以下是詳細步驟,確保在指定環境中正確配置 Jupyter 和 Python Kernel: 1. 準備工作 確保已安裝 Anaconda 或 Miniconda,Conda 環境管理工具可用。確認已創建或計劃使用的 Conda 環境。2. 步驟:安裝 J…

【數據結構與算法】數據結構初階:詳解順序表和鏈表(四)——單鏈表(下)

🔥個人主頁:艾莉絲努力練劍 ?專欄傳送門:《C語言》、《數據結構與算法》、C語言刷題12天IO強訓、LeetCode代碼強化刷題 🍉學習方向:C/C方向 ??人生格言:為天地立心,為生民立命,為…

Java+AI精準廣告革命:實時推送系統實戰指南

? 廣告推送的世紀難題 用戶反感&#xff1a;72%用戶因無關廣告卸載APP 轉化率低&#xff1a;傳統推送轉化率<0.5% 資源浪費&#xff1a;40%廣告預算被無效曝光消耗 &#x1f9e0; 智能廣告系統架構 &#x1f525; 核心模塊實現&#xff08;Java 17&#xff09; 1. 實時…

JVM組成及運行流程 - 面試筆記

JVM整體架構 JVM&#xff08;Java Virtual Machine&#xff09;是Java程序運行的核心環境&#xff0c;主要由以下幾個部分組成&#xff1a;1. 程序計數器&#xff08;Program Counter&#xff09; 特點&#xff1a;線程私有&#xff0c;每個線程都有獨立的程序計數器作用&#…

JavaEE——線程池

目錄前言1. 概念2. 線程池相關參數3. Executors的使用總結前言 線程是為了解決進程太重的問題&#xff0c;操作系統中進程的創建和銷毀需要較多的系統資源&#xff0c;用了輕量級的線程來代替部分線程&#xff0c;但是如果線程創建和銷毀的頻率也開始提升到了一定程度&#xf…

3 c++提高——STL常用容器(一)

目錄 1 string容器 1.1 string基本概念 1.2 string構造函數 1.3 string賦值操作 1.4 string字符串拼接 1.5 string查找和替換 1.6 string字符串比較 1.7 string字符存取 1.8 string插入和刪除 1.9 string子串 2 vector容器 2.1 vector基本概念 2.2 vector構造函數…

手把手教你用【Go】語言調用DeepSeek大模型

1、首先呢&#xff0c;點擊 “DeepSeek”” 這個&#xff0c; 可以充1塊玩玩。 2、然后獲取api-key 3、替換apiKey const (apiURL "https://api.deepseek.com/v1/chat/completions"apiKey "your api key" // 替換為你的實際 API KeymodelName &…

自動化UI測試工具TestComplete的核心功能及應用

對桌面應用穩定性與用戶體驗的挑戰&#xff0c;手動測試效率低、覆蓋有限&#xff0c;而普通自動化工具常難以應對復雜控件識別、腳本靈活性和大規模并行測試的需求。 自動化UI測試工具TestComplete憑借卓越的對象識別能力、靈活的測試創建方式以及高效的跨平臺并行執行功能&a…

【C/C++】邁出編譯第一步——預處理

【C/C】邁出編譯第一步——預處理 在C/C編譯流程中&#xff0c;預處理&#xff08;Preprocessing&#xff09;是第一個也是至關重要的階段。它負責對源代碼進行初步的文本替換與組織&#xff0c;使得編譯器在后續階段能正確地處理規范化的代碼。預處理過程不僅影響編譯效率&…

快捷鍵——VsCode

一鍵折疊所有的代碼塊 先按 ctrl K&#xff0c;再ctrl 0 快速注釋一行 ctrl /

import 和require的區別

概念 import 是es6 規范&#xff0c;主要應用于瀏覽器和主流前端框架當中&#xff0c;export 導出&#xff0c; require 是 commonjs 規范&#xff0c;主要應用于nodejs環境中&#xff0c;module.exports 導出編譯規則 import 靜態導入是編譯時解析&#xff0c;動態導入是執…

8、鴻蒙Harmony Next開發:相對布局 (RelativeContainer)

目錄 概述 基本概念 設置依賴關系 設置參考邊界 設置錨點 設置相對于錨點的對齊位置 子組件位置偏移 多種組件的對齊布局 組件尺寸 多個組件形成鏈 概述 RelativeContainer是一種采用相對布局的容器&#xff0c;支持容器內部的子元素設置相對位置關系&#xff0c;適…

Linux命令的命令歷史

Linux下history命令可以對當前系統中執行過的所有shell命令進行顯示。重復執行命令歷史中的某個命令&#xff0c;使用&#xff1a;!命令編號&#xff1b;環境變量histsize的值保存歷史命令記錄的總行數&#xff1b;可用echo查看一下&#xff1b;需要大寫&#xff1b;環境變量hi…

【C++小白逆襲】內存管理從崩潰到精通的秘籍

目錄【C小白逆襲】內存管理從崩潰到精通的秘籍前言&#xff1a;為什么內存管理讓我掉了N根頭發&#xff1f;內存四區大揭秘&#xff1a;你的變量都住在哪里&#xff1f;&#x1f3e0;內存就像大學宿舍區 &#x1f3d8;?C語言的內存管理&#xff1a;手動搬磚時代 &#x1f9f1;…

【網絡安全】利用 Cookie Sandwich 竊取 HttpOnly Cookie

未經許可,不得轉載。 文章目錄 引言Cookie 三明治原理解析Apache Tomcat 行為Python 框架行為竊取 HttpOnly 的 PHPSESSID Cookie第一步:識別 XSS 漏洞第二步:發現反射型 Cookie 參數第三步:通過 Cookie 降級實現信息泄露第四步:整合攻擊流程修復建議引言 本文將介紹一種…