我是靠谱客的博主 失眠路灯,最近开发中收集的这篇文章主要介绍linux使用反汇编解决程序崩溃,linux下如何在内核空间实现memcpy的汇编代码?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

void *memcpy(void *pdst,

const void *psrc,

size_t pn)

{

/* Ok.  Now we want the parameters put in special registers.

Make sure the compiler is able to make something useful of this.

As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).

If gcc was allright, it really would need no temporaries, and no

stack space to save stuff on. */

register void *return_dst __asm__ ("r10") = pdst;

register char *dst __asm__ ("r13") = pdst;

register const char *src __asm__ ("r11") = psrc;

register int n __asm__ ("r12") = pn;

/* When src is aligned but not dst, this makes a few extra needless

cycles.  I believe it would take as many to check that the

re-alignment was unnecessary.  */

if (((unsigned long) dst & 3) != 0

/* Don't align if we wouldn't copy more than a few bytes; so we

don't have to check further for overflows.  */

&& n >= 3)

{

if ((unsigned long) dst & 1)

{

n--;

*(char*)dst = *(char*)src;

src++;

dst++;

}

if ((unsigned long) dst & 2)

{

n -= 2;

*(short*)dst = *(short*)src;

src += 2;

dst += 2;

}

}

/* Decide which copying method to use. */

if (n >= 44*2)                /* Break even between movem and

move16 is at 38.7*2, but modulo 44. */

{

/* For large copies we use 'movem' */

/* It is not optimal to tell the compiler about clobbering any

registers; that will move the saving/restoring of those registers

to the function prologue/epilogue, and make non-movem sizes

suboptimal.

This method is not foolproof; it assumes that the "asm reg"

declarations at the beginning of the function really are used

here (beware: they may be moved to temporary registers).

This way, we do not have to save/move the registers around into

temporaries; we can safely use them straight away.

If you want to check that the allocation was right; then

check the equalities in the first comment.  It should say

"r13=r13, r11=r11, r12=r12" */

__asm__ volatile ("

;; Check that the following is true (same register names on

;; both sides of equal sign, as in r8=r8):

;; %0=r13, %1=r11, %2=r12

;;

;; Save the registers we'll use in the movem process

;; on the stack.

subq 11*4,$sp

movem$r10,[$sp]

;; Now we've got this:

;; r11 - src

;; r13 - dst

;; r12 - n

;; Update n for the first loop

subq    44,$r12

0:

movem[$r11+],$r10

subq   44,$r12

bge     0b

movem$r10,[$r13+]

addq   44,$r12  ;; compensate for last loop underflowing n

;; Restore registers from stack

movem [$sp+],$r10"

/* Outputs */ : "=r" (dst), "=r" (src), "=r" (n)

/* Inputs */ : "0" (dst), "1" (src), "2" (n));

}

/* Either we directly starts copying, using dword copying

in a loop, or we copy as much as possible with 'movem'

and then the last block (= 16 )

{

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

n -= 16;

}

/* A switch() is definitely the fastest although it takes a LOT of code.

* Particularly if you inline code this.

*/

switch (n)

{

case 0:

break;

case 1:

*(char*)dst = *(char*)src;

break;

case 2:

*(short*)dst = *(short*)src;

break;

case 3:

*((short*)dst)++ = *((short*)src)++;

*(char*)dst = *(char*)src;

break;

case 4:

*((long*)dst)++ = *((long*)src)++;

break;

case 5:

*((long*)dst)++ = *((long*)src)++;

*(char*)dst = *(char*)src;

break;

case 6:

*((long*)dst)++ = *((long*)src)++;

*(short*)dst = *(short*)src;

break;

case 7:

*((long*)dst)++ = *((long*)src)++;

*((short*)dst)++ = *((short*)src)++;

*(char*)dst = *(char*)src;

break;

case 8:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

break;

case 9:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*(char*)dst = *(char*)src;

break;

case 10:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*(short*)dst = *(short*)src;

break;

case 11:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((short*)dst)++ = *((short*)src)++;

*(char*)dst = *(char*)src;

break;

case 12:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

break;

case 13:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*(char*)dst = *(char*)src;

break;

case 14:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*(short*)dst = *(short*)src;

break;

case 15:

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((long*)dst)++ = *((long*)src)++;

*((short*)dst)++ = *((short*)src)++;

*(char*)dst = *(char*)src;

break;

}

return return_dst; /* destination pointer. */

} /* memcpy() */

最后

以上就是失眠路灯为你收集整理的linux使用反汇编解决程序崩溃,linux下如何在内核空间实现memcpy的汇编代码?的全部内容,希望文章能够帮你解决linux使用反汇编解决程序崩溃,linux下如何在内核空间实现memcpy的汇编代码?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部