ARM架構

目錄

哈佛結構

arm指令格式

?有符號數的溢出(8bit)?

無符號數的進位/借位

CPSR(當前程序狀態寄存器)

ARM模式

arm異常類型

?ARMv7架構異常向量表

?arm異常的處理流程

arm寄存器

堆棧指針寄存器

arm模式切換流程

LDR指令、STR指令

指令流水線(三級流水線+馮諾依曼體系)

三級流水線

帶有訪問存儲器指令流水線(LDR/STR)

分支流水線

B/BL

arm立即數編碼規則

arm條件碼表

arm移位操作

邏輯移位vs算術移位

邏輯移位的本質----無論左移還是右移,空出的位均補零,不保留符號信息

LDM/STM指令

?LDM指令:

軟中斷指令

軟中斷的本質

??????? arm Linux系統調用實現

?STM指令

arm尋址方式

多寄存器尋址

堆棧尋址

?標簽label

全局標簽

?定義全局函數

?定義全局變量

?使用場景

局部標簽

引用方式

引用規則

使用場景

弱標簽

?弱標簽的覆蓋原則

使用場景

靜態標簽

靜態標簽的定義

?使用場景

偽指令

NOP偽指令

ADR偽指令

ADRL偽指令

LDR偽指令

LDR偽指令的兩種形式

arm偽操作

匯編調用c程序

?c調用匯編程序

內聯匯編

飽和算術運算:

協處理器

內聯匯編的基本語法


?

哈佛結構

核心特征是將指令存儲數據存儲完全分離,各自使用獨立的存儲器和總線

arm指令格式

arm指令集采用固定長度32位的指令格式

?有符號數的溢出(8bit)

無符號數的進位/借位

CPSR(當前程序狀態寄存器)

ARM模式

  • 用戶模式,用戶程序的工作模式,用戶模式沒有權限去操作其它硬件資源,只能執行處理自己的 數據;

  • 系統模式,首先用戶模式與系統模式共用同一套寄存器,系統模式為特權模式,系統模式可以直接訪問硬件資源

  • svc模式,主要用于完成系統初始化的工作,cpu上電之后默認的工作模式,當調用swi/svc,cpu處于svc模式;

  • 中止模式,當用戶訪問非法內存地址或者訪問某一塊不具有讀寫權限的內存地址時處于此工作模式;

  • Fiq模式 (快速中斷模式),用來處 理對時間要求比較緊急的中斷請求,主要用于高速數據傳輸及通道處理中;

  • IRQ模式(普通中斷模式),用于處理一般的中斷請求,通常在硬件產生中斷信號之后自動進入IRQ模式;

arm異常類型

?ARMv7架構異常向量表

?arm異常的處理流程

arm寄存器

arm處理器在任何工作模式下共用一個PC寄存器(程序計數寄存器)與CPSR寄存器(當前程序狀態寄存器)。

堆棧指針寄存器

?棧按照棧的生長方向(遞增、遞減)與數據的存儲方式(滿棧、空棧)分為四種類型

1. 滿遞增棧 2. 滿遞減棧 3. 空遞增棧 4. 空遞減棧

棧頂指針(sp): 始終指向當前棧的棧頂,即最后一個入棧元素的地址(滿棧)或者 下一個可用空間的地址(空棧)

遞增棧:棧頂向高地址方向增長

遞減棧:棧頂向低地址方向增長

push操作時處理器先減小SP值然后將指定寄存器存儲到SP寄存器指向的存儲器地址

?POP操作時處理器先將SP指向的存儲器地址存儲到指定寄存器中,然后將SP寄存器值增加

arm模式切換流程

在ARM中,當發生異常時,處理器會自動切換到對應的異常模式,每種異常模式都有自己獨立的物理寄存器,R13(SP:堆棧寄存器)、R14(LR:鏈接寄存器)SPSR(備份程序狀態寄存器)。

