匯編語言中的數據

在匯編語言中,程序都是由指令流構成的,而指令一般是由操作符和操作數組成的,操作符是CPU用來完成某項功能的操作,而操作數是操作符所處理加工的對象。比如:add eax, 42,add是執行一個加法運算的操作符,是把eax中的值和常數42相加,并保存到eax中,而指令中的操作數,如常數42和存放在eax寄存器中的數值。

在高級語言中,數據本身帶有類型信息,比如C語言中,6是一個整型(int)的值,'6’是字符型(char)的值,而"6"就是字符串類型的值,再比如變量:int a,那么在內存地址“&a”中存放的數據是有符號int整型數據。而在匯編語言中,如果脫離開指令上下文環境單獨看待它們,它們僅僅是一個二進制的數據,并沒有具體的意義,也就是它們沒有類型信息,一個數據只有出現在指令中,作為操作數進行操作時才知道它所表示的意義,同一個數據用在不同形式的指令中,可能表示不同的類型。

注,本文以x86-64處理器的匯編語言說明,匯編指令的格式是Intel風格,下面內容均為個人觀點。

1、如何表述數據?

既然在匯編語言中,數據自身沒有類型信息,那么,如何來表述它們呢?描述數據有三個要素:位置、長度和內容。

位置,就是表示數據存放在哪兒,以及怎么才能找到它?數據只能存放在三個地方:指令中、寄存器中和內存中。

長度,就是數據它占有多大的存放空間。比如數據可以占用1字節、2字節、4字節、8字節、16字節等2的次冪大小的空間,如果是存放在內存中,也可以是3字節、5字節、6字節、乃至n字節大小的空間,比如表示串操作的數組、字符串等數據。

內容,就是指它所表示的是什么。同一個數據可能表示一個字符、整型數、浮點數、地址等,取決于數據用作什么指令的操作數,也就是數據表示什么是根據所處的上下文環境決定的,所表示的是什么和操作它的指令息息相關。

顯然,長度和內容對應了高級語言中的類型,比如在C/C++中聲明short data,則表示data長度占用2個字節,表示的是范圍在-37768~37767之間的整型數,data的位置取決于定義的場合:可以在棧中、堆中,數據區、常量區等。在匯編語言中,如果數據存放在內存中的話,比如[rax],寄存器rax中存放64位的地址,rax可以對應高級語言的void*指針,只是一個位置地址,如果沒有相關的前綴信息比如dword ptr,是不知道所指向的數據的長度,也不知道表示的是什么。

下面分別看一下它們在匯編語言中是如何表示的。

2、數據位置-放在什么地方?

在匯編語言中,數據就存在于三個地方:

1、位于指令中
是一個常量,也叫立即數,一般會被編碼到指令中,成為指令的一部分。 它只能用作指令的源操作數,比如指令mov eax, 42,源數據42位于指令中。

下面是這條指令編譯完之后的二進制指令流,就是這條mov指令匯編完之后的二進制數據b82a000000,在執行時,CPU要把這個二進制指令流放在執行引擎中執行,在譯碼時就能從中得到數據42。
在這里插入圖片描述
我們知道,十進制數字42對應的16進制是0x2a,而b8表示把4字節的二進制數據存入寄存器eax,指令的其余部分2a000000就是數字42,是個4字節長度的數據。

立即數一般來源自高級程序中的const int、constexpr int、整數字面量等,但高級程序中的常量也不一定都會當作立即數位于指令中,有時候也會位于只讀數據區,存放于內存中。

2、位于寄存器中
數據存放在通用寄存器中,它可以用作源操作數和目的操作數。比如:

add eax, edx

加法操作add有兩個操作數,數據分別存放在寄存器eax和edx中,CPU在執行時,執行引擎會從這兩個寄存器中得到數據。

3、位于內存中
指定的是數據在內存中的位置,可以用作源操作數或目的操作數,但不能同時用作源和目的操作數。所在內存位置最常見的表示形式是:[64位寄存器±偏移量],比如[rax+4],寄存器rax的值表示一個內存地址,假設是0x8000000000,把它加上4之后,也就是在0x80000000004內存位置。

