C语言内嵌汇编程序(linux与VS2019)

GCC内嵌汇编

基本行内汇编

基本格式:

asm("statements");// statements为汇编语句
__asm__ __volatile__("hlt");// 不要优化代码,保持原样指令

如果有多行汇编,则每一行后都要加上“\n\t”,例如:

asm( "pushl %eax\n\t"
"movl $0,%eax\n\t"
"popl %eax"); 

或者可以写多行:

asm("movl %eax,%ebx");
asm("xorl %ebx,%edx");
asm("movl $0,_booga); 

扩展的行内汇编

  • 在扩展的行内汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入寄存器,以及如何将计算结果写回C变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可, GCC会自动插入代码完成必要的操作。
  • 使用内嵌汇编,要先编写汇编指令模板,然后将C语言表达式与指令的操作数相关联,并告诉GCC对这些操作有哪些限制条件。例如:
__asm__ __violate__  ("movl %1,%0" : "=r" (result) : "r"(input)); 
// “movl %1,%0”是指令模板;“%0”和“%1”代表指令的操作数,称为占位符,“=r”代表它之后是输入变量且需用到寄存器,指令模板后面用小括号括起来的是C语言表达式 ,其中input是输入变量,该指令会完成把input的值复制到result中的操作

内嵌汇编语法

基本格式:

   // __asm__(
   // 	汇编语句模板: 
   // 	输出部分: 
   // 	输入部分: 
   //	寄存器修改部分--提醒编译器这个寄存器的值将要改变);
    asm ( "statements" : output_regs : input_regs : registers-modified) 

扩展行内汇编共分四个部分:汇编语句模板,输出部分,输入部分,破坏描述部分,各部分使用“:”格开,汇编语句模板必不可少,其他三部分可选,如果使用了后面的部分,而前面部分为空,也需要用“:”格开,相应部分内容为空。例如:

int main(void)
{
    
    
    int dest;
    int value=1;
    asm(
    "movl  %1, %0"
    : "=a"(dest)
    : "c" (value)
    : "%ebx");
    printf("%d\n", dest);
    return 0;
} 
  • 限定字符
    限定字符便是内嵌汇编中放在引用的C变量之前的字符,它们的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系,例如是将变量放在寄存器中还是放在内存中等,常用的如下:
限定字符 描述
a、b、 c、 d、 s、 D 具体的一个寄存器
q、r、A 混合的寄存器
m、o、V、p 内存
g、X 寄存器或内存
I、J、N、i、n 立即数
=、+ 操作数类型
  • 汇编语句模板
    汇编语句模板由汇编语句序列组成,语句之间使用“;”、“\n”或“\n\t”分开。
    例如:
asm( "pushl %eax\n\t"
"movl $0,%eax\n\t"
"popl %eax"); 

指令中的操作数可以使用占位符引用C语言变量,操作数占位符最多10个,名称如下:%0,%1…,%9。指令中使用占位符表示的操作数,总被视为long型(4,个字节)。
但对其施加的操作根据指令可以是字或者字节,当把操作数当作字或者字节使用时,默认为低字或者低字节。对字节操作可以显式的指明是低字节还是次字节。方法是在%和序号之间插入一个字母,“b”代表低字节,“h”代表高字节,例如:%h1。

  • 输出部分
    输出部分描述输出操作数,不同的操作数描述符之间用逗号格开,每个操作数描述符由限定字符串和C语言变量组成。每个输出操作数的限定字符串**必须包含“=”**表示它是一个输出操作数。例如:
__asm__	 __volatile__ ("pushfl ; popl %0 ; cli":"=g" (x) )
//在这里“x”便是最终存放输出结果的C程序变量,而“=g”则是限定字符串,限定字符串表示了对它之后的变量的限制条件
  • 输入部分
    输入部分描述输入操作数,不同的操作数描述符之间使用逗号格开,每个操作数描述符同样也由限定字符串和C语言表达式或者C语言变量组成。例如:
 __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt)); 

Visual C++使用内联汇编

基本汇编块

基本格式:

__asm{
    
    statements}//statements为汇编语句
// 例子
__asm
{
    
    
MOV AL, 2
MOV DX, 0XD007
OUT AL, DX
}

也可以分多行写,需要在每一句前面加__asm,例如:

__asm MOV AL, 2
__asm MOV DX, 0xD007
__asm OUT AL, DX

扩展写法(使用C语言变量)

亲自运行一个内联汇编程序

1.符号,包括标号、变量和函数名;

2.常量,包括符号常量和枚举型(enum)成员;

3.宏定义和预处理指示符;

4.注释,包括"“和”//";

5.类型名,包括所有MASM中合法的类型

6.typedef名称, 像PTR、TYPE、特定的结构成员或枚举成员这样的通用操作符。
  例如:

	int dest;
	int value = 666;
	__asm {
    
    
		MOV eax, value;
		MOV dest, eax;
	};
	printf("%d\n", dest);
	return 0;

Linux Ubuntu

程序:

int main(void)
{
    
    
    int dest;
    int value=1;
    asm(
    "movl  %1, %0"
    : "=a"(dest)
    : "c" (value)
    : "%ebx");
    printf("%d\n", dest);
    return 0;
} 

运行结果:
在这里插入图片描述

Visual Studio 2019

程序:

#include<stdio.h>

int main(void)
{
    
    	
	int dest;
	int value = 666;
	__asm {
    
    
		MOV eax, value;
		MOV dest, eax;
	};
	printf("%d\n", dest);
	return 0;
}

运行截图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39021670/article/details/109068802