當從用戶模式進入IRQ模式時,保存需要保護的寄存器到IRQ模式的堆棧,步驟如下:

  1. 用戶程序在用戶模式下運行,使用SP_usr;
  2. 發生中斷,處理器自動切換到IRQ模式,此時SP自動變為SP_irq。
  3. 保存返回地址到LR_irqLR_irq = 當前PC + 4)。

  4. 保存當前CPSR到SPSR_irq

  5. 中斷處理程序開始執行,使用SP_irq指向的堆棧保存寄存器(如R0-R12, LR_irq)
  6. 處理完中斷后,從SP_irq的堆棧中恢復寄存器。
  7. 返回到用戶模式,繼續使用SP_usr。
IRQ_Handler:; 1. 保存用戶模式的寄存器(R0-R12, LR_irq保存的是返回地址)STMFD SP!, {R0-R12, LR}   ; 使用SP_irq壓棧(SP_irq -= 56字節); 2. 處理中斷(如讀取定時器狀態)BL Handle_Timer_Interrupt; 3. 恢復寄存器并返回用戶模式LDMFD SP!, {R0-R12, LR}   ; 從SP_irq彈棧(SP_irq += 56字節)SUBS PC, LR, #4           ; 返回到用戶模式的下一條指令(恢復CPSR)

?

LDR指令、STR指令

LDR指令(Load Register)是用于從內存中加載數據到寄存器的核心指令

?STR指令(Store Register)用于將寄存器中的值存儲到內存中

指令流水線(三級流水線+馮諾依曼體系)

馮諾依曼體系:數據總線只有一根,取指令與取數據采用同一根數據線

三級流水線

帶有訪問存儲器指令流水線(LDR/STR)

LDR指令

? ? ? step1:訪問內存——取數據——數據總線被占用——AND指令被延時(stall)

? ? ? step2:數據寫回寄存器——寫數據——數據總線被占用——其他指令被延時

分支流水線

BL(Branch with Link)指令核心功能是跳轉到目標地址執行子程序,同時將返回地址下一條指令地址保存到鏈接寄存器LR;

B(Branch)指令的核心功能是改變程序執行流程,常用于循環控制(for/while)、條件分支(if-else) 和代碼塊跳轉

B/BL

BL <label> #label中存儲的是目標地址

跳轉地址計算流程:

?eg:

arm立即數編碼規則

ARM立即數采用 "8 位數值 + 4 位循環右移(Rotate Right)"的組合編碼:

arm條件碼表

假設有符號數AB,比較A ≥ B等價于判斷A - B ≥ 0

S = A - B,則

  • S ≥ 0,則S的符號位為 0(N=0)。
  • 若計算過程未溢出(V=0),則N=0直接表示S ≥ 0
  • 若計算過程溢出(V=1),則N=1才表示S ≥ 0(溢出導致符號位反轉)。

A ≥ B的充要條件是:N 與 V 狀態一致(N?V=0)

arm移位操作

邏輯移位vs算術移位

邏輯移位的本質----無論左移還是右移,空出的位均補零,不保留符號信息

算術移位的本質----右移時保留符號位(高位填充原符號位),左移與邏輯左移一致

LDM/STM指令

?LDM指令:

軟中斷指令

軟中斷的本質

  • 主動觸發:與硬件中斷(由外部設備觸發,如鍵盤、時鐘)不同,軟中斷是程序通過顯式執行指令主動發起的。

  • 特權級切換:在保護模式下,軟中斷通常用于從用戶態(低特權級)切換到內核態(高特權級),以便執行受保護的操作(如訪問硬件、管理內存)。

??????? arm Linux系統調用實現

系統調用號操作系統內核為每個系統調用分配的唯一編號!

?STM指令

arm尋址方式

指令如何表達 “去哪里找數據” 或 “把結果存到哪里”?這需要一套規則 —— 即尋址模式

尋址是確定指令中操作數位置的過程。操作數可以存儲在:

1. 寄存器(如 R0~R15)

2. 內存(如變量、數組)

3. 立即數(指令中直接給出的常數)


多寄存器尋址

?

堆棧尋址

push/pop

?標簽label

標簽是一個符號化的地址標記,指向代碼或數據在內存中的位置;

在 ARM Linux 匯編開發中,標簽(Label)的分類主要基于其 作用域(可見性范圍)、鏈接屬性(符號在鏈接階段的行為)以及 符號強弱性(是否允許被覆蓋)可以分為 全局標簽局部標簽靜態標簽弱標簽

全局標簽

