先看源码:
1 | // compiled with : gcc -o memcpy memcpy.c -m32 -lm |
程序比较了两个内存复制算法slow_memcpy
和fast_memcpy
的效率。用户按程序要求输入十次要分配的内存大小,并使用malloc函数来分配内存,如果所有步骤执行完毕,程序会在最后输出 flag。
fast_memcpy
函数中用于内存复制的两个指令movdqa
和movntps
,他们的操作数如果是内存地址的话,那么这个地址必须是16字节对齐的,否则会产生一般保护性异常导致程序退出。malloc
在分配内存时实际上分多分配4字节用于存储堆块信息,所以如果申请a字节的内存,实际上分配的是a+4字节。另外32位系统上该函数分配的内存是以8字节对齐。
每次分配大小限制在两个相邻的2次幂之间。
知道这些其实就很好筛选了
1 | #coding:utf-8 |
movntps指令
从XMM寄存器复制4个单精度浮点数至128位内存单元
The source operand is an XMM register, YMM register or ZMM register, which is assumed to contain packed single-precision, floating-pointing. The destination operand is a 128-bit, 256-bit or 512-bit memory location. The memory operand must be aligned on a 16-byte (128-bit version), 32-byte (VEX.256 encoded version) or 64-byte (EVEX.512 encoded version) boundary otherwise a general-protection exception (#GP) will be generated.
对应源操作数为XMM,则目的内存为128比特内存位置。内存必须16字节对齐,否则会生成一个 general-protection 异常。
movdqa指令
移动对齐的双四字128bit
XMM寄存器
SSE指令集提供了xmm寄存器,xmm一组8个128位寄存器,分别名为xmm0~xmm7
对应指令
movaps 把4个对准的单精度值传送到xmm寄存器或者内存
movups 把4个不对准的单精度值传送到xmm寄存器或者内存
movss 把1个单精度值传送到内存或者寄存器的低位双字
movlps 把2个单精度值传送到内存或者寄存器的低四字
movhps 把2个单精度值传送到内存或者寄存器的高四字
movlhps 把2个单精度值从低四字传送到高四字
movhlps 把2个单精度值从高四字传送到低四字
movapd 把2个对准的双精度值传送到xmm寄存器或者内存
movupd 把2个不对准的双精度值传送到xmm寄存器或者内存
movdqa 把2个对准的四字节整数传送到xmm寄存器或者内存
movdqu 把2个不对准的四字节整数传送到xmm寄存器或者内存
movsd 把1个双精度值传送到内存或者寄存器的低四字
movhpd 把1个双精度值传送到内存或者寄存器的高四字
movlpd 把1个双精度值传送到内存或者寄存器的低四字
segfault原因
程序尝试去读或者写一个非法内存地址
A segfault occurs when a reference to a variable falls outside the segment where that variable resides, or when a write is attempted to a location that is in a read-only segment.