GCC内嵌汇编相关语法

汇编语言中的'#'_转码的硅工的博客-CSDN博客_汇编#

" # " ,代表寻址方式为立即寻址

MOV A, #21H 

意思是:将值21H传递给寄存器A暂存

MOV A,21H,寻址方式变为直接寻址, 21H就不是值了,而是一个地址,意思是将 21H这个地址里面的内容给到寄存器A暂存。

80x86汇编:

操作系统原理:详解汇编语言基础知识(图文代码) - 知乎

内联汇编:gnu汇编语言使用内联汇编 扩展asm_我是小x的博客-CSDN博客_asm 扩展

  • assembly code:即汇编代码部分,可以在该部分编写所需的内联汇编代码,和基本asm格式相比,扩展格式里的汇编代码除了在百分号的使用上有所不同外(下面会介绍),其他的汇编指令的书写格式都是差不多的
  • Output operands: A list of registers and memory locations that will contain the output values
    from the inline assembly code
    输出操作数:用于指定内联汇编代码的执行结果需要输出到哪个寄存器,以及需要输出到哪个C变量里
  • Input operands: A list of registers and memory locations that contain input values for the inline
    assembly code
    输入操作数:可以将C变量的值输入到指定的寄存器,这样就可以在内联汇编代码里,通过这些寄存器来使用到C变量的值了,这里的C变量既可以是全局变量,也可以是局部变量
  • Changed registers: A list of any additional registers that are changed by the inline code
    被修改的寄存器:用于指明在内联汇编代码里修改了哪些寄存器,编译器会根据实际情况,对这些修改的寄存器进行一些push、pop之类的操作,这样,汇编代码修改的寄存器就不会影响到外面C代码的正常执行
    并非每个部分都必须进行设置,假设你不需要第二个输出操作数,那么输出操作数部分就可以留空,不过需要注意的是,即便输出操作数留空,开头的两个冒号也必须保留,如:asm (“assembly code” : : input operands : changed registers);的格式,另外,如果不需要设置被修改的寄存器部分,那么最后一个冒号可以省略,如:asm (“assembly code” : output locations : input operands);的格式。
     

C中的内联汇编为什么需要上述的内容。

assemble code ,编译器主要来解析这部分,执行到这里的时候,PC会指向这里的assemble code 往后执行。

output, 我们需要把执行结果写回个C语言,那就必须用一个变量存起来,同理input也是,C语言要把数据准确的传递给汇编的某个寄存器。

changed registers , 这是为了防止内联汇编修改了某些寄存器的值,导致的影响,在执行之前先把这部分的值压入栈中,然后执行完之后再弹出栈。

约束符:

Constraint
约束符 Description
描述
a Use the %eax, %ax, or %al registers.
使用%eax, %ax或%al寄存器
b Use the %ebx, %bx, or %bl registers.
使用%ebx, %bx或%bl寄存器
c Use the %ecx, %cx, or %cl registers.
使用%ecx, %cx或%cl寄存器
d Use the %edx, %dx, or $dl registers.
使用%edx, %dx或%dl寄存器
S Use the %esi or %si registers.
使用%esi或%si寄存器
D Use the %edi or %di registers.
使用%edi或%di寄存器
r Use any available general-purpose register.
使用任何可用的通用寄存器
q Use either the %eax, %ebx, %ecx, or %edx register.
使用%eax, %ebx, %ecx或%edx寄存器
A Use the %eax and the %edx registers
for a 64-bit value.
使用%eax和%edx寄存器来存储一个64位的值
f Use a floating-point register.
使用一个浮点寄存器
t Use the first (top) floating-point register.
使用第一个ST0浮点寄存器
u Use the second floating-point register.
使用第二个ST1浮点寄存器
m Use the variable’s memory location.
使用变量的内存位置
o Use an offset memory location.
使用一个带有偏移值的内存位置,例如:使用4(%edi)来表示EDI加偏移值4的内存地址,多用于数组元素的访问
V Use only a direct memory location.
使用不带偏移值的内存位置
i Use an immediate integer value.
表示操作数是一个立即数(常量整数值)
n Use an immediate integer value with a known value.
表示操作数是一个已知数值的立即数,在许多系统里,当操作数小于1个word(字)宽时,就不能使用i,而应使用n来表示立即数
g Use any register or memory location available.
可以使用任一通用寄存器或内存位置,或者操作数是一个立即数
除了上面的这些约束外,对于操作数还包含一个constraint modifier(约束修饰符),用于表示操作数是否可读写之类的,可用的约束修饰符如下表所示:
 

Constraint modifier
约束修饰符 Description
描述

The operand can be both read from
and written to.
说明操作数是可读写的,例如"+r",指的是在内联汇编指令开始前,必须先将变量的值赋值给对应的寄存器(也就是读的过程),在执行完汇编指令后,再将寄存器的值写入变量(即写的过程)
= The operand can only be written to.
说明操作数是只写的,例如"=r",就是说,只需将结果写入变量,至于内联汇编指令执行前,对应寄存器里的值则可以是任意值,无需在执行前读取变量的值。
% The operand can be switched with the
next operand if necessary.
在必要时,操作数可以和下一个操作数进行交换,下面会举例说明
& use ‘&’ for each output operand that may
not overlap an input
&修饰符是用来强制编译器为输入操作数与输出操作数分配不同的寄存器
可以参考
例解gcc内嵌汇编(inline assembly)中&修饰符(modifier)的作用_bokee的博客-CSDN博客
该链接里的文章
上面的约束修饰符里"+"、"="、"&“这三个只能用于修饰输出操作数,不能用于修饰输入操作数,而”%“则刚好相反,只能用于修饰输入操作数。

猜你喜欢

转载自blog.csdn.net/qq_38307618/article/details/124613516