計組(2)CPU與指令

一、總體認識CPU

1、軟硬件角度

? ? ? ? CPU,全稱就是中央處理器。從硬件上來說,CPU是一個超大規模集成電路,通過電路實現加法、乘法乃至各種各樣的處理邏輯。從軟件來說,CPU就是一個執行各種計算機指令的邏輯機器。

2、計算機指令

????????所謂的計算機指令,其實就是CPU能聽懂的語言,我們可以叫做機器語言。不同的CPU能夠聽懂的語言也是不一樣的。例如,一般的電腦所用的是Intel的CPU,而蘋果手機用的是ARM的CPU。這兩種CPU各自支持的語言,就是兩組不同的計算機指令集。

? ? ? ? 所以,我們在電腦上寫的一個C語言程序,經過編譯、匯編之后形成exe文件,把這個文件復制到手機上一般是沒法正常運行的。而把這臺電腦上的exe文件復制到另一個相同OS的電腦上,是可以正常運行的。

3、存儲程序型計算機

? ? ? ? 一個計算機程序,一般有很多指令組成,但是CPU里不能一直放著所有指令(CPU中主要用于存放當前正在執行即將執行的指令和數據。),所以計算機程序平時是存儲在存儲器中的(這個存儲器一般稱之為內存或主存)。

二、簡單了解編譯與匯編

1、整體過程

????????平時編寫的代碼,到底是怎么變成一條條計算機指令,最后被 CPU 執行的?以一段C語言程序舉例:

????????

// test.c
int main()
{int a = 1; int b = 2;a = a + b;
}

????????要讓這段程序在一個 Linux 操作系統上跑起來,我們需要把整個程序翻譯成一個匯編語言(ASM,Assembly Language)的程序,這個過程我們一般叫編譯(Compile)成匯編代碼。

????????針對匯編代碼,我們可以再用匯編器(Assembler)翻譯成機器碼(Machine Code)。這些機器碼由“0”和“1”組成的機器語言表示。這一條條機器碼,就是一條條的計算機指令。這樣一串串的 16 進制數字,就是我們 CPU 能夠真正認識的計算機指令。????????

????????在一個 Linux 操作系統上,我們可以簡單地使用 gcc 和 objdump 這樣兩條命令,把對應的匯編代碼和機器碼都打印出來。

$ gcc -g -c test.c
$ objdump -d -M intel -S test.o

????????結果如下:

test.o:     file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
int main()
{0:   55                      push   rbp1:   48 89 e5                mov    rbp,rspint a = 1; 4:   c7 45 fc 01 00 00 00    mov    DWORD PTR [rbp-0x4],0x1int b = 2;b:   c7 45 f8 02 00 00 00    mov    DWORD PTR [rbp-0x8],0x2a = a + b;12:   8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]15:   01 45 fc                add    DWORD PTR [rbp-0x4],eax
}18:   5d                      pop    rbp19:   c3                      ret    

????????可以看到,左側有一堆數字,這些就是一條條機器碼;右邊有一系列的 push、mov、add、pop 等,這些就是對應的匯編代碼。一行 C 語言代碼,有時候只對應一條機器碼和匯編代碼,有時候則是對應兩條機器碼和匯編代碼。匯編代碼和機器碼之間是一一對應的。

? ? ? ? 小問題:為什么要經過匯編而不是把代碼直接編譯成機器碼?因為匯編代碼其實就是“給程序員看的機器碼”,也正因為這樣,機器碼和匯編代碼是一一對應的。我們人類很容易記住 add、mov 這些用英文表示的指令,而 8b 45 f8 這樣的指令,由于很難一下子看明白是在干什么,所以會非常難以記憶。所以編譯、匯編的整體過程如下:

? ? ? ? 但其實,這里是有更深層次的原因。將編譯過程劃分為“編譯器 -> 匯編器”兩步,而不是直接從高級語言生成機器碼,主要是出于軟件工程上的考量,即模塊化、可移植性和簡化設計

????????編譯器和匯編器各自的任務是解耦的:

這樣分工的好處是:

2、簡單解析指令與機器碼

(1)匯編語言的指令分類

①算數類指令

????????我們的加減乘除,在 CPU 層面,都會變成一條條算術類指令。

②數據傳輸類指令