3、數據長度-占多大的地方?

數據的長度信息表示,和它存放在哪兒有關,在不同的地方有不同的長度表示方式。

1、立即數
長度取決于字面形式源操作數和目的操作數的長度,一般都是1、2、4、8字節的長度。例如,對于0x42這個立即數,如果目的數是單字節長度,它在指令中是單字節長度,如果目的數是2字節長度,它在指令中的長度是2字節,如果目的數是4、8字節長度,它在指令中的長度是4字節;對于0x4200這個立即數,如果目的數是2字節長度,它在指令中的長度是2字節,如果目的數是4、8字節長度,它在指令中的長度是4字節;對于0x4200000000這個立即數,在指令中只能是8字節長度。

2、寄存器
長度取決于寄存器的大小,就以累加寄存器ax、eax、rax系列以及SIMD寄存器為例:

寄存器 1字節bit長度可能對應的C/C++類型
al18char、unit8_t、int8_t
ax216short、uint_16、int_16
eax432int、uint32_t、int32_t、float
rax864long long、uint64_t, int64_t、double
rdx:rax組合16128struct {int64_t, int64_t}、int64_t[2]、double[2]
ymm16128int8_t[16]、int16_t[8]、int32_t[4]、int64_t[2]、float[4]、double[2]
ymm32256int8_t[32]、int16_t[16]、int32_t[8]、int64_t[4]、float[8]、double[4]
zmm64512int8_t[64]、int16_t[32]、int32_t[16]、int64_t[8]、float[16]、double[8]

即,如果一個數據存放在寄存器eax中,它的長度就是4字節32bit,顯然可能是來自高級語言的int、uint32_t、int32_t、float、struct{short, short}, char[4]等類型的數據。

3、內存數據
內存可以存放更多的數據,而且存放數據的地方也沒有額外的信息來表示它的長度,在指令中需要專門的標識符來表示長度,在不同風格形式的匯編語言中有不同的表示形式。

在Intel風格的匯編語言中,數據的長度信息需要專門指定前綴,如:單字節長度的內存數據使用byte ptr前綴來指示,4字節長度的內存數據使用dword ptr前綴來表示,例如 mov eax,dword ptr [rax],表示把寄存器rax中的值作為地址,從內存中讀取4字節的數據放到寄存器eax中,即數據是[rax]指向的內存位置處連續4字節的長度。

而ATT風格的匯編語言中,長度信息是由操作符使用后綴來指示的,比如:movl (%rax), %eax,使用movl操作符來表示寄存器rax指向的內存位置的4字節數據,把它存入寄存器eax。其它的比如movb、movw、movq等用于不同長度的數據,b、w、l、q后綴分別表示1字節、2字節、4字節和8字節的內存數據的長度。

下面列舉各種數據的長度的前綴,以及對應C/C++的類型:

前綴字節bit長度可能對應的C/C++類型
byte ptr18char、unit8_t、int8_t
word ptr216short、uint_16、int_16
dword ptr432int、uint32_t、int32_t、float
qword ptr864long long、uint64_t, int64_t、double
xmm ptr16128int8_t[16]、int16_t[8]、int32_t[4]、int64_t[2]、float[4]、double[2]
ymm ptr32256int8_t[32]、int16_t[16]、int32_t[8]、int64_t[4]、float[8]、double[4]
zmm ptr64512int8_t[64]、int16_t[32]、int32_t[16]、int64_t[8]、float[16]、double[8]

此外,匯編中還有串操作(對應于C/C++語言中的數組類型),這些數據全部存放在內存中,串操作數據的長度,需要由專門的寄存器存放,存放在寄存器cx/ecx中。

4、數據內容- 存放的是什么?

數據所表示的類型,取決于用做什么指令的操作數。指令運算時的它眼中的操作數可以是整型、浮點型、指針、位域、BCD整型、串型(string)和組合類型。

比如,以下面的指令形式為例:
#操作符# eax, dword ptr [rbp-24];
源操作數: dword ptr [rbp-24];
位置:rbp-24指向的內存位置
長度:dword,雙字,即4字節長度
類型:取決于操作符的類型,如果是傳輸型,如mov,不確定,如果是算術運算符,則是整型,如果是邏輯運算型,則是無符號整型
目的操作數:eax
位置:寄存器eax
長度:eax位長是32位,即4字節長度
類型:取決于操作符的類型

