https://blog.csdn.net/darennet/article/details/41128881
通常嵌入到 C 代码中的汇编语句很难做到与其它部分没有任何关系,因此更多时候需要用到完整的内联汇编格式:
__asm__("asm statements" : outputs : inputs : registers-modified);
下面是一个内联汇编的简单例子:
例4.内联汇编
/* inline.c */
int main()
{
int x = 10, y = 0;
printf("init:x=%d, y=%d\n", x, y);
__asm__ __volatile__("movl %1, %%eax;\n\r"
"movl %%eax, %0;"
:"=r"(y) /* 输出参数列表 */
:"r"(x) /* 输入 */
:"%eax"); /* 不受影响的寄存器 */
printf("now: x=%d, y=%d\n", x, y);
}
/*
上面的程序完成将变量x的值赋予变量y
*/
有几点需要说明:
-
变量
y
是输出操作数,通过%0
来引用,而变量x
是输入操作数,通过%1
来引用。 -
输入操作数和输出操作数都使用r进行约束,表示将变量x和变量y存储在寄存器中。输入约束和输出约束的不同点在于输出约束多一个约束修饰符'='。
-
在内联汇编语句中使用寄存器eax时,寄存器名前应该加两个'%',即%%eax。内联汇编中使用
%0
、%1
等来标识变量,任何只带一个'%'的标识符都看成是操作数,而不是寄存器。 -
内联汇编语句的最后一个部分告诉GCC它将改变寄存器eax中的值,GCC在处理时不应使用该寄存器来存储任何其它的值。
-
由于变量y被指定成输出操作数,当内联汇编语句执行完毕后,它所保存的值将被更新。
在内联汇编中用到的操作数从输出部的第一个约束开始编号,序号从0
开始,每个约束记数一次,指令部要引用这些操作数时,只需在序号前加上'%'作为前缀
64位 AT&T汇编的寄存器
作者:Lin__Chuan
链接:https://www.jianshu.com/p/0480e431f1d7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 有16个常用的64位寄存器
- %rax, %rbx, %rcx , %rdx, %rsi, %rdi, %rbp, %rsp (和 8086汇编类似 )
- %r8, %r9, %r10, %r11, %r12, %r13, %r14, %r15
- 寄存器的具体用途
- %rax 作为函数返回值使用.
- %rsp 指向栈顶.
- %rdi, %rsi, %rdx, %rcx, %r8, %r9, %r10等寄存器用于存放函数参数.
64位, 32位, 16位, 8位 寄存器的显示.
二、32位通用寄存器
节选自:肖文鹏 2003 年 7 月 03 日发布的《Linux 汇编语言开发指南》
网址:http://www.ibm.com/developerworks/cn/linux/l-assembly/
顾名思义,通用寄存器是那些你可以根据自己的意愿使用的寄存器,但有些也有特殊作用,IA32处理器包括8个通用寄存器,分为3组
- 数据寄存器
- EAX 累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据。
- EBX 基址寄存器,常用于地址索引
- ECX 计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器.
- EDX 数据寄存器,常用于数据传递。
- 变址寄存器
- ESI 源地址指针
- EDI 目的地址指针
- 指针寄存器
- EBP为基址指针(Base Pointer)寄存器,存储当前栈帧的底部地址。
- ESP为堆栈指针(Stack Pointer)寄存器,一直记录栈顶位置,不可直接访问,push时ESP减小,pop时增大。
网友评论