学习自唐佐林老师,仅作为个人笔记




注意 占位符的作用:
当使用如 “r” 等限制符的时候,表示编译器会自动完成寄存器的分配。那么怎么引用这些被编译器自动分配的寄存器呢? 就是通过 %N 的形式加以引用,N可以是从0 到 9,N指示了寄存器在 “输出寄存器”和“输入寄存器” 列表中的索引
#include <stdio.h>
int main()
{
int result = 0;
int input = 1;
int a = 1;
int b = 2;
/*
开始内嵌汇编,并防止编译器对嵌入的汇编指令进行优化,volatile参数可选
使用占位符 %1 %0 指定寄存器在 输入输出寄存器列表中的索引
输出寄存器(列表)关联到变量格式,r 指示编译器自动将通用寄存器关联到变量
输入寄存器(列表)关联到变量格式
*/
asm volatile (
"movl %1, %0\n"
: "=r"(result)
: "r"(input)
);
printf("result = %d\n", result);
printf("input = %d\n", input);
/*
开始内嵌汇编,并防止编译器对嵌入的汇编指令进行优化,volatile参数可选
直接使用 %%eax %%ebx %%ecx 进行交换操作
输出寄存器(列表)关联到变量格式 a 指定 eax寄存器 b 指定ebx 寄存器
输入寄存器(列表)关联到变量格式 a 指定 eax寄存器 b 指定ebx 寄存器
*/
asm volatile (
"movl %%eax, %%ecx\n"
"movl %%ebx, %%eax\n"
"movl %%ecx, %%ebx\n"
: "=a"(a), "=b"(b)
: "a"(a), "b"(b)
);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
查看部分 反汇编代码
mhr@ubuntu:~/Desktop/system/qianzhuan/9$ gcc -g 9-1.c 编译并加上调试信息
mhr@ubuntu:~/Desktop/system/qianzhuan/9$ objdump -S a.out 查看反编译的汇编代码
...
0000000000400526 <main>:
#include <stdio.h>
int main()
{
400526: 55 push %rbp
400527: 48 89 e5 mov %rsp,%rbp
40052a: 53 push %rbx
40052b: 48 83 ec 18 sub $0x18,%rsp
int result = 0;
40052f: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp)
int input = 1;
400536: c7 45 e4 01 00 00 00 movl $0x1,-0x1c(%rbp)
int a = 1;
40053d: c7 45 e8 01 00 00 00 movl $0x1,-0x18(%rbp)
int b = 2;
400544: c7 45 ec 02 00 00 00 movl $0x2,-0x14(%rbp)
开始内嵌汇编,并防止编译器对嵌入的汇编指令进行优化,volatile参数可选
使用占位符 %1 %0 指定寄存器在 输入输出寄存器列表中的索引
输出寄存器(列表)关联到变量格式,r 指示编译器自动将通用寄存器关联到变量
输入寄存器(列表)关联到变量格式
*/
asm volatile (
40054b: 8b 45 e4 mov -0x1c(%rbp),%eax //将栈上的内存0x1c位置的数据(input==1) 拷贝到 eax寄存器
40054e: 89 c0 mov %eax,%eax //可省略
400550: 89 45 e0 mov %eax,-0x20(%rbp) //将 eax寄存器的数据 拷贝到 栈上的内存0x20位置中(result )
"movl %1, %0\n"
: "=r"(result)
: "r"(input)
);
...
内嵌汇编的应用:
在不使用 printf() 的情况下打印字符串
可以通过 INT 80H 使用内核服务
INT 指令用于使用 Linux 内核服务(中断指令)
80H 是一个中断向量号,用于执行系统调用

存在可选参数 %0 %1 所以寄存器使用 %%

不存在可选参数 %0 %1 所以寄存器使用 %
#include <stdio.h>
int main()
{
char* s = "D.T.Software\n";
int l = 13;
printf("main begin\n");
/*
将立即数4 存储到 eax 寄存器,用于指定编号为4的系统调用:sys_write
将立即数1 存储到 ebx 寄存器,用于指定 系统调用sys_write 的第一个参数:输出目标
将占位符%0 拷贝到 ecx寄存器,用于指定 系统调用sys_write 的第二个参数:输出字符串地址
将占位符%1 拷贝到 edx寄存器,用于指定 系统调用sys_write 的第三个参数:输出字符串长度
执行系统调用
输出参数格式,虽然没有 但是需要占位
输入参数格式
保留寄存器,因为这里已经使用,所以这里告诉编译器 这几个寄存器不能再用于关联其他变量
*/
asm volatile(
"movl $4, %%eax\n"
"movl $1, %%ebx\n"
"movl %0, %%ecx\n"
"movl %1, %%edx\n"
"int $0x80 \n"
:
: "r"(s), "r"(l)
: "eax", "ebx", "ecx", "edx"
);
asm volatile(
"movl $1, %eax\n"
"movl $42, %ebx\n"
"int $0x80 \n"
);
printf("main end\n");
return 0;
}


2610



被折叠的 条评论
为什么被折叠?



