2 dovahkiinx DovahkiinX 于 2016.01.26 17:25 提问

Visual C++中内嵌汇编的问题

如下,是一个利用内嵌汇编实现的两整数交换的程序。输出结果是2,1;2,1;1,2;2,1.可以看到Swap2这个函数行不通,在函数内两个变量确实交换了,但是调用后a和b没有交换,仍然是2,1。就像是传值一样,而没有传址,令我很困惑。

 #include <cstdio>
void Swap1(int &_int1, int &_int2);
void Swap2(int &_int1, int &_int2);
int main() {
    int a = 1, b = 2;
    Swap1(a, b);
    printf("%d,%d;", a, b);
    Swap2(a, b);
    printf("%d,%d.", a, b);
    return 0;
}
void Swap1(int &_int1, int &_int2) {
    unsigned c = _int1, d = _int2;
    __asm {
        mov ebx, [c];
        xchg ebx, [d];
        mov [c], ebx;
    }
    _int1 = c;
    _int2 = d;
    printf("%d,%d;", _int1, _int2);
}
void Swap2(int &_int1, int &_int2) {
    __asm {
        mov ebx, [_int1];
        xchg ebx, [_int2];
        mov [_int1], ebx;
    }
    printf("%d,%d;", _int1, _int2);
}

请各位朋友帮忙看看为什么会这样。

5个回答

caozhy
caozhy   Ds   Rxr 2016.01.26 19:32
已采纳
 21:       Swap2(a, b);
0040107B   lea         ecx,[ebp-8]
0040107E   push        ecx
0040107F   lea         edx,[ebp-4]
00401082   push        edx
00401083   call        @ILT+0(Swap2) (00401005)
00401088   add         esp,8
22:       printf("\n-%d,%d.", a, b);
0040108B   mov         eax,dword ptr [ebp-8]
0040108E   push        eax
0040108F   mov         ecx,dword ptr [ebp-4]
00401092   push        ecx
00401093   push        offset string "\n-%d,%d." (0042201c)
00401098   call        printf (004011d0)
0040109D   add         esp,0Ch

根据如上代码,printf用的是本函数堆栈上的int1 int2,缺少一个写回的动作

DovahkiinX
DovahkiinX 谢谢!
2 年多之前 回复
caozhy
caozhy   Ds   Rxr 2016.01.26 19:20
 36:   void Swap2(int &_int1, int &_int2) {
00401170   push        ebp
00401171   mov         ebp,esp
00401173   sub         esp,40h
00401176   push        ebx
00401177   push        esi
00401178   push        edi
00401179   lea         edi,[ebp-40h]
0040117C   mov         ecx,10h
00401181   mov         eax,0CCCCCCCCh
00401186   rep stos    dword ptr [edi]
37:       __asm {
38:           mov ebx, [_int1];
00401188   mov         ebx,dword ptr [ebp+8]
39:           xchg ebx, [_int2];
0040118B   xchg        ebx,dword ptr [ebp+0Ch]
40:           mov [_int1], ebx;
0040118E   mov         dword ptr [ebp+8],ebx
41:       }
42:       printf("\n2-%d,%d;", _int1, _int2);
00401191   mov         eax,dword ptr [ebp+0Ch]
00401194   mov         ecx,dword ptr [eax]
00401196   push        ecx
00401197   mov         edx,dword ptr [ebp+8]
0040119A   mov         eax,dword ptr [edx]
0040119C   push        eax
0040119D   push        offset string "\n2-%d,%d;" (00422040)
004011A2   call        printf (004011d0)
004011A7   add         esp,0Ch
43:   }
 25:   void Swap1(int &_int1, int &_int2) {
004010E0   push        ebp
004010E1   mov         ebp,esp
004010E3   sub         esp,48h
004010E6   push        ebx
004010E7   push        esi
004010E8   push        edi
004010E9   lea         edi,[ebp-48h]
004010EC   mov         ecx,12h
004010F1   mov         eax,0CCCCCCCCh
004010F6   rep stos    dword ptr [edi]
26:       unsigned c = _int1, d = _int2;
004010F8   mov         eax,dword ptr [ebp+8]
004010FB   mov         ecx,dword ptr [eax]
004010FD   mov         dword ptr [ebp-4],ecx
00401100   mov         edx,dword ptr [ebp+0Ch]
00401103   mov         eax,dword ptr [edx]
00401105   mov         dword ptr [ebp-8],eax
27:       __asm {
28:           mov ebx, [c];
00401108   mov         ebx,dword ptr [ebp-4]
29:           xchg ebx, [d];
0040110B   xchg        ebx,dword ptr [ebp-8]
30:           mov [c], ebx;
0040110E   mov         dword ptr [ebp-4],ebx
31:       }
32:       _int1 = c;
00401111   mov         ecx,dword ptr [ebp+8]
00401114   mov         edx,dword ptr [ebp-4]
00401117   mov         dword ptr [ecx],edx
33:       _int2 = d;
00401119   mov         eax,dword ptr [ebp+0Ch]
0040111C   mov         ecx,dword ptr [ebp-8]
0040111F   mov         dword ptr [eax],ecx
34:       printf("\n1-%d,%d;", _int1, _int2);
00401121   mov         edx,dword ptr [ebp+0Ch]
00401124   mov         eax,dword ptr [edx]
00401126   push        eax
00401127   mov         ecx,dword ptr [ebp+8]
0040112A   mov         edx,dword ptr [ecx]
0040112C   push        edx
0040112D   push        offset string "\n1-%d,%d;" (00422034)
00401132   call        printf (004011d0)
00401137   add         esp,0Ch
35:   }

