Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何通过gcc从x86内联程序集中获取EIP_Gcc_Assembly_X86_Inline Assembly - Fatal编程技术网

如何通过gcc从x86内联程序集中获取EIP

如何通过gcc从x86内联程序集中获取EIP,gcc,assembly,x86,inline-assembly,Gcc,Assembly,X86,Inline Assembly,我想从下面的代码中获取EIP的值,但是编译没有通过 命令: gcc-o xxx x86_内联组件c-m32&./xxx 文件内容x86_inline_asm.c: #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { unsigned int eip_val; __asm__("mov %0,%%eip":"=r"(eip_val)); ret

我想从下面的代码中获取EIP的值,但是编译没有通过

命令: gcc-o xxx x86_内联组件c-m32&./xxx

文件内容x86_inline_asm.c:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{
    unsigned int eip_val;
    __asm__("mov %0,%%eip":"=r"(eip_val)); 
    return 0;
}
#包括
#包括
#包括
int main()
{
未签名的国际通行证;
__asm_uu__;(“mov%0,%%eip”:“=r”(eip_val));
返回0;
}
如何使用内联程序集获取EIP的值,并且可以在x86下成功编译。
如何修改代码并使用命令完成它?

我不知道这方面的gcc内联汇编语法,但对于masm:

        call    next0
next0:  pop     eax           ;eax = eip for this line
在Masm的情况下,$表示当前位置,并且由于调用是一条5字节指令,因此不带标签的替代语法为:

        call    $+5
        pop     eax

我不知道这方面的gcc内联汇编语法,但对于masm:

        call    next0
next0:  pop     eax           ;eax = eip for this line
在Masm的情况下,$表示当前位置,并且由于调用是一条5字节指令,因此不带标签的替代语法为:

        call    $+5
        pop     eax

这听起来不太可能有用(而只是获取整个函数的地址,如
void*tmp=main
),但这是可能的


只需获取标签地址,或使用
(当前行的地址),并让链接器担心如何将正确的立即数输入机器代码。因此,您并不是在体系结构上读取
EIP
,而是从即时消息读取它当前拥有的值

asm volatile("mov $., %0" : "=r"(address_of_mov_instruction) );
AT&T语法是
mov-src,dst
,所以如果将其组装起来,您编写的将是一个跳转

(在体系结构上,EIP=指令执行时的结束,因此可以说您应该这样做

asm volatile(
  "mov $1f, %0  \n\t"      // reference label 1 forward
  "1:"               // GAS local label
  "=r"(address_after_mov)
);
我使用的是
asm volatile
,以防此asm语句通过内联或其他方式在同一函数内重复多次。如果希望每个实例获得不同的地址,则它必须是
volatile
。否则编译器可以假定此asm语句的所有实例都产生相同的输出。通常t会好的


从架构上讲,在32位模式下,LEA没有RIP相对寻址,因此实际读取EIP的唯一好方法是call/pop。它不是通用寄存器,因此不能仅将其用作
mov
或任何其他指令的源或目标


但实际上,您根本不需要内联asm。 显示如何使用GNU C扩展,其中
&&label
获取其地址

int foo;
void *addr_inside_function() {
    foo++;

    lab1:  ;  // labels only go on statements, not declarations
    void *tmp = &&lab1;

    foo++;
    return tmp;
}
在函数之外,您无法安全地使用此地址;我返回它只是作为一个示例,让编译器在asm中放置一个标签,看看会发生什么。如果没有该标签的
goto
,它仍然可以非常积极地优化函数,但您可能会发现它作为
asm goto(…)的输入很有用
函数中的其他位置

但无论如何,它编译成这个asm

# gcc -O3 -m32
addr_inside_function:
.L2:
        addl    $2, foo
        movl    $.L2, %eax
        ret

因此,clang加载全局,计算foo+1并存储它,然后在标签计算foo+2并存储它之后(而不是加载两次)。因此,您仍然无法从任何地方有效地跳转到标签,因为它取决于
foo
eax
中的旧值,以及存储
foo+2

的期望行为,这听起来不太可能有用(而只是获取整个函数的地址,如
void*tmp=main
),但这是可能的


只需获取标签地址,或使用
(当前行的地址),并让链接器担心如何将正确的立即数输入机器代码。因此,您不是从体系结构上读取
EIP
,而是从立即数读取它当前拥有的值

asm volatile("mov $., %0" : "=r"(address_of_mov_instruction) );
AT&T语法是
mov-src,dst
,所以如果将其组装起来,您编写的将是一个跳转

(在体系结构上,EIP=指令执行时的结束,因此可以说您应该这样做

asm volatile(
  "mov $1f, %0  \n\t"      // reference label 1 forward
  "1:"               // GAS local label
  "=r"(address_after_mov)
);
我使用的是
asm volatile
,以防此asm语句通过内联或其他方式在同一函数内重复多次。如果希望每个实例获得不同的地址,则它必须是
volatile
。否则编译器可以假定此asm语句的所有实例都产生相同的输出。通常t会好的


从架构上讲,在32位模式下,LEA没有RIP相对寻址,因此实际读取EIP的唯一好方法是call/pop。它不是通用寄存器,因此不能仅将其用作
mov
或任何其他指令的源或目标


但实际上,您根本不需要内联asm。 显示如何使用GNU C扩展,其中
&&label
获取其地址

int foo;
void *addr_inside_function() {
    foo++;

    lab1:  ;  // labels only go on statements, not declarations
    void *tmp = &&lab1;

    foo++;
    return tmp;
}
在函数之外,您无法安全地使用此地址;我返回它只是作为一个示例,让编译器在asm中放置一个标签,看看会发生什么。如果没有该标签的
goto
,它仍然可以非常积极地优化函数,但您可能会发现它作为
asm goto(…)的输入很有用
函数中的其他位置

但无论如何,它编译成这个asm

# gcc -O3 -m32
addr_inside_function:
.L2:
        addl    $2, foo
        movl    $.L2, %eax
        ret

因此,clang加载全局,计算foo+1并存储它,然后在标签计算foo+2并存储它之后(而不是加载两次)。因此,您仍然无法从任何位置有效地跳转到标签,因为它取决于
eax
中有
foo
的旧值,并且取决于所需的行为是存储
foo+2

没有
mov-foo、eip
mov-eip、foo
指令。没有
mov-foo、eip
mov-eip、foo指令。仅就记录而言,
call+0
是特殊情况,不会破坏返回地址预测。因此,这很好,而且不会比
call
调用一个帮助函数更糟糕,该函数会像许多人期望的那样返回返回地址。/。仅就记录而言,
call+0
是特殊情况,不会破坏返回地址预测