下面舉一個例子:
假設源數據是qword ptr [rsp],此形式能確定數據的兩個要素,位置:rsp指向的內存地址,長度:8字節。下面是它可能出現的場景及類型,假設long、double是64位長度:

MOV rax, qword ptr [rsp]
什么類型都可能,取決于后續以rax為操作數的操作

ADD rax, qword ptr [rsp]
因為ADD操作符用于整型加法運算,因此類型可能是long或unsigned long

MUL rax, qword ptr [rsp]
因為MUL操作符用于無符號整型乘法運算,因此類型明確是unsigned long

IMUL rax, qword ptr [rsp]
因為MUL操作符用于無符號整型乘法運算,因此類型明確是signed long型

MOVSS xmm3, qword ptr [rsp] ;是float類型

MOVSD xmm3, qword ptr [rsp] ;是double類型

MOV rax, qword ptr [rsp]
什么類型都可能,取決于后續以rax為操作數的操作
MOVD xmm0, qword ptr[rax]
后續操作MOVD:qword ptr[rax],rax用作地址,它是指向一個8字節的數據的指針,仍不知指向什么類型。
MOVSD xmm3, xmm0
此時確定是double類型,即rsp是一個二維指針,即對應C/C++的double **ptr類型;

paddw mm1, qword ptr [rsp]; 指向組合整數,等同于C的short[4]數組
paddb mm1, qword ptr [rsp]; 指向組合整數,等同于C的char[8]數組
jmp qword ptr [rsp] ; 是地址,可能是指針,包括函數指針類型
jcc qword ptr [rsp] ; 是地址,可能是指針,包括函數指針類型
call qword ptr [rsp] ; 是函數指針

可見,同一個數據在不同形式的指令中,可能表示不同的類型,比如,假設rsp寄存器指向的內存處,長度8字節的內容是0x8123456781234567。比如,在下面的指令中,它會表示不同的類型:
MUL rax, qword ptr [rsp] ; 是uint64_t類型,值是9305357565928097127
IMUL rax, qword ptr [rsp] ; 是int64_t類型,值是-9141386507781454489
MOV rax, qword ptr [rsp] 和 MOV mm0, qword ptr[rax]; 是指針,指向0x8123456781234567內存位置
MOV mm0, qword ptr[rax] ; 是char數組,值是{0x81, 0x23, 0x45, 0x67, 0x81, 0x23, 0x45, 0x67}
MOVSD xmm0, qword ptr [rsp] ; 是double類型,值是-3.5127004713770933e-303,幾乎是0.0。

5、如何訪問數據

知道數據在哪兒,也知道長度,如何取獲取數據呢?尤其是在內存中的數據。是由不同的尋址方式來獲取數據,在x86-64處理器中共有下面幾種方式:

1、立即數尋址
數據是立即數常數,存在于指令中。比如指令:mov eax, 42,它的指令二進制編碼是:b82a000000,其中4字節長度的2a000000,就是立即數42。

C/C++的代碼中,這些數據一般對應字面量或者const、constexpr修飾的常量數據。

2、寄存器尋址
數據在寄存器中,這種尋址方式性能很高,因為寄存器都在CPU執行單元內部,訪問它們很快。

在C/C++代碼中,函數傳遞參數、返回結果、循環變量、使用register修飾的變量等都是存放在寄存器中,此外,表達式運算產生的中間結果一般也放在寄存器中。

3、內存直接尋址
數據在內存中,直接使用地址的絕對值訪問它們,如mov eax, dword ptr [0x7fff324ce00c],從內存位置0x7fff324ce00c處讀取4字節的數據。

在C/C++代碼中,全局變量、靜態變量、函數入口地址可能會用這種尋址方式,但是因為指令編碼較長,可能會用下面的內存間接尋址方式,尤其是x86-64處理器的rip相對尋址方式。

4、內存間接尋址
這一類尋址方式最為豐富。

4.1、寄存器間接
形式:[寄存器],如[rax]