使用 .global 偽指令聲明標簽為全局,允許其他文件引用

.global 標簽名       @ 聲明為全局標簽
標簽名:              @ 標簽定義匯編指令
?定義全局函數
@定義一個全局函數 add_two
.global add_two     @ 聲明為全局
add_two:ADD R0, R0, R1  @ R0 = R0 + R1BX  LR          @ 返回
?定義全局變量
.data
.global g_counter   @ 聲明全局變量
g_counter:.word 0x0       @ 初始值為0
?使用場景

局部標簽

在 ARM 匯編中局部標簽是僅在 當前代碼塊或作用域內有效 的臨時符號,用于簡化循環、條件分支等控制邏輯,避免命名沖突。局部標簽通過 數字 + 冒號 定義,并通過 b(backward)和 f(forward) 引用;

  • 定義格式:以數字開頭,后跟冒號(如 1:2:);

  • 作用域:僅在當前代碼塊(如函數或循環體)內有效;

引用方式
  • 1b:向后跳轉(Backward),指向 最近的前一個 1: 標簽。

  • 1f:向前跳轉(Forward),指向 最近的后一個 1: 標簽

引用規則
  • 就近原則:根據 b/f 方向,尋找最近的同名標簽。

  • 可重復使用:同一代碼塊內可多次定義同名局部標簽(如 1:)。

使用場景
.text
.global _start_start:MOV R0, #5        @ 初始化 R0 = 5loop_start:           @ 全局標簽(可選)
1:                    @ 局部標簽1(循環入口)SUBS R0, R0, #1   @ R0 = R0 - 1,更新標志位BEQ 1f            @ 若 R0 == 0,向前跳轉到局部標簽1(循環出口)B   1b            @ 否則,向后跳轉到局部標簽1(繼續循環)1:                    @ 局部標簽1(循環出口)MOV R7, #1        @ 退出系統調用號SVC #0            @ 觸發系統調用

弱標簽

在 ARM 匯編中,弱標簽(Weak Label) 是一種允許 同名符號覆蓋 的標簽類型。它常用于定義 默認實現可選功能,當鏈接器發現同名的 強標簽(Strong Label) 時,會優先使用強標簽的定義,弱標簽的定義則被忽略。

.weak 標簽名       @ 聲明為弱標簽
標簽名:            @ 標簽定義匯編指令
?弱標簽的覆蓋原則
  • 強標簽優先:若存在同名的強標簽(通過 .global 聲明),鏈接時使用強標簽的定義。

  • 無強標簽時生效:若未定義強標簽,鏈接器使用弱標簽的實現。

  • 允許多個弱標簽若多個弱標簽同名,鏈接器隨機選擇其一(通常報警告)。

使用場景

靜態標簽

靜態標簽是僅在 當前匯編文件內有效 的符號,不可被其他文件引用。它的核心作用是 封裝內部實現,避免命名沖突,提升代碼模塊化;

靜態標簽的定義

?使用場景

在文件 utils.s 中定義靜態函數 internal_add,僅在文件內部調用;在 main.s 中嘗試調用該函數將失敗。

偽指令

NOP偽指令

NOP(No Operation)偽指令 核心功能 1. 實現延時 2.?對齊指令地址

ADR偽指令

ADR偽指令 可以獲取程序的運行地址,而不是鏈接地址

ADRL偽指令

注意: 標簽地址必須與ADRL指令位于同一代碼段內

LDR偽指令

LDR偽指令(Pseudo-Instruction)主要功能如下:

  • 加載32位立即數到寄存器;
  • 加載標簽地址到寄存器;
LDR偽指令的兩種形式

?注意:#offset是當前指令地址(PC)到 文字池中目標數據地址 的偏移量

arm偽操作

匯編調用c程序

匯編調用c程序流程
@1 		c文件中實現c語言函數
@2 		.extern偽操作聲明c函數 .extern my_add
@3.1 	根據ATPCS標準,R0,R1,R2,R3用于傳遞參數,由于c語言函數的參數可能超過4個
@3.2  	采用偽指令ldr初始化棧空間
@4    	傳遞參數 mov r0,#0x01
@5    	調用函數 BL/B my_add
 @start.s文件.text.global _start @將_start聲明為全局的.extern my_add_start:@先初始化要使用的棧空間ldr sp, =0x400mov r0, #10mov r1, #20mov r2, #30mov r3, #40mov r5, #50push {r5}bl my_addloop:b loop.data.align 4 @按2^4字節對齊
