Đây là lần đầu lttq viết bài ở box này.Vì biết ở đây có nhiều cao thủ nên việc chém gió rất dễ lộ.Vì thế những gì mình nắm được thì sẽ trình bày kỹ,cái nào còn lơ mơ thì không dám nói nhiều,chờ cao nhân.
Có 1 thread nào đó,bác TQN có bảo không nên dùng inline asm,chỉ nên dùng khi cần optimize,không nên chạy đua với trình dịch.Bài này viết ra chỉ để giải trí là chính,vì những project to thì mấy chỗ lặt vặt này chắc cũng chẳng ai ngó.
#include <iostream>
using namespace std;
int Tong(int len,int A[]) {
int i,sum=0;
for(i=0;i<len;i++) sum+=A[i];
return sum;
}
int main(int argc,char* argv[])
{
int M[10];
M[0]=1;
M[1]=2;
cout << Tong(2,M);
return 0;
}
Khi disasembly thì tại vị trí của "for(i=0;i<len;i++) sum+=A[i];" nó sẽ như sau :
00D713BE MOV DWORD PTR SS:[EBP-14],0 // sum = 0
00D713C5 MOV DWORD PTR SS:[EBP-8],0 // i = 0
00D713CC JMP SHORT loop-asm.00D713D7 // vào loop
00D713CE MOV EAX,DWORD PTR SS:[EBP-8] //
00D713D1 ADD EAX,1 // i++
00D713D4 MOV DWORD PTR SS:[EBP-8],EAX
00D713D7 MOV EAX,DWORD PTR SS:[EBP-8]
00D713DA CMP EAX,DWORD PTR SS:[EBP+8] // while(i < len)
00D713DD JGE SHORT loop-asm.00D713F0
00D713DF MOV EAX,DWORD PTR SS:[EBP-8]
00D713E2 MOV ECX,DWORD PTR SS:[EBP+C]
00D713E5 MOV EDX,DWORD PTR SS:[EBP-14]
00D713E8 ADD EDX,DWORD PTR DS:[ECX+EAX*4] // sum += A[i]
00D713EB MOV DWORD PTR SS:[EBP-14],EDX // sum
00D713EE JMP SHORT loop-asm.00D713CE
00D713F0 MOV EAX,DWORD PTR SS:[EBP-14] //return về eax
Rõ ràng là ta có thể giảm đi 1 biến i và 1 biến sum cho chỡ chật stack.
Như sau :
int Tong(int len,int A[]) {
__asm {
xor eax, eax // coi eax là sum
xor edx, edx // coi như edx là i
mov ecx,dword ptr [A]
cmp len, 0 // if (len != 0)
je L2 //mảng trống thì nhảy qua loop
L1: add eax, dword ptr [ecx+edx*4] // Tong += A[i]
add edx, 1 // i++
cmp edx,len
jb L1 //nhảy khi i>=len
L2: //return eax
}
}
Tiết kiệm:
Code:
mov eax, [a]
imul eax, 6
mov [b], eax
mov ebx, [c]
add ebx, 2
mov [d], ebx
có thể bớt ebx đi:
Code:
mov eax, [a]
imul eax, 6
mov [b], eax
mov eax, [c]
add eax, 2
mov [d], eax
sử dụng triệt để các thanh ghi thấp hơn(16bit-8bit)
Code:
mov eax, [a]
imul eax, 6
mov [b], eax
mov ax, [c]
add ax, 2
mov [d], ax
giảm đi 1 thanh ghi :
biểu thức (A *= 128) và (A <<= 7) đều được biên dịch thành:
Code:
mov eax, A
shl eax, 7
mov A, eax
tối ưu hơn :
Giảm lệnh :
int a, b, c, d, e;
e = a*b + a*c;
Trình biên dịch phát sinh mã hợp ngữ như sau:
Code:
mov eax, dword ptr [a]
imul eax, dword ptr [b]
mov ecx, dword ptr [a]
imul ecx, dword ptr [c]
add eax, ecx
mov dword ptr [e], eax
Tuy nhiên, ta có thể viết rút gọn giảm được 1 phép imul (nhân), 1 phép mov (di
chuyển, sao chép):
Code:
__asm
{
mov eax, b;
add eax, c;
imul eax, a;
mov e, eax;
}
Từ 1 câu lệnh :
a = b > c ? d : e;
VS2010 sinh mã như sau :
Code:
00173550 mov eax,dword ptr [b (177144h)]
00173555 cmp eax,dword ptr [c (177140h)]
0017355B jle wmain+6Bh (17356Bh)
0017355D mov ecx,dword ptr [d (17713Ch)]
00173563 mov dword ptr [ebp-0C4h],ecx
00173569 jmp wmain+77h (173577h)
0017356B mov edx,dword ptr [e (177138h)]
00173571 mov dword ptr [ebp-0C4h],edx
00173577 mov eax,dword ptr [ebp-0C4h]
0017357D mov dword ptr [a (177148h)],eax
Ta có thể inline lại gọn hơn
Code:
__asm{
mov eax, [b]
cmp eax, [c]
jng L1
mov eax, [d]
jmp L2
L1: mov eax, [e]
L2: mov [a], eax
}
Optimize hơn:
Code:
mov eax, [b]
cmp eax, [c]
mov eax, [d]
cmovng eax, [e]
mov [a], eax
Bài viết này lượm lặt ý tưởng từ nhiều nguồn,triển khai lại theo ý tưởng của mình ^^