内联汇编 - 没有参数的pushf

时间:2015-02-28 17:40:20

标签: assembly x86 gdb inline-assembly kvm

我试图理解以下代码:

n = 0;
asm volatile(
    "pushf\n\t"
    "pop %%rax\n\t"
    "or $(1<<8),%%rax\n\t"
    "push %%rax\n\t"
    "lea (%%rip),%0\n\t"
    "popf\n\t"
    "and $~(1<<8),%%rax\n\t"
    "push %%rax\n\t"
    "popf\n\t"
    : "=g" (start) : : "rax");

我试图通过以下模式弄明白:

asm ( assembler template,code. 
    : output operands                   (optional)
    : input operands                    (optional)
    : list of clobbered registers       (optional)
    );

&#34; PUSHF \ n \吨&#34;将值推送到堆栈?这个命令推送到堆栈的值是多少? 同样适用于&#34; popf \ n \ t&#34;

基本上我想写一个模拟数据写/读断点的测试。

我附上了kvm-unit-test repository的代码:

int main(int ac, char **av)
{
    unsigned long start;

    setup_idt();
    handle_exception(DB_VECTOR, handle_db);
    handle_exception(BP_VECTOR, handle_bp);

sw_bp:
    asm volatile("int3");
    report("#BP", bp_addr[0] == (unsigned long)&&sw_bp + 1);

    set_dr0(&&hw_bp);
    set_dr7(0x00000402);
hw_bp:
    asm volatile("nop");
    report("hw breakpoint",
           n == 1 &&
           bp_addr[0] == ((unsigned long)&&hw_bp) && dr6[0] == 0xffff0ff1);

    n = 0;
    asm volatile(
        "pushf\n\t"
        "pop %%rax\n\t"
        "or $(1<<8),%%rax\n\t"
        "push %%rax\n\t"
        "lea (%%rip),%0\n\t"
        "popf\n\t"
        "and $~(1<<8),%%rax\n\t"
        "push %%rax\n\t"
        "popf\n\t"
        : "=g" (start) : : "rax");
    report("single step",
           n == 3 &&
           bp_addr[0] == start+1+6 && dr6[0] == 0xffff4ff0 &&
           bp_addr[1] == start+1+6+1 && dr6[1] == 0xffff4ff0 &&
           bp_addr[2] == start+1+6+1+1 && dr6[2] == 0xffff4ff0);

    n = 0;
    set_dr1((void *)&value);
    set_dr7(0x00d0040a);

    asm volatile(
        "mov $42,%%rax\n\t"
        "mov %%rax,%0\n\t"
        : "=m" (value) : : "rax");
hw_wp:
    report("hw watchpoint",
           n == 1 &&
           bp_addr[0] == ((unsigned long)&&hw_wp) && dr6[0] == 0xffff4ff2);

    return report_summary();
}

1 个答案:

答案 0 :(得分:0)

模式

asm ( assembler template,code. 
    : output operands                   (optional)
    : input operands                    (optional)
    : list of clobbered registers       (optional)
    );

用于gcc inline assembly

首先分解示例中的部分,然后执行实际的汇编代码:

"pushf\n\t"
"pop %%rax\n\t"
"or $(1<<8),%%rax\n\t"
"push %%rax\n\t"
"lea (%%rip),%0\n\t"
"popf\n\t"
"and $~(1<<8),%%rax\n\t"
"push %%rax\n\t"
"popf\n\t"

要准确了解每条指令的作用,您应该查看x86说明手册。但是,有一些特定于扩展的asm语法的要点。

"lea (%%rip),%0\n\t"行中,%0表示将替换为output operands部分中列出的第一个约束值。在此示例中为"=g" (start)

g表示 "Any register, memory or immediate integer operand is allowed, except for registers that are not general registers."(start)表示代码中的变量start将使用此值。

在您的示例中,输入操作数部分为空,因此asm代码不会从早期的C代码中获取任何输入值。

最后在被破坏的寄存器列表部分中,代码表明rax被破坏了。这意味着编译器应该假定asm代码可以更改rax的值,因此编译器需要在内联asm代码执行之前/之后保存/恢复rax中的值,如果{ {1}}是一个实时注册。