.space 4096.end
 //add.c文件int my_add(int x, int y, int z, int m, int n) {return x + y + z + m + n;}

?c調用匯編程序

1. 定義匯編函數my_add, 注意傳遞的參數、返回值滿足ATCPS規則
2. 匯編文件中通過.global 把my_add聲明為全局函數
3. C語言中通過extern聲明外部函數my_add
@start.s文件
.text
.global _start
.extern main
_start:ldr sp,=0x400bl main 
.data.align 4.space 4096
loop:b loop
.end
//main.c文件
extern int my_add(int x,int y,int z);
int main()
{int ret=my_add(10,20,30);return ret;
}
@ add.s文件
.arm
.text
.global my_add
my_add:add r5,r0,r1add r5,r5,r2mov r0,r5 @函數的返回值通過R0傳遞
.end

內聯匯編

內聯匯編允許在高級語言(如C/C++)中直接嵌入匯編代碼,內聯匯編的應用場景:

  • 程序中使用飽和算術運算(Saturating Arithmetic)
  • 程序需要操作協處理器;
  • C程序中需要操作程序狀態寄存器;
飽和算術運算:

飽和算術運算是一種在數值運算中防止溢出的處理方式。當運算結果超出數據類型的表示范圍時,結果會被“飽和”到該數據類型能表示的最大值或最小值;

協處理器

ARM架構通過支持協處理器來擴展處理器的功能。ARM架構的處理器支持最多16個協處理器,通常稱為CP0~CP15;

CP15,提供系統控制功能,主要用于配置MMU、TLB和Cache、異常向量表的地址設置;

內聯匯編的基本語法
//__asm__告知編譯器不用檢查后面的內容,只需要交給匯編器進行處理
__asm__ volatile ("asm code" : 輸出操作數列表 : 輸入操作數列表 : 破壞列表(Clobber List)
);

1. volatile 關鍵字禁止編譯器優化內聯匯編代碼;

2. "asm code"主要用于填寫匯編代碼,用\n\t分隔多行匯編指令;

__asm__ volatile ("add r0, r1, r2\n\t""add r0, r0, r3\n\t""mov r0, r0": /* 輸出操作數列表 */: /* 輸入操作數列表 */: /* 破壞列表 */
);

3. 輸出操作數列表(asm->c/c++)用于指定匯編代碼執行后需要傳遞回 C/C++ 變量的結果,通常只能為變量;

__asm__ volatile ("mov r0, #0xFF":=r(value)       // 將r0的值寫入value:                // 輸入操作數列表:                // 破壞列表
);

每個輸出操作數的格式為 "約束"(變量),多個操作數用逗號分隔,其中約束由兩部分構成,一部分方向修飾符(+,=,&),方向修飾符用于指定該操作數是輸入還是輸出,輸出操作數必須包含 =(表示操作數僅用于輸出等價于只寫)或? +(表示操作數既是輸入又是輸出等價于可讀可寫)& 必須通過 +& 或者 =& 進行使用,另一部分為約束符(r,m),約束符用于指定操作數的存放位置,其中 r 約束(寄存器約束)要求操作數存儲在通用寄存器中,m 約束(內存約束)要求操作數直接存儲在內存地址中,避免通過寄存器中轉;

=r :?輸出到通用寄存器,操作數僅用于寫入

__asm__ volatile ("mov r0, #42" : "=r" (result)
);

結果寫入寄存器 r0,再傳遞給 result

4. 輸入操作數列表(c/c++ -> asm)用于c/c++程序向匯編代碼傳遞數據,輸入操作數的值在匯編代碼中不應被修改只能讀取,因此輸入操作數無需方向修飾符,常用約束符 r(變量值存入通用寄存器)m(變量直接通過內存地址訪問)i(立即數(整數常量)),此外用于定義輸入的參數,可以是變量也可以是立即數;