? ? ? ? 給變量賦值、在內存里讀寫數據,用的都是數據傳輸類指令。

③邏輯類指令

? ? ? ? 邏輯上的與或非。

④條件分支類指令

? ? ? ? 類似"if/else"編譯形成的指令

⑤無條件跳轉指令

????????寫一些大一點的程序,我們常常需要寫一些函數或者方法。在調用函數的時候,其實就是發起了一個無條件跳轉指令。

(2)機器碼是怎樣生成的

????????不同的 CPU 有不同的指令集,也就對應著不同的匯編語言和不同的機器碼。這里以MIPS指令集為例(MIPS 是一組由 MIPS 技術公司在 80 年代中期設計出來的 CPU 指令集)

????????MIPS 的指令是一個 32 位的整數,高 6 位叫操作碼(Opcode),也就是代表這條指令具體是一條什么樣的指令,剩下的 26 位有三種格式,分別是 R、I 和 J。

????????R 指令是一般用來做算術和邏輯操作,里面有讀取和寫入數據的寄存器的地址。如果是邏輯位移操作,后面還有位移操作的位移量,而最后的功能碼,則是在前面的操作碼不夠的時候,擴展操作碼表示對應的具體指令的。

????????I 指令,則通常是用在數據傳輸、條件分支,以及在運算的時候使用的并非變量還是常數的時候。這個時候,沒有了位移量和操作碼,也沒有了第三個寄存器,而是把這三部分直接合并成了一個地址值或者一個常數。

????????J 指令就是一個跳轉指令,高 6 位之外的 26 位都是一個跳轉后的地址。

? ? ? ? 以一個簡單的add指令為例:

add $t0, $s2, $s1

? ? ? ? 這個指令的含義是,將s2寄存器和s1寄存器中的值相加,放到t0寄存器中。

????????這條指令對應的?MIPS 指令里 opcode 是 0,rs 代表第一個寄存器 s1 的地址是 17,rt 代表第二個寄存器 s2 的地址是 18,rd 代表目標的臨時寄存器 t0 的地址,是 8。因為不是位移操作,所以位移量是 0。把這些數字拼在一起,就變成了一個 MIPS 的加法指令。

????????為了讀起來方便,我們一般把對應的二進制數,用 16 進制表示出來。在這里,也就是 0X02324020。這個數字也就是這條指令對應的機器碼。

? ? ? ? 小拓展:區分是R、I、J指令主要就是看 前 6 位的 opcode 字段。opcode = 0幾乎是所有 R 型,真正的操作由 funct 字段決定。opcode ≠ 0->I型(區別不同 I 型指令)。opcode = 0x02(j) 或 0x03(jal)->J型。

3、python和java的執行

????????除了 C 這樣的編譯型的語言之外,不管是 Python 這樣的解釋型語言,還是 Java 這樣使用虛擬機的語言,其實最終都是由不同形式的程序,把我們寫好的代碼,轉換成 CPU 能夠理解的機器碼來執行的。只是解釋型語言,是通過解釋器在程序運行的時候逐句翻譯,而 Java 這樣使用虛擬機的語言,則是由虛擬機對編譯出來的中間代碼進行解釋,或者即時編譯成為機器碼來最終執行。

三、CPU執行指令的過程

? ? ? ? 以Intel的CPU為例,里面差不多有幾百億個晶體管。實際上,一條條計算機指令執行起來非常復雜。但是在 CPU 在軟件層面已經為我們做好了封裝。對于我們這些做軟件的程序員來說,我們只要知道,寫好的代碼變成了指令之后,是一條一條順序執行的就可以了。

????????邏輯上,我們可以認為,CPU 其實就是由一堆寄存器組成的。而寄存器就是 CPU 內部,由多個觸發器(Flip-Flop)或者鎖存器(Latches)組成的簡單電路。(觸發器和鎖存器,其實就是兩種不同原理的數字電路組成的邏輯門。)

????????N 個觸發器或者鎖存器,就可以組成一個 N 位(Bit)的寄存器,能夠保存 N 位的數據。比方說,我們用的 64 位 Intel 服務器,寄存器就是 64 位的。(沒錯,一個寄存器就是這么小,換算成高級語言中相當于一個32位整型或64位長整型。但是寄存器只是用來保存當前正在計算的數據,不像內存需要存儲程序等)

