gcc 下内联汇编的一些简单案例讲解

具体的教程 参考转载的前一篇博文 GCC 内联汇编 https://blog.csdn.net/m0_37329910/article/details/89465064
持续更新中

案列

demo1

直接看代码

char dest_m[0x20] = {'\0'};
static inline char * strcpy_zj(char * dest,const char *src)
{
        int d0, d1, d2;
        __asm__ __volatile__(  "1:\tlodsb\n\t"
                       "stosb\n\t"
                       "testb %%al,%%al\n\t"
                       "jne 1b"
                     : "=&S" (d0), "=&D" (d1), "=&a" (d2)
                     : "0" (src),"1" (dest)
                     : "memory");
        return dest;
}
int main(){
                char *src_m = "zhangji";
                strcpy_zj(dest_m, src_m);
                return 0;
}

编译

gcc -m32 -g demo1.c -o demo1

基本知识点
先解释下内联汇编中的 修饰约束 (第三个冒号后面)
基本格式为:
asm ( 汇编程序模板
: 输出操作数 /* 可选的 /
: 输入操作数 /
可选的 /
: 修饰寄存器列表 /
可选的 */
);

当使用约束时,对于更精确的控制超过了对约束作用的需求,GCC 给我们提供了约束修饰符。最常用的约束修饰符为:

  • “=” : 意味着对于这条指令,操作数为只写的;旧值会被忽略并被输出数据所替换。
  • “&” : 意味着这个操作数为一个早期改动的操作数,其在该指令完成前通过使用输入操作数被修改了。因此,这个操作数不可以位于一个被用作输出操作数或任何内存地址部分的寄存器。如果在旧值被写入之前它仅用作输入而已,一个输入操作数可以为一个早期改动操作数。源地址存放于 esi,目标地址存放于 edi,同时开始拷贝,当我们到达 0 时,拷贝完成。约束 “&S”、"&D"、"&a" 表明寄存器 esi、edi 和 eax 早期修饰寄存器,也就是说,它们的内容在函数完成前会被改变。这里很明显可以知道为什么 “memory” 会放在修饰寄存器列表。

直接看汇编代码

Dump of assembler code for function strcpy_zj:
   0x080483ed <+0>:     push   ebp
   0x080483ee <+1>:     mov    ebp,esp
   0x080483f0 <+3>:     push   edi
   0x080483f1 <+4>:     push   esi
   0x080483f2 <+5>:     sub    esp,0x10
   0x080483f5 <+8>:     mov    edx,DWORD PTR [ebp+0xc]   !!!arg2  src
   0x080483f8 <+11>:    mov    eax,DWORD PTR [ebp+0x8]  !!!arg1 dest
   0x080483fb <+14>:    mov    ecx,edx
   0x080483fd <+16>:    mov    edx,eax
   0x080483ff <+18>:    mov    esi,ecx      !!! esi
   0x08048401 <+20>:    mov    edi,edx    !!! edi
   0x08048403 <+22>:    lods   al,BYTE PTR ds:[esi]
   0x08048404 <+23>:    stos   BYTE PTR es:[edi],al
   0x08048405 <+24>:    test   al,al
   0x08048407 <+26>:    jne    0x8048403 <strcpy_zj+22>
   0x08048409 <+28>:    mov    edx,edi   !!! edi
   0x0804840b <+30>:    mov    ecx,esi   !!! esi
   0x0804840d <+32>:    mov    DWORD PTR [ebp-0x14],ecx   !!! &d0 , esi
   0x08048410 <+35>:    mov    DWORD PTR [ebp-0x10],edx   !!!  &d1, edi
   0x08048413 <+38>:    mov    DWORD PTR [ebp-0xc],eax     !!! &d2, eax
   0x08048416 <+41>:    mov    eax,DWORD PTR [ebp+0x8]
=> 0x08048419 <+44>:    add    esp,0x10
   0x0804841c <+47>:    pop    esi
   0x0804841d <+48>:    pop    edi
   0x0804841e <+49>:    pop    ebp
   0x0804841f <+50>:    ret

代码中 d0 d1 d2 与寄存器的关系 进行了跟踪 基本明了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值