能力值:
( LV13,RANK:530 )
|
-
-
2 楼
最初由 kflnig 发布 有很多人认为汇编已经失去了用武之地,包括曾经的我。我用的是visual c++6.0。现在我要问你一个问题。 a=10,b=20。你现在要使a和b的值交换。你有什么办法。这是教科书上说得很多的方法。第一种方法: #include <iostream.h> void main() { ........
我只说“你现在要使a和b的值交换”
千万不要小视编译器优化。。具体你用Release版编译一下就知道了
另外MSVCRT也有库函数可以用:swap。
Swaps bytes.
void _swab(
char *src,
char *dest,
int n
);
|
能力值:
( LV9,RANK:170 )
|
-
-
3 楼
Good,学习,
经验都是心血耗来的,
谢谢分享
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
我觉得VC的优化是做的不错,如果是为提高效率而使用内联汇编,基本上没有必要。
调过几个Borland C++ 1999的程序,垃圾代码不是一般的多
|
能力值:
( LV9,RANK:250 )
|
-
-
6 楼
a=0x120; _asm { lea ebx,a movzx eax, byte ptr [ebx] mov b,eax } cout<<b; b等于多少?知道吗? ........
mov b,eax 楼主这个不是一样的错误么?第一个操作数必须是寄存器
|
能力值:
( LV8,RANK:130 )
|
-
-
7 楼
_asm
{
mov eax,a
mov ebx,b
xchg eax,ebx //用西裤哥的话来说,这叫脱了裤子打屁
mov a,eax
mov b,ebx
}
不知道这么写是否为教学意图?
|
能力值:
( LV9,RANK:250 )
|
-
-
8 楼
楼上的指出。。。。。。。
|
能力值:
( LV6,RANK:90 )
|
-
-
9 楼
楼主的文章确实很好,适合我们菜鸟.向楼主致敬
这样写不知道会如何编译.
a=a+b
b=a-b
a=a-b
|
能力值:
( LV6,RANK:90 )
|
-
-
10 楼
很好!理论+实践的文章~受教了!
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
sz[1]= 3;
_asm
{
mov eax,sz[1]
mov a,eax
}
cout<<a;
这里无论我mov eax,sx 都无法输出正确结果,不知道为什么? 另外请教:
>另外浮点通过st(0)返回值。
如何在C中实现?
|
能力值:
( LV9,RANK:1130 )
|
-
-
12 楼
“最后夸奖自己一句,这篇文章真的很好,很难找到这么浅显易懂的文章啊!^_^”
我也这么认为,
|
能力值:
( LV9,RANK:210 )
|
-
-
13 楼
最初由 binbinbin 发布 “最后夸奖自己一句,这篇文章真的很好,很难找到这么浅显易懂的文章啊!^_^” 我也这么认为,
同上
|
能力值:
( LV12,RANK:210 )
|
-
-
14 楼
asm
{
mov eax,a
mov ebx,b
xchg eax,ebx //用西裤哥的话来说,这叫脱了裤子打屁
mov a,eax
mov b,ebx
}
楼上的指出。。。。。。。
===========
教学的话, 可以这么写
asm
{
mov eax,a
xchg eax,b
mov a,eax
}
|
能力值:
( LV12,RANK:210 )
|
-
-
15 楼
最初由 fonge 发布 同上
楼主写完了以后, 有没有握着自己的右手说一声耶。
|
能力值:
( LV9,RANK:170 )
|
-
-
16 楼
最初由 仙剑太郎 发布 很好!理论+实践的文章~受教了!
同意
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
不错的好文章啊
|
能力值:
( LV12,RANK:570 )
|
-
-
18 楼
内联汇编补遗
kflnig狂枫
上次写了一篇内联汇编,但是有点不周全的地方,所以写了这篇补遗。
针对大家的批评,尤其是我那个XCHG的使用,简直是脱了裤子放屁,自己汇编功底差,一时误记,在此向大家道歉。
mov ebx,dword ptr[eax]简单点吧,mov ebx,[eax],64bit的机器我不敢说正确,但是32bit的机器中还是后一种写法更加简单,因为指针指向的值,32bit中默认就当作dword类型了。
结构类型,也得说一下。这个东西还是很头痛的,没有汇编写过程序的一般人是不会知道的。Yonsm 大哥的内联汇编教程中有提到。这里我再补充一下。
#include <iostream.h>
struct first
{
int a;
};
struct first str;
void main()
{
str.a=10;
__asm
{
MOV EBX, OFFSET str
MOV [EBX]str.a,20
}
cout<<str.a;
}
注意定义str结构类型的位置。
Yonsm 大哥的内联汇编教程说得对,都是非常对的,可是他功力太高,忘了提醒我们一点OFFSET的特点。
OFFSET不能用于获取局部变量的地址,只是由于OFFSET伪指令确定偏移量是在编译时预先确定好的,对局部变量在编译时是不确定的,它与堆栈寄存器的取值有关,而堆栈寄存器的取值随着执行环境的不同而不同。所以在声明struct变量的时候应该放在开头,应该是全局变量,大家注意核实,我不想误导你。对c语言这种很拗口的语法,我也并不是很清楚。当然还有一类人是不看上文也绝对不会写错的。懒人。
因为懒人通常是
struct first
{
int a;
}str;
这么写的。这样也可以。
现在明白了吧!我只是提醒这个,Yonsm 大哥提到的,可以省略些代码的写法,你不妨自己去看看他的教程。
若你看过crack7中的《Thinking in ASM 》,那么你不妨再看看我的。
他们都在大谈swap(a,b)之后a,b的值有没有换过。我来一个稍微变态的,也作为对使用内联汇编者的提醒,小心这种情况。
#include <iostream.h>
void swap(int &a, int &b)
{
__asm
{
push a
push b
pop a
pop b
}
}
void main()
{
int a,b;
cin>>a>>b;
swap(a,b);
cout<<a1<<b1;
}
答案当然是没有啦。
|
能力值:
(RANK:1060 )
|
-
-
19 楼
好像优化newbie手册。。。
一个原则是最好不要使用堆栈,时空都耗费很厉害
找一个reg来交换吧。。。
不过编译器会干的,研究这种优化上有意义吗
这些其实就是手熟而已,经常用asm作开发的都知道。但要他们研究brainfuck可能会晕
|
能力值:
( LV12,RANK:570 )
|
-
-
20 楼
内联汇编再补遗[大结局]
kflnig中文名:狂枫
声明:此文或许会有多处错误,大家请踊跃发言!提出错误!本文基于WINXP,VC6.0调试通过。
一篇内联汇编产生了这么多的补遗,^_^如果你内联汇编一般,看了这篇文章那么肯定吓一跳。因为我本来的题目是7474742。就是气死气死气死你!它早就把我气死过一回了。我的目标就是把你搞混到不敢学内联汇编!^_^
如果你对自己的内联汇编很有信心,那么看下去。
说点不重要的。也是复习一下。
void main()
{
int a[10];
a[0]=10;
a[1]=20;
__asm
{
mov eax,a[0]
add eax,a[4]
mov a[0],eax
}
cout<<a[0];
}
我在第一篇《内联汇编》中已经说过。这样是输出a[0]+a[1]。
我们再来看。法一:
void main()
{
int bl1,bl2;
bl1=10;
bl2=20;
__asm
{
mov eax,bl1
xchg eax,bl2
mov bl1,eax
}
cout<<bl1<<bl2;
}
这个更加简单了就是bl1和bl2交换。那么法二:
void main()
{
int bl1,bl2;
bl1=10;
bl2=20;
__asm
{
lea eax,bl1
mov ebx,[eax]
lea ecx,bl2
mov edx,[ecx]
xchg ebx,edx
mov [ecx],edx
mov [eax],ebx
}
cout<<bl1<<bl2;
}
上面的代码毫无优化可言,我只是为了对照c++源码的翻译式写法。也是bl1,bl2的值相互交换。
从代码的高级程度无疑是法一高得多。但是,我推荐小鸟牢牢掌握法二。要问我为什么,先等等,待会儿说!
我们知道
void swap(int &a,int &b)
{
__asm{
push a
push b
pop a
pop b
}
}
这样执行
c=10;
d=20;
swap(c,d);
c依旧是10而d依旧是20。我没有什么好办法只好来一个笨点的。
void swap(int &a,int &b)
{
int a1,b1;
a1=a;
b1=b;
__asm
{
mov eax,a1
xchg eax,b1
mov b1,eax
}
a=a1;
b=b1;
}
言归正传。
void add(int c[10],int d[10])
{
__asm
{
mov eax,c[0]
add eax,d[0]
mov c[0],eax
}
cout<<c[0];
}
void swap(int c[10],int d[10])
{
__asm
{
mov eax,c[0]
xchg eax,d[0]
mov c[0],eax
}
cout<<c[0]<<d[0];
}
void main()
{
int a[10],b[10],bl1,bl2;
a[0]=10;
b[0]=20;
swap(a,b);
}
这样是对的输出20,10。但是假如把swap(a,b);改成add(a,b);那么只会跳出一个丑陋的对话框。因为swap(a,b)没有问题,所以原因不再其它而在add函数自己内部的__asm中。这就是传数组,这个很特别的特例。我们在add函数里操纵的是数组的地址。如果你要add那么用类法二的方法吧!
void add(int c[10],int d[10])
{
__asm
{
mov eax,c[0]
mov ebx,[eax]
mov ecx,d[0]
add ebx,[ecx]
mov [eax],ebx
}
cout<<c[0];
}
这样就不会有丑陋的对话框了。以后不要再把两个地址加起来了。在函数中处理传入的数组尤其小心!所以上面的swap(a,b)其实是很高级的交换c[0],d[0]的地址。
好了我的《内联汇编》教程(共三篇)结束了。写得很详细。相信大家的内联汇编技术也很强了。我也不弱^_^自己多用才是可以提高!
这是我在寒假里给大家写的最后一篇文章了。再见!
最后我来布置一道终极考试题目a=10;这用内联汇编怎么写。
这是一题怎么写都不会错的。比如
__asm
{
mov eax,10
mov a,eax
}
或者
_asm
{
mov eax,10
mov [a],eax
}
都对!不要问我为什么,我也不知道,这是VC的编译器这么说的。
所以我们可以知道,假如是这样:
void add(int c,int d)
{
__asm
{
mov eax,c
add eax,d
mov c,eax
}
cout<<c;
}
这个add函数可以安全执行。我相信此刻你已被内联汇编搞混了头脑!到底该怎么用,还是自己去试验然后总结吧!
|