在C/C++代碼中,指針使用*操作符解引用、通過this指針訪問虛函數表地址時,都是這種形式的尋址。

4.2、基址+偏移量
形式:[寄存器±立即數偏移量],如[rbp-16]

也可以把寄存器間接尋址看作是這種尋址方式當偏移量為0時的特例,如[rax]即為[rax+0]
在C/C++中,訪問局部變量、數組元素或者結構成員時常見這種尋址方式,常用于基址的寄存器多是rax、rbx、rbp、rsp,使用它們指令編碼較短,在C++中,如果出現rdi作為基址寄存器,很可能是通過this指針在訪問對象的數據成員。其中寄存器rbp用作訪問函數棧幀的基址、rsp用作棧頂基址,差不多是所有編譯器的標準用法了。

4.3、基址+變址
形式:[基址寄存器±變址寄存器] ,如[rbx+rsi]

用作基址寄存器常見有rbx、rbp,變址寄存器常見有rsi、rdi,當然所有寄存器都可以用作它們。

在C/C++中,使用下標變量來訪問char、uint8_t等單字節數據組成的數組時,就是這種尋址方式,其中數組起始位置是基址寄存器,而下標是變址寄存器。

4.4、基址+變址因子
形式:[基址寄存器±變址寄存器
立即數因子] ,立即數因子只能是2的次冪,如[rbx+rsi*4]

在C/C++中,使用下標變量來訪問short、int、float等多字節數據組成的數組時,就是這種尋址方式,其中數組起始位置是基址寄存器,而下標是變址寄存器,立即數因子就是數組元素的長度,比如對于數組:int ar[],立即數因子就是sizeof(int)=4。

4.5、基址+變址因子+偏移量
形式:[基址寄存器±變址寄存器
立即數因子±立即數偏移量] ,立即數因子只能是2的次冪,如[rbx+rsi*4]。

在C/C++中,使用下標變量來訪問結構數組中某個結構中的數據成員,就是這種尋址方式,其中數組起始位置是基址寄存器,而下標是變址寄存器,因子就是結構的長度,偏移量是數據在結構中的偏移量。

4.6、基址+變址+偏移量
形式:[基址寄存器±變址寄存器±立即數偏移量] ,如[rbx+rsi+8]

在C/C++中,使用下標變量來訪問結構數組中某個結構的數據成員,如果沒有使用4.5的尋址方式(因為變址因子只能使用1、2、4、8等有限的幾個值),就使用兩條指令來尋址,先計算出變址*因子的值放在變址寄存器中,其中數組起始位置是基址寄存器,而下標位置就是變址寄存器,偏移量是數據在結構中的偏移量。

比如:

// size是16字節
struct pointer {int x;  // 偏移量0int64_t z; // 偏移量8
};long foo(pointer a[], int x) {return a[x].z;
}

可以這樣尋址:

foo(pointer*, int):movsx   rsi, esisal     rsi, 4 ; 單獨計算變址的值mov     rax, QWORD PTR [rsi+8+rdi]ret

也可以:

foo(pointer*, int):movsx   rsi, esiadd     rsi, rsi ; 翻倍,這樣rsi*8就是rsi*16mov     eax, DWORD PTR [rdi+rsi*8+8]ret     0

4.7、rip間接尋址
形式:[rip±立即數偏移量],比如[rip - 0x33538]

現代操作系統中,進程的內存布局模型都是flat平坦模式,即所有的代碼和數據都不再分段管理,而是在同一個地址空間內統一編址,這樣就使用指令指針寄存器rip來訪問數據,在指令訪問內存數據時,所執行的位置處(即RIP的值)加上和目標地址的距離——偏移量,就能訪問到目標地址處的內存數據。在C、C++訪問全局變量、static變量、動態加載的函數和全局變量時,都可以使用這種方式來尋址。

最后

雖然在前面我把數據分成了三部分進行說明,實際上它們三者是同時密切聯系在一起的。在一條指令中,同時表示了這三部分的信息,比如下面的指令:

add   edx, DWORD PTR [rdi+4+rsi*8]

