【汇编语言】8086、x86-32和C语言【赋值语句 和 数组】的对比学习(王爽学习笔记:5.8段前缀的使用)
0 前言
這里給出兩種思路,都比王爽老師書上的做法要簡單高效,事實上,理解指令的本質,就能達到靈活應用,這樣才能打破規則
題目:將內存ffff:0 - ffff:b的數據,復制到內存ffff:10 - ffff:1b中
備注:使用8086匯編語言
本篇的核心是:分別使用8086、x86-32和C語言,理解內存空間的復制。
1 思路一:使用push、pop指令
push,pop指令的本質,是內存傳送指令,它也是送數據的。
例如pop DS:[EA]本質是mov DS:[EA],SS:[SP]
; 思路一:使用push,pop內存轉移指令,注意是字型數據,2個2個搬運 assume cs:code code segment start:; DS:[bx]指向0:200mov ax,0mov ds,axmov bx,0200h; 設置棧頂mov ax,0ffffhmov ss,axmov sp,0; 設置循環mov cx,6s:pop [bx]add bx,2 ; 一次copy一個字loop smov ax,04c00hint 021h code ends end start2 思路二:使用段前綴
完全沒有必要一個字節一個字節傳送,這樣需要字節擴展為字再使用,效率低下。
; 思路二:使用段前綴 assume cs:code code segmentstart:mov ax,0ffffhmov ds,axmov ss,axmov bx,0mov cx,6s: mov dx,ds:[bx]mov ss:[bx+10h],dxadd bx,2loop smov ax,04c00hint 021h code ends end start3 結合C語言和x86-32匯編語言
這個題目,本質上對應于C語言的基本模型:賦值語句,例如int a = b;
int a = 2; int b; b = a;對應匯編語言
int a = 2; mov dword ptr [a],2int b b = a; mov eax,dword ptr [a] mov dword ptr [b],eax這里也可以看出int b;變量聲明,是不會生成匯編代碼的,它的本質就是給某個內存段做個標記,叫b,且它占連續的4個字節。
4 第3部分的擴展:連續內存空間的copy
先來看一個基本數組
int a[10] = { 1,23,4,4,5,6,77,0 };對應的匯編
00184198 mov dword ptr [a],1 0018419F mov dword ptr [ebp-28h],17h 001841A6 mov dword ptr [ebp-24h],4 001841AD mov dword ptr [ebp-20h],4 001841B4 mov dword ptr [ebp-1Ch],5 001841BB mov dword ptr [ebp-18h],6 001841C2 mov dword ptr [ebp-14h],4Dh 001841C9 mov dword ptr [ebp-10h],0 001841D0 xor eax,eax 001841D2 mov dword ptr [ebp-0Ch],eax 001841D5 mov dword ptr [ebp-8],eax這里有一個值得注意的地方,就是寄存器的清零,這里使用了xor eax,eax,一個數跟自己異或,再賦值給自己,必然是0,這個用法比較新奇。當然也可以使用基本語句mov eax,0。
另外,你可以知道
如果想要將整個數組的內容,復制到另外一個數組int b[10]怎么辦?
最容易想到的做法是,直接循環遞增復制
int a[10] = { 1,23,4,4,5,6,77,0 };int b[10]; for (int i = 0; i < 10; i++) {b[i] = a[i]; }對應的匯編語言
1: for (int i = 0; i < 10; i++) { 00DB4D21 mov dword ptr [ebp-78h],0 00DB4D28 jmp 00DB4D33 00DB4D2A mov eax,dword ptr [ebp-78h] 00DB4D2D add eax,1 00DB4D30 mov dword ptr [ebp-78h],eax 00DB4D33 cmp dword ptr [ebp-78h],0Ah 00DB4D37 jge 00DB4D49 2: b[i] = a[i]; 00DB4D39 mov eax,dword ptr [ebp-78h] 00DB4D3C mov ecx,dword ptr [ebp-78h] 3: b[i] = a[i]; 00DB4D3F mov edx,dword ptr [ebp+ecx*4-30h] 00DB4D43 mov dword ptr [ebp+eax*4-6Ch],edx 4: } 00DB4D47 jmp 00DB4D2A這種拷貝方式,就是一個個拷貝,很容易想到,但是在C語言中,這一點都不酷,不過這種做法與最開始8086匯編的思路是一致的,一點點轉移過去,應該有更酷的內容被使用。
此外,應該了解小知識點是 【尋址方式】,對于語句mov edx,dword ptr [ebp+ecx*4-30h]中的[ebp+ecx*4-30h],地址形成的方式是 ebp + ecx*常數 + 常數。
更酷的方式是memcpy函數(memory copy),也就是內存復制。
int a[10] = { 1,23,4,4,5,6,77,0 }; int b[10]; memcpy(&b, &a,sizeof(a));這樣,就能夠直接將整個內存空間拷貝到另外一段內存空間了,不過,這種做法其實就是直接使用封裝的函數,本質還是一點點拷貝過去。但是對于高級語言來說,應該更多地使用已經封裝好的常用函數,以提高效率。
對于memcoy的用法,簡單說明,(1,2,3)
- 1放的是目標的內存地址空間的首地址,這里是&b
- 2放的是源內存地址空間的首地址,這里是&a
- 3放的是需要拷貝過去地址空間的大小,這里是sizeof(a),也就是40個字節
總結
以上是生活随笔為你收集整理的【汇编语言】8086、x86-32和C语言【赋值语句 和 数组】的对比学习(王爽学习笔记:5.8段前缀的使用)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成都欢乐谷乘地铁几号线
- 下一篇: 为什么要学习汇编语言?如何正确学习汇编语