1、CPU的幾種寄存器

一個 CPU 里面會有很多種不同功能的寄存器。這里介紹三種比較重要、特殊的。

(1)PC寄存器

????????我們也叫指令地址寄存器。顧名思義,它就是用來存放下一條需要執行的計算機指令的內存地址。

(2)指令寄存器

????????用來存放當前正在執行的指令。

(3)條件碼寄存器

????????用里面的一個一個標記位(Flag),存放 CPU 進行算術或者邏輯計算的結果。

(4)其他寄存器

????????除了這些特殊的寄存器,CPU 里面還有更多用來存儲數據和內存地址的寄存器。這樣的寄存器通常一類里面不止一個。我們通常根據存放的數據內容來給它們取名字,比如整數寄存器、浮點數寄存器、向量寄存器和地址寄存器等等。有些寄存器既可以存放數據,又能存放地址,我們就叫它通用寄存器。

2、執行指令(順序)

????????一個程序執行的時候,CPU 會根據 PC 寄存器里的地址,從內存里面把需要執行的指令讀取到指令寄存器里面執行,然后根據指令長度自增,開始順序讀取下一條指令。可以看到,一個程序的一條條指令,在內存里面是連續保存的,也會一條條順序加載。

? ? ? ? 注意:PC寄存器自增(包括后面所說的更新),一般是在CPU的指令周期(取指 → 譯碼 → 執行 → 寫回)的取指階段

  • CPU 取到當前指令時,就會把 PC 自增(例如 +4)到下一條指令地址。

  • 如果當前指令是跳轉/分支類指令(如 jmpbeq),那么譯碼/執行階段可能會修改 PC 的值(覆蓋掉剛才的 +4)。

????????而有些特殊指令,比如 J 類指令,也就是跳轉指令,會修改 PC 寄存器里面的地址值。這樣,下一條要執行的指令就不是從內存里面順序加載的了。

3、指令的跳轉——條件語句

????????下面是一個簡單的包含條件判斷if...else...的指令:

// test.c#include <time.h>
#include <stdlib.h>int main()
{srand(time(NULL));int r = rand() % 2;int a = 10;if (r == 0){a = 1;} else {a = 2;} 

????????我們用 rand 生成了一個隨機數 r,r 要么是 0,要么是 1。當 r 是 0 的時候,我們把之前定義的變量 a 設成 1,不然就設成 2。

? ? ? ? 用以下代碼生成匯編代碼:

$ gcc -g -c test.c
$ objdump -d -M intel -S test.o 
    if (r == 0)3b:   83 7d fc 00             cmp    DWORD PTR [rbp-0x4],0x03f:   75 09                   jne    4a <main+0x4a>{a = 1;41:   c7 45 f8 01 00 00 00    mov    DWORD PTR [rbp-0x8],0x148:   eb 07                   jmp    51 <main+0x51>}else{a = 2;4a:   c7 45 f8 02 00 00 00    mov    DWORD PTR [rbp-0x8],0x251:   b8 00 00 00 00          mov    eax,0x0} 

????????可以看到,這里對于 r == 0 的條件判斷,被編譯成了 cmp 和 jne 這兩條指令。

????????cmp 指令比較了前后兩個操作數的值,這里的 DWORD PTR 代表操作的數據類型是 32 位的整數,而[rbp-0x4]則是變量 r 的內存地址。所以,第一個操作數就是從內存里拿到的變量 r 的值。第二個操作數 0x0 就是我們設定的常量 0 的 16 進制表示。cmp 指令的比較結果,會存入到條件碼寄存器當中去。

????????在這里,如果比較的結果是 True,也就是 r == 0,就把零標志條件碼(對應的條件碼是 ZF,Zero Flag)設置為 1。除了零標志之外,Intel 的 CPU 下還有進位標志符號標志以及溢出標志,用在不同的判斷條件下。

????????cmp 指令執行完成之后,PC 寄存器會自動自增,開始執行下一條 jne 的指令。

????????跟著的 jne 指令,是 jump if not equal 的意思,它會查看對應的零標志位。如果 ZF 為 1,說明上面的比較結果是 TRUE,則繼續往下順序執行;如果是 ZF 是 0,也就是上面的比較結果是 False,會跳轉到后面跟著的操作數 4a 的位置。這個 4a,對應這里匯編代碼的行號,也就是上面設置的 else 條件里的第一條指令。當跳轉發生的時候,PC 寄存器就不再是自增變成下一條指令的地址,而是被直接設置成這里的 4a 這個地址。這個時候,CPU 再把 4a 地址里的指令加載到指令寄存器中來執行。

????????跳轉到執行地址為 4a 的指令,實際是一條 mov 指令,第一個操作數和前面的 cmp 指令一樣,是另一個 32 位整型的內存地址,以及 2 的對應的 16 進制值 0x2。mov 指令把 2 設置到對應的內存里去,相當于一個賦值操作。然后,PC 寄存器里的值繼續自增,執行下一條 mov 指令。

????????這條 mov 指令的第一個操作數 eax,代表累加寄存器,第二個操作數 0x0 則是 16 進制的 0 的表示。這條指令其實沒有實際的作用,它的作用是一個占位符。我們回過頭去看前面的 if 條件,如果滿足的話,在賦值的 mov 指令執行完成之后,有一個 jmp 的無條件跳轉指令。跳轉的地址就是這一行的地址 51。我們的 main 函數沒有設定返回值,而 mov eax, 0x0 其實就是給 main 函數生成了一個默認的為 0 的返回值到累加器里面。if 條件里面的內容執行完成之后也會跳轉到這里,和 else 里的內容結束之后的位置是一樣的。

? ? ? ? 指令可以往后跳轉也可以向前跳轉——這就是for/while循環實現的原理。

4、指令的跳轉——循環語句

????????下面是段簡單的c語言for循環指令:

int main()
{int a = 0;for (int i = 0; i < 3; i++){a += i;}
}

????????循環自增變量 i 三次,三次之后,i>=3,就會跳出循環。整個程序,對應的 Intel 匯編代碼就是這樣的:

    for (int i = 0; i <= 2; i++)b:   c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x012:   eb 0a                   jmp    1e {a += i;14:   8b 45 f8                mov    eax,DWORD PTR [rbp-0x4]17:   01 45 fc                add    DWORD PTR [rbp-0x8],eax1a:   83 45 f8 01             add    DWORD PTR [rbp-0x4],0x11e:   83 7d f8 02             cmp    DWORD PTR [rbp-0x4],0x222:   7e f0                   jle    14 24:   b8 00 00 00 00          mov    eax,0x0}

????????對應的循環也是用 1e 這個地址上的 cmp 比較指令,和緊接著的 jle 條件跳轉指令來實現的。主要的差別在于,這里的 jle 跳轉的地址,是在這條指令之前的地址 14,而非 if…else 編譯出來的跳轉指令之后。往前跳轉使得條件滿足的時候,PC 寄存器會把指令地址設置到之前執行過的指令位置,重新執行之前執行過的指令,直到條件不滿足,順序往下執行 jle 之后的指令,整個循環才結束。

? ? ? ? 小拓展:jne和jle

????????在 x86 匯編 里,像 jnejle 這樣的條件跳轉指令,本身并不會做比較運算,它們只是檢查標志寄存器 (EFLAGS)(這個寄存器叫做條件碼寄存器) 的狀態。而這個狀態一般需要由 cmp 指令 或者 test 指令 先設置。

5、總結

? ? ? ? 對于多條指令,除了簡單地通過 PC 寄存器自增的方式順序執行外,條件碼寄存器會記錄下當前執行指令的條件判斷狀態,然后通過跳轉指令讀取對應的條件碼,修改 PC 寄存器內的下一條指令的地址,最終實現 if…else 以及 for/while 這樣的程序控制流程。

????????雖然我們可以用高級語言,可以用不同的語法,比如 if…else 這樣的條件分支,或者 while/for 這樣的循環方式,來實現不同的程序運行流程,但是回歸到計算機可以識別的機器指令級別,其實都只是一個簡單的地址跳轉而已,也就是一個類似于 goto 的語句。

????????想要在硬件層面實現這個 goto 語句,除了本身需要用來保存下一條指令地址,以及當前正要執行指令的 PC 寄存器、指令寄存器外,我們只需要再增加一個條件碼寄存器,來保留條件判斷的狀態。這樣簡簡單單的三個寄存器,就可以實現條件判斷和循環重復執行代碼的功能。

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

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

相關文章

用Java讓家政服務觸手可及

家政服務不僅僅包括日常保潔&#xff0c;隨著社會的發展&#xff0c;從日常保潔、衣物清潔到家電維修、月嫂保姆&#xff0c;家政服務的場景越發多元。用戶不僅追求服務的 “專業度”&#xff0c;更看重 “便捷性”—— 能否快速找到服務、預約服務、了解服務效果&#xff1f;上…

Python OpenCV圖像處理與深度學習:Python OpenCV特征檢測入門

特征檢測與描述&#xff1a;探索圖像中的關鍵點 學習目標 通過本課程&#xff0c;學員們將掌握特征檢測的基本概念&#xff0c;了解如何使用OpenCV庫中的SIFT和SURF算法進行特征點檢測和特征描述符的計算。實驗將通過理論講解與實踐操作相結合的方式&#xff0c;幫助學員深入理…

ECDH (橢圓曲線迪菲-赫爾曼密鑰交換)

文章目錄一、什么是ECDH&#xff1f;二、為什么需要 ECDH&#xff1f;要解決什么問題&#xff1f;三、原理與圖示四、核心比喻&#xff1a;混合顏料五、技術實現步驟1. 約定公共參數2. 生成密鑰對3. 交換公鑰4. 計算共享密鑰5. 密鑰派生六、注意事項七、安全性基礎八、優勢特點…

Spring Boot實戰:打造高效Web應用,從入門到精通

目錄一、Spring Boot 初相識二、搭建開發環境2.1 安裝 JDK2.2 安裝 IDE&#xff08;以 IntelliJ IDEA 為例&#xff09;2.3 初始化 Spring Boot 項目三、Spring Boot 基礎配置3.1 配置文件詳解&#xff08;application.properties 和 application.yml&#xff09;3.2 自定義配置…

2025網絡安全宣傳周知識競賽答題活動怎么做

網絡安全答題PK小程序可以結合競技性、趣味性和知識性&#xff0c;設計以下核心功能模塊&#xff0c;提升用戶參與度和學習效果&#xff1a;一、核心PK功能實時對戰匹配 隨機匹配在線用戶&#xff08;按段位/積分相近原則&#xff09; 好友定向PK&#xff08;支持分享邀請對戰&…

echo、seq、{}、date、bc命令

文章目錄echo、seq、{}、date、bc命令echo案例seq命令案例{}花括號列表擴展序列擴展嵌套擴展datebc(高精度計算器)echo、seq、{}、date、bc命令 echo echo命令是一個常用的Shell命令&#xff0c;用于在終端上輸出文本。它的基本語法如下&#xff1a; echo [option] [string]…

Vue2之Vuex

文章目錄 數據準備新建項目選擇模塊安裝vscode工具打開 刪除無用文件刪除src/assets文件下的所有內容刪除src/components文件下的所有內容修改src/app.vuevscode運行項目 一、 概述1.是什么2. 使用場景3.優勢4 Vuex流程圖5.注意&#xff1a; 二、需求: 多組件共享數據創建三個組…

2025具身智能賽道觀察:技術、產業與視頻基礎設施

引言 2025 年&#xff0c;具身智能&#xff08;Embodied Intelligence&#xff09;毫無疑問已經成為全球資本追逐的“風口賽道”。從人形機器人、無人配送&#xff0c;到低空經濟和智能駕駛&#xff0c;幾乎所有與物理世界深度結合的領域&#xff0c;都被納入具身智能的廣義范…

【商業銀行風控模型(python版本,實操合集,附帶anaconda安裝教程,持續更新)】

Anaconda&#xff08;Python工具&#xff09;安裝1.Mac中安裝Anaconda2.點擊“Free Download”下載后&#xff0c;點擊“Skip registration”&#xff0c;跳過注冊環節。 3.conda list4.安裝完成Anaconda基本操作命令 # 查看當前虛擬環境下的所有包 conda list # 查看某個特定的…

FPGA DDR 地址映射-黃金法則

FPGA 中 DDR 控制器的地址映射順序&#xff08;Address Mapping Order&#xff09; 是優化設計速度&#xff08;帶寬和效率&#xff09; 的關鍵。簡單來說&#xff0c;地址映射順序決定了線性地址如何映射到 DDR 芯片內部的物理結構&#xff08;Bank、Row、Column&#xff09;。…

網絡安全設備監控指標

網絡安全設備監控指標 近日看到一篇設備情況匯報&#xff0c;內容寫得有些欠缺&#xff0c;因此我特意問了一下AI&#xff0c;整理了一下思路。以下是監控需要關注的性能指標。權當拋磚引玉。根據指標可以做監控&#xff0c;也可以做調研指標。 業務承載能力 吞吐量&#xff08…

JSP程序設計之JSP指令

1、JSP指令概念與分類 &#xff08;1&#xff09;概念 JSP指令相當于在編譯期間的命令&#xff0c;用來設置與整個JSP頁面相關的屬性&#xff0c;它并不直接產生任何可見的輸出&#xff0c;用來設置全局變量、聲明類、要實現的方法和輸出內容的類型等。在JSP文件被解析為Java…

Generative Art with p5.js: Creating Beauty from Code

Are you ready to make something truly beautiful with p5.js? Forget about boring bar charts and sales data—let’s create art that moves, breathes, and responds to your touch. We’re going to explore generative art, where code becomes your paintbrush and a…

Wi-Fi技術——網絡安全

一、數據幀的安全 1、無線網絡安全的發展 理論上無線電波范圍內的任何一個站點都可以監聽并登錄無線網絡&#xff0c;所有發送或接收的數據&#xff0c;都有可能被截取&#xff0c;因此無線網絡安全十分重要。 原始802.11的安全策略為WEP&#xff0c;其存在根本性的漏洞&#x…

Java提供高效后端支撐,Vue呈現直觀交互界面,共同打造的MES管理系統,含完整可運行源碼,實現生產計劃、執行、追溯一站式管理,提升制造執行效率

前言在當今競爭激烈的制造業環境中&#xff0c;企業面臨著提高生產效率、降低成本、保證產品質量以及快速響應市場變化等多重挑戰。制造執行系統&#xff08;MES&#xff0c;Manufacturing Execution System&#xff09;作為連接企業上層計劃管理系統&#xff08;如ERP&#xf…

【macOS】垃圾箱中文件無法清理的常規方法

【macOS】垃圾箱中文件無法清理的方法如果外接 SSD 移動盤上的垃圾文件無法刪除&#xff0c; 可能是由于文件系統格式不兼容、文件被占用、權限不足等原因導致的&#xff0c; 以下是一些常見的解決方法&#xff1a;檢查移動硬盤文件系統格式&#xff1a;如果移動硬盤是 NTFS 格…

鴻蒙ArkTS 核心篇-15-條件渲染(組件)

目錄 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 預覽效果 總結 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 let num: number 20Entry Component struct Index {build() {Column() {if (num 1) {Text(文本 1)} …

大模型微調顯存內存節約方法

大模型微調時節約顯存和內存是一個至關重要的話題&#xff0c;尤其是在消費級GPU&#xff08;如RTX 3090/4090&#xff09;或資源有限的云實例上。下面我將從顯存&#xff08;GPU Memory&#xff09; 和內存&#xff08;CPU Memory&#xff09; 兩個方面&#xff0c;為你系統地…

Linux筆記12——shell編程基礎-6

字符截取命令一、cut命令功能&#xff1a;用于從文件或標準輸入中提取指定字段或列語法&#xff1a;cut [選項] 文件名-f&#xff1a;列號&#xff0c;提取第幾列&#xff0c;默認識別制表符分割出來的列&#xff08;列號之間用,隔開&#xff09;-d&#xff1a;分隔符&#xff…

高效瀏覽器標簽頁管理:Chrome擴展開發完全指南

Hi&#xff0c;我是前端人類學&#xff08;之前叫布蘭妮甜&#xff09;&#xff01; 在信息過載的時代&#xff0c;瀏覽器標簽頁管理已成為提高工作效率的關鍵技能。本文將介紹如何開發一個功能完整的Chrome擴展&#xff0c;幫助用戶高效管理瀏覽器標簽頁&#xff0c;并探討其實…