1、源數據位于內存中,是一個“基址+變址*因子+偏移量”的尋址方式,位置是經過基址寄存器rdi和變址寄存器rsi運算后的內存地址,數據長度是4字節(dword ptr指示),而地址數據存放在寄存器rdi中,它的長度是8字節,相當于rdi對應C/C++中的指針類型;

2、目的數據位于寄存器edx中,它的長度是4字節

3、指令操作符是add,是算數加法操作,因此源數據和目的數據都是整型數,但是有符號還是無符號數仍不知道。

差不多是類似于下面形式的C/C++代碼結構:

struct strct {int x;int z;
};.....
strct ar[M];
int index;
int sum;
...
sum += ar[index].z;

其中ar是一個結構數組,rdi=&ar,rsi=index,edx=sum。

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

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

相關文章

C++17 信號量模擬實現

C17 信號量模擬實現 一、實現原理 C17 標準庫沒有原生信號量(C20才有)&#xff0c;但可以通過 std::mutex std::condition_variable 模擬實現。以下是核心邏輯&#xff1a; #include <mutex> #include <condition_variable>class CountingSemaphore { private:…

C++ 網絡層接口設計與實現:基于 Socket 編程

在網絡編程中&#xff0c;網絡層是 OSI 七層模型中負責將數據從源節點傳輸到目的節點的關鍵層次。在 C 中&#xff0c;網絡層的功能通常通過 Socket 編程接口來實現。Socket 提供了一種抽象機制&#xff0c;允許應用程序通過網絡發送和接收數據。本文將詳細介紹如何在 C 中使用…

uniapp中uni-easyinput 使用@input 不改變綁定的值

只允許輸入數字和字母 使用input 正則replace后賦值給A 遇到問題: 當輸入任意連續的非法字符時, 輸入框不變. 直到輸入一個合法字符非法字符才成功被過濾. <uni-forms-item label"納稅人識別號" name"number"><uni-easyinput v-model"numb…

Docker安裝hoppscotch

