GCC ASM
GCC 内联汇编
语法
asm (
assembler template // 汇编代码
:output operands // 输出数 optional
:input operands // 输入数 optional
:list of clobbered registers // 被污染的寄存器 optional
)
下面是一个例子, 来自 pintos
// this pass the ip address of the eip to the eax, and jump to page_fault_handler
// then the err handler change eax, and jump back to this code, therefore return -1
/* Reads a byte at user virtual address UADDR.
UADDR must be below PHYS_BASE.
Returns the byte value if successful,
-1 if a segfault occurred. */
static int get_user (const uint8_t *uaddr) {
int result;
asm ("movl $1f, %0; movzbl %1, %0; 1:"
: "=&a" (result) : "m" (*uaddr));
return result;
}
/* Writes BYTE to user address UDST.
UDST must be below PHYS_BASE.
Returns true if successful,
false if a segfault occurred. */
static bool put_user (uint8_t *udst, uint8_t byte) {
int error_code;
asm ("movl $1f, %0; movb %b2, %1; 1:"
: "=&a" (error_code), "=m" (*udst) : "q" (byte));
return error_code != -1;
}
-
“$1f”为向前引用”1:”处的地址
- 第一项为汇编代码, 多条语句用 ; 分割
- 第二项为输出操作数, 以”=?”形式, (constraints 约束)
- 第三项为输入操作数, 以”?”形式
-
第四项标出汇编代码中被修改的寄存器, 或者用”memory”表示修改了内存, 需要更新某些寄存器值
- 操作数(包括输入输出), 从 0 开始, 依次排序, 以(%+数字)显示在汇编代码中
- 操作数”?”可以包括一下标识符
- a,b,c,d,S,D -> eax,ebx,ecx,edx,esi,edi
- r 上述任意寄存器
- m 内存
- i 立即数
- g 寄存器,内存,立即数均可
- 与特殊架构相关的一些格式, 以下为i386独有
- constraints “q” Any register accessible as rl. In 32-bit mode, a, b, c, and d; in 64-bit mode, any integer register.
- “%b2” -> “%al”, “%h0” -> “%ah”
-
如果你不想你写的汇编语句被优化, 那就在 asm 关键字后加上 volatile 关键字
- 约束修饰字符
- (“=”: write-only)
- (“+”: read-write)
- (“&”: eary-clobber 操作数, 在指令使用输入操作数之前被写入了值, 所以这个操作数就不能位于输入操作数的寄存器, 以免被覆盖
代码示例
int a = 10, b = 2, c = 10;
asm (
"movl %1, %%eax;"
"addl %2, %%eax;"
"movl %%eax, %0"
: "=r"(c)
: "r"(a), "r"(b)
: "%eax"
);
int five_times_x = 4; int x = 10;
asm ("leal (%0,%0,4), %0"
: "=r" (five_times_x)
: "0" (x) // 即是输入也是输出
);