WinsenJiansbomber
WinsenJiansbomber   2016.01.30 07:16

所谓授人以鱼不如渔,VISUAL C++ 有个好用的工具叫Listing File,好多人都不用,但是和ASM打交道的同学们是必需的工具:Listing Files

通过设置 Listing Files的不同类型,可以产生一个和源代码相应的COD文件,它可以包含汇编代码,机器码和源代码。通过这些内容,可以清晰直观地看到VC编译器对源代码做了些什么改动。

VC工程设置

以当前的ChildView.cpp为例,编译后会产生 ChildView.cod 文件,打开它,这就是你想要的:
COD

WinsenJiansbomber
WinsenJiansbomber 竟然收到MVP的一个赞,立马觉得眼前一片锃光瓦亮:}
2 年多之前 回复
caozhy
caozhy
2 年多之前 回复
lm_whales
lm_whales   Rxr 2016.01.26 22:02

手动写个 swap函数
然后查看反汇编,以及自动生成德汇编代码

WinsenJiansbomber
WinsenJiansbomber   2016.03.05 14:24

应该这样调用:

Swap1(&a, &b);

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
Linux 内嵌汇编
简要说下GNU汇编编译器的语法 GCC,linux下的GNU c编译器,用的是AT&T的语法,下面列出一些,但并不是全部,,只是和内嵌汇编相关的部分 寄存器的命名 在寄存器的名字前加前缀%, 比如你要用eAx,那就要这样用%eAx 源操作数与目的操作数的顺序 源操作数在前,目的操作数在后,这点和Intel 语法刚好相反 比如: mov %eAx,%ebx  表示把eAx中的内容传到eb
c内嵌汇编语句
内核代码绝大部分使用C语言编写,只有一小部分使用汇编语言编写,例如与特定体系结构相关的代码和对性能影响很大的代码。GCC提供了内嵌汇编的功能,可以在C代码中直接内嵌汇编语言语句,大大方便了程序设计。 一、基本内嵌汇编   GCC提供了很好的内嵌汇编支持,最基本的格式是: __asm__ __volatile__(汇编语句模板); 1、__asm__   __asm__是G
C语言中使用汇编语言之一GCC内嵌汇编
在C语言中如何使用汇编语言呢?这个问题在 不同的编译器中,具体实现方法是不同的。不过在实现大方上也不过就是有两种,而且各种编译器的实现方法也是大同小异。一种是在C语言中嵌入汇编语言代码, 另一种是让C语言从外部调用汇编。下面我们就以 Borland格式为例来说一说具体用法。但是,GCC与Microsoft的实现方法的与Borland只在格式上有点区别。当然,GCC的嵌入汇编是 AT&T格式的。
2.2.1 GNU C内嵌汇编语言
一个64位操作系统的实现
ARM汇编和内嵌汇编
汇编指令 跳转指令 b{cond} bl blx bx 数据处理指令 mov  mvn add adc sub rsb rsc and or eor bic cmn cmp tst teq 状态寄存器指令 mrs  msr ldr str ldm stm mcr  arm和协处理器之间数据交换 mrc cond
keil软件中C语言嵌套汇编
原文地址:keil软件中C语言嵌套汇编作者:SUN_403 一、讲解背景 在单片机学习的过程中,掌握一点汇编语言是非常有必有的,作为低级语言汇编语言在单片机开发中有它不可取代的作用,比如每条指令可以精确的确定延时时间,便于理解非常适合硬件工程师学习。但是要提高单片机技能,必须掌握C 语言编程,因为C 语言有强大的模块化管理思想。我想在很多人学习的过程中即学了汇编语言,又学习了C 语言,那么一个问
GNU C内嵌汇编学习笔记
前文所述,只是针对汇编格式的整理,本文将使用coreboot项目代码对其进行实例化。以方便、清晰了解到如何在C语言里使用内嵌汇编的方法。同样地,网络上也有众多文章涉及到这方面,所以本文更多是归纳总结。形成自己的学习笔记。
C++ 内嵌汇编 实现 加法操作
程序体现了怎么在C++的代码中进行汇编程序开发 #include #include void asmFunc(int* pAddress); void main() { int *pAddress=(int*)malloc(sizeof(int)); asmFunc(pAddress); printf("%d\n",*pAddress); } // 0x0F + 0X10 =
arm gcc 内嵌汇编
在linux 的源码中,出现不少的内嵌汇编,比如内核同步机制等等,有必要搞清楚它的原理,就要大概清除它的原理。内嵌汇编的格式asm volatile ( “asm code” :output : input :changed ) 一、 1。asm code 在”asm code”里面,可以写多条汇编代码,但是每一条汇编代码都以\n 或者是 \nt进行换行
MDK 下STM32内嵌汇编
__asm("指令");这种语法是内联汇编的语法。 而RMDK下,内联汇编仅支持ARM汇编语言,不支持Thumb或者Thumb-2汇编语言;但内嵌汇编器支持Thumb和Thumb-2。 “target architecture/processor”及STM32的cor