int a = 10, b = 20;
__asm__ volatile ("add r0, %1, %2\n\t"   // %0, %1, ..., %n表示占位符,先按照輸出操作數的順序進行引用//再按照輸入操作數的順序進行引用"mov %0, r0"           // result = r0: "=r" (result)        // 輸出操作數: result -> %0: "r" (a), "r" (b)     // 輸入操作數:a -> %1, b-> %2: "r0"                 // 破環列表用于告知編譯器哪些寄存器或資源被隱式修改
);

5. 破壞列表告知編譯器哪些寄存器或資源被隱式修改,常見值如下:

  • "cc":條件碼寄存器(CPSR);

  • "memory":表示內存被修改(強制刷新內存緩存);

  • "r0", "r1":指定被破壞的寄存器;

__asm__ volatile ("mov r0, %1\n\t""str r0, [%0]": : "r" (addr), "r" (value): "r0", "memory"  // 聲明破壞 r0 和 memory
);

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

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

相關文章

canvas(三)-動畫3d

在 <canvas> 中實現 3D 動畫通常需要借助 WebGL 技術,因為原生的 2D 上下文(CanvasRenderingContext2D)無法直接支持 3D 渲染。WebGL 是基于 OpenGL ES 2.0 的 JavaScript API,可以直接在瀏覽器中實現高性能的 3D 圖形渲染。以下是關于 <canvas> 3D 動畫的概念…

右鍵打開 pycharm 右鍵 pycharm

文件夾右鍵打開pycharm aaa.reg notepad 右下角把文件格式改為&#xff1a;ansi Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Directory\Background\shell\PyCharm] "Open with PyCharm" "Icon""\"D:\\soft\\PyCharm 2024.1.4\\bi…

一張紙決定的高度

從我捧起《格局》這個本書開始&#xff0c;轉眼間兩個月過去了。 回頭望一望&#xff0c;好似還在昨天。 這兩個月&#xff0c;心態在變&#xff0c;前進的方向在變&#xff0c;但唯一不變的就是每天晚上睡前&#xff0c;留給自己十分鐘的讀書時光。 我也從來沒想過&#xf…

R 語言科研繪圖 --- 熱力圖-匯總

在發表科研論文的過程中&#xff0c;科研繪圖是必不可少的&#xff0c;一張好看的圖形會是文章很大的加分項。 為了便于使用&#xff0c;本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中&#xff0c;獲取方式&#xff1a; R 語言科研繪圖模板 --- sciRplothttps://mp.…

新手到資深的Java開發編碼規范

新手到資深的開發編碼規范 一、前言二、命名規范&#xff1a;代碼的 “第一印象”2.1 標識符命名原則2.2 命名的 “自描述性” 原則2.3 避免魔法值 三、代碼格式規范&#xff1a;結構清晰的視覺美學3.1 縮進與空格3.2 代碼塊規范3.3 換行與斷行 四、注釋規范&#xff1a;代碼的…

鴻蒙倉頡開發語言實戰教程:實現商城應用詳情頁

昨天有朋友提到鴻蒙既然有了ArkTs開發語言&#xff0c;為什么還需要倉頡開發語言。其實這個不難理解&#xff0c;安卓有Java和Kotlin&#xff0c;iOS先后推出了Objective-C和Swift&#xff0c;鴻蒙有兩種開發語言也就不奇怪了。而且倉頡是比ArkTs更加靈活的語言&#xff0c;雖然…

CNN手寫數字識別/全套源碼+注釋可直接運行

數據集選擇&#xff1a; MNIST數據集來自美國國家標準與技術研究所, National Institute of Standards and Technology (NIST)。訓練集&#xff08;training set&#xff09;由來自250個不同人手寫的數字構成&#xff0c;其中50%是高中學生&#xff0c;50%來自人口普查局&…

探秘谷歌Gemini:開啟人工智能新紀元

一、引言 在人工智能的浩瀚星空中&#xff0c;每一次重大模型的發布都宛如一顆璀璨新星閃耀登場&#xff0c;而谷歌 Gemini 的亮相&#xff0c;無疑是其中最為耀眼的時刻之一。它的出現&#xff0c;猶如在 AI 領域投下了一顆重磅炸彈&#xff0c;引發了全球范圍內的廣泛關注與熱…

小白場成長之路-計算機網絡(三)