Docker安裝hoppscotch 1 簡介 1.1 Hoppscotch?系統 ?Hoppscotch?是一個輕量、高效的[API開發生態系統&#xff0c;開源于2020年&#xff0c;原名Postwoman&#xff0c;后更名為Hoppscotch。它基于Node.js構建&#xff0c;支持多種HTTP請求方法&#xff0c;包括GET、POST、…

1.Axum 與 Tokio:異步編程的完美結合

摘要 深入解析 Axum 核心架構與 Tokio 異步運行時的集成&#xff0c;掌握關鍵原理與實踐技巧。 一、引言 在當今的軟件開發領域&#xff0c;高并發和高性能是衡量一個系統優劣的重要指標。對于 Web 服務器而言&#xff0c;能夠高效地處理大量并發請求是至關重要的。Rust 語言…

CSS偽元素

偽元素 偽元素 用于在元素的內容前后或特定部分插入虛擬元素&#xff0c;并為其添加樣式&#xff0c;無需修改 HTML 結構。 語法&#xff1a;使用雙冒號 ::&#xff08;現代規范&#xff09; 以下是一些常見的CSS偽元素的示例&#xff1a; 1.::before &#xff1a; 在元素內…

easyexcel使用模板填充excel坑點總結

1.單層map設置值是{屬性}&#xff0c;那使用兩層map進行設置值&#xff0c;是不是可以使用{屬性.屬性}&#xff0c;以為取出map里字段只用{屬性}就可以設置值&#xff0c;那再加個.就可以從里邊map取出對應屬性&#xff0c;沒有兩層map寫法 填充得到的文件打開報錯 was empty (…

在Ubuntu服務器上部署xinference

一、拉取鏡像 docker pull xprobe/xinference:latest二、啟動容器&#xff08;GPU&#xff09; docker run -d --name xinference -e XINFERENCE_MODEL_SRCmodelscope -p 9997:9997 --gpus all xprobe/xinference:latest xinference-local -H 0.0.0.0 # 啟動一個新的Docker容…

三周年創作紀念日

文章目錄 回顧與收獲三年收獲的五個維度未來的展望致謝與呼喚 親愛的社區朋友們&#xff0c;大家好&#xff01; 今天是 2025 年 4 月 14 日&#xff0c;距離我在 2022 年 4 月 14 日發布第一篇技術博客《SonarQube 部署》整整 1,095 天。在這條創作之路上&#xff0c;我既感慨…

Redis——五種數據類型

目錄 前言 1.String 1.1RAW編碼 1.2EMBSTR編碼 1.3 INT編碼 2.List 3.Set 3.1 InSet編碼轉化成Dict編碼 4.ZSet 4.1結合SkipList和HT實現 4.2使用ZipList實現 4.3編碼轉換 4.4 ZipList排序功能 5.Hash 5.1Hash底層存儲結構 6.Redis數據結構和數據類型關系圖 前言…

zookeeper啟動報錯have small server identifier

解決方案&#xff1a; 1、查看myid是否有重復 2、查看server.X 與myid的X是否一致 3、啟動順序為myid從小到大的服務器順序

#Linux動態大小裁剪以及包大小變大排查思路

1 動態庫裁剪 庫分為動態庫和靜態庫&#xff0c;動態庫是在程序運行時才加載&#xff0c;靜態庫是在編譯時就加載到程序中。動態庫的大小通常比靜態庫小&#xff0c;因為動態庫只包含了程序需要的函數和數據&#xff0c;而靜態庫則包含了所有的函數和數據。靜態庫可以理解為引入…

消息隊列生產者投遞的高可靠性與一致性保障方案

在構建高可靠分布式系統時&#xff0c;確保業務數據庫與消息隊列&#xff08;MQ&#xff09;之間的一致性是一項核心挑戰。尤其當使用 Kafka 作為消息隊列中間件時&#xff0c;如何避免“數據庫寫入成功&#xff0c;但消息發送失敗”或“消息重復發送”等問題&#xff0c;成為系…

Formality:Bug記錄

相關閱讀 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 本文記錄博主在使用Synopsys的形式驗證工具Formality中遇到的一個Bug。 Bug復現 情況一 // 例1 module dff (input clk, input d_in, output d_out …

通信算法之267 : DJI無人機 云哨 DroneID 640ms

DJI 無人機 與DroneID 轉 *** 載 0x01 摘要 消費級無人機可以用于高級航拍、物流和人道主義救援等等。但是其廣泛使用給安全、安保和隱私帶來了許多風險。例如&#xff0c;攻擊方可能會使用無人機進行監視、運輸非法物品&#xff0c;或通過侵入機場上方的封閉空域造成經濟損…

論壇測試報告

作者前言 &#x1f382; ??????&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ?&#x1f382; 作者介紹&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

npx 的作用以及延伸知識(.bin目錄,npm run xx 執行)

文章目錄 前言原理解析1. npx 的作用2. 為什么會有 node_modules/.bin/lerna3. npx 的查找順序4. 執行流程總結1&#xff1a; 1. .bin 機制什么是 node_modules/.bin&#xff1f;例子 2. npx 的底層實現npx 是如何工作的&#xff1f;為什么推薦用 npx&#xff1f;npx 的特殊能力…

【c語言】深入理解指針3——回調函數

一、回調函數 回調函數&#xff1a;通過函數指針調用的函數. 當把一個函數的地址傳遞給另一個函數&#xff0c;通過該地址去調用其指向的函數&#xff0c;那么這個被調用的函數就是回調函數. 示例&#xff1a; 在【深入理解指針2】中結尾寫了用函數指針實現計算器的功能&#…

HTTP 核心概念

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家&#xff0c;歷代文學網&#xff08;PC端可以訪問&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移動端可微信小程序搜索“歷代文學”&#xff09;總架構師&#xff0c;15年工作經驗&#xff0c;…

VidBot:從野外 2D 人體視頻中學習可泛化的 3D 動作,實現零樣本機器人操控

25年3月來自慕尼黑工大、瑞士 ETH 和微軟的論文“VidBot: Learning Generalizable 3D Actions from In-the-Wild 2D Human Videos for Zero-Shot Robotic Manipulation”。 未來的機器人被設想為能夠執行各種家務的多功能系統。最大的問題仍然是&#xff0c;如何在盡量減少機器…