内联汇编如何实现

内联汇编

行内联汇编

_asm pushad
_asm mov eax,0x12345678;

块内联汇编

_asm
{
	Pushad;
	Popad;
}

尝试用内联汇编弹出一个提示框:

MessageBoxA(0,0,0,0);
char str[] = "HelloWorld";
	_asm {
		push 0;
		push 0;
		lea eax, [str];	
		push eax;
		push 0;
		call MessageBoxA;
	}

传入函数前首先应参数入栈,最先入栈的为最后的函数形参,想要push一个字符串进去,我们不能简单的push str,我们应该把字符串的地址传入函数参数。

  • lea eax,[str] :把str的地址给到eax
  • push eax:eax入栈,保存的是字符串的地址。

在这里插入图片描述


裸函数

内容为空的函数

void func()
{

}

我们一般认为它是空的,但是它真的是空的吗?
不是的。

我们查看其反汇编

void func()
{
//保存栈底的地址
00EB1800  push        ebp  
//提升堆栈空间
00EB1801  mov         ebp,esp  
00EB1803  sub         esp,0C0h  
//保存临时变量
00EB1809  push        ebx  
00EB180A  push        esi  
00EB180B  push        edi  
//填充堆栈空间
00EB180C  mov         edi,ebp  
00EB180E  xor         ecx,ecx  
00EB1810  mov         eax,0CCCCCCCCh  
00EB1815  rep stos    dword ptr es:[edi]  
//安全检查
00EB1817  mov         ecx,offset _C300FBC1_源@cpp (0EBC0F2h)  
00EB181C  call        @__CheckForDebuggerJustMyCode@4 (0EB1316h)  

}
//恢复临时变量
00EB1821  pop         edi  
00EB1822  pop         esi  
00EB1823  pop         ebx  
//降低堆栈空间
00EB1824  add         esp,0C0h  
00EB182A  cmp         ebp,esp  
00EB182C  call        __RTC_CheckEsp (0EB123Ah)  
00EB1831  mov         esp,ebp  
//弹出一开始的栈底
00EB1833  pop         ebp  
00EB1834  ret  

我们可以在反汇编层面把一个函数分为三部分:

  • 第一部分,进入函数,提升堆栈空间,保存临时变量,并且CC填充堆栈
  • 第二部分,函数的内容,包括我们所实现的行为。
  • 第三部分,即将返回主函数,降低堆栈的空间,恢复ebp及临时变量。

任何函数都具有这些操作,所以说一个什么都没有的函数其实并不是空的。

所以,我们能否自己实现一个真正的裸函数? 即这个函数里连这些汇编指令都没有。

void _declspec(naked) func()
{

}
  • _declspec(naked):添加此表示函数为一个真正的裸函数,它里面什么都没有,只有一堆CC填充对于一个裸函数而言,就是编译器不会为这个函数生成代码,想用汇编怎么写就怎么写,那也就意味着,函数的开辟栈针,平衡堆栈,返回等都是由我们自己来实现。

我们在裸函数里自己实现一个小功能?
弹出一个提示框。

void _declspec(naked) func(char* name)
{
	_asm {
		push ebp;
		mov ebp, esp;
		sub esp, 0x20;

		push 0;
		push 0;
		mov eax, [ebp + 8];
		push eax;
		push 0;
		call MessageBoxA;

		add esp, 0x20;
		mov esp, ebp;
		pop ebp;
		ret 0x4;
	}
}

int main()
{
	char str[] = "HelloWorld";
	_asm {
		lea eax, [str];
		push eax;
		call func;
	}
	return 0;
}

我们省略了填充的过程,运行如下;
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
内联汇编是一种将汇编语句嵌入到高级语言代码中的技术。实现printf函数的内联汇编的关键在于使用汇编指令来访问和操作C语言变量。通过在C代码中使用asm关键字,可以在内联汇编块中编写汇编指令来实现printf函数。 具体实现printf函数的内联汇编可能会因编译器和平台而异,以下提供一种例子: ```c inline void inline_printf(const char* format, int value) { asm("movl %[value], %%eax\n\t" // 将value值存入eax寄存器 "pushl %[format]\n\t" // 将format参数压入栈中 "call printf\n\t" // 调用printf函数 "addl $4, %%esp" // 栈指针恢复 : : [value "r" (value), [format "r" (format) : "%eax" ); } ``` 在这个例子中,使用了movl指令将value值加载到eax寄存器中,然后使用pushl指令将format参数压入栈中,再调用printf函数,最后使用addl指令恢复栈指针。 需要注意的是,具体的实现可能因编译器和平台的不同而有所差异。所以在实际中,建议查阅相关的编译器手册或文档,以了解如何在特定环境下实现printf函数的内联汇编。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C语言进阶——内联汇编](https://blog.csdn.net/lyndon_li/article/details/118471845)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuleo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值