文章目錄 一、網絡參數配置1.圖形化配置2.命令行配置2.1、ifconfig命令2.2ifup和ifdown子接口配置 2.3 多ip地址配置2.4子接口配置 總結 一、網絡參數配置 1.圖形化配置 NetworkManager&#xff0c;Linux7系統中&#xff0c;一般建議停止該管理方式&#xff1b;Linux8以上操作…

WireShark網絡抓包—詳細教程

本文僅用于技術研究&#xff0c;禁止用于非法用途。 Wireshark入門指南&#xff1a;從零開始掌握網絡抓包分析 一、Wireshark是什么&#xff1f; Wireshark 是全球最受歡迎的開源網絡協議分析工具&#xff0c;被廣泛應用于網絡故障排查、協議學習、網絡安全分析等領域。它支…

區塊鏈DApp的開發技術方案

區塊鏈DApp開發技術方案&#xff1a;架構設計與實踐指南 引言&#xff1a;DApp的技術革新與生態價值 區塊鏈技術的去中心化特性與智能合約的自動化執行能力&#xff0c;推動DApp&#xff08;去中心化應用&#xff09;成為Web3.0的核心載體。截至2025年&#xff0c;全球DApp用…

Linux(3)——基礎開發工具

目錄 一、軟件包管理器——yum 1.Linux下安裝程序的方式 2.什么是yum 3.查找軟件包 4.安裝軟件 5.本地與服務器端進行文件互傳 6.卸載軟件 二、Linux的編輯器——vim 1.基本概念 2.vim下各個模式之間的切換 3.vim在命令行模式下的命令匯總 4.vim在底行模式下的命令…

大數據學習(121)-sql重點問題

&#x1f34b;&#x1f34b;大數據學習&#x1f34b;&#x1f34b; &#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 用力所能及&#xff0c;改變世界。 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4dd;支持一…

【QT】QString和QStringList去掉空格的方法總結

目錄 一、QString去掉空格 1. 移除字符串首尾的空格&#xff08;trimmed&#xff09; 2. 移除字符串中的所有空格&#xff08;remove&#xff09; 3. 僅移除左側&#xff08;開頭&#xff09;或右側&#xff08;結尾&#xff09;空格 4. 替換多個連續空格為單個空格 5. 移…

電腦 IP 地址修改工具,輕松實現異地登陸

在互聯網時代&#xff0c;異地登陸需求日益頻繁 —— 訪問區域限制內容、跨區協作、優化游戲體驗等場景&#xff0c;都需要通過修改 IP 地址實現。 一、IP 地址基礎認知 IP 地址是設備的網絡身份標識&#xff0c;不同地區分配不同 IP 段。通過修改 IP&#xff0c;可模擬目標地…

[BUG]Debian/Linux操作系統中 安裝 curl等軟件顯示無候選安裝(E: 軟件包 curl 沒有可安裝候選)

本文內容組織形式 問題描述失效原因解決方案首先修改源列表為國內確認當前系統的版本Debian 11 (Bullseye)Debian 12 (Bookworm) 執行系統升級更新系統重新安裝curl 結語 問題描述 日期&#xff1a;20250526 操作系統&#xff1a; debian darkchunkdebian:/home$ sudo apt i…

leetcode hot100刷題日記——12.反轉鏈表

解答&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(n…

JavaSE核心知識點04工具04-01(JDK21)

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 JavaSE核心知識點04工具04-01&#xff08;JD…

數據庫入門:以商品訂單系統為例

數據庫入門&#xff1a;以商品訂單系統為例 一、前言 數據庫是現代軟件開發中不可或缺的基礎&#xff0c;掌握數據庫的基本概念和操作&#xff0c;是每個開發者的必經之路。本文將以“商品-品牌-客戶-訂單-訂單項”為例&#xff0c;帶你快速入門數據庫的核心知識和基本操作。…

UE失落方舟特效學習 筆記01

通過法線扭曲貼圖 Begin Object Class/Script/UnrealEd.MaterialGraphNode Name"MaterialGraphNode_0" ExportPath"/Script/UnrealEd.MaterialGraphNode/Engine/Transient.M_RadialUV_01:MaterialGraph_0.MaterialGraphNode_0"Begin Object Class/Script/E…