我需要通过GCC获取寄存器中的值。
类似的东西:
EAX=00000002 EBX=00000001 ECX=00000005 EDX=BFFC94C0 ESI=8184C544 EDI=00000000 EBP=0063FF78 ESP=0063FE3C CF=0 SF=0 ZF=0 OF=0
获取32位寄存器很简单,但我不确定获取标志的最简单方法是什么。
在本书的示例中:http://kipirvine.com/asm/
他们通过获取整个EFLAGS寄存器并转移相关位来实现。我还想过用Jcc和CMOVcc做的。
关于如何做的任何其他建议?一些要验证的测试用例也很有用。
答案 0 :(得分:4)
不需要使用汇编程序来获取寄存器。
你可以使用setjmp。这会将所有寄存器写入jmp_buf类型的结构中。除了jmp_buf本身对于每个架构都不同之外,它甚至是一种跨平台的工作。
但是,调用setjmp(并调用汇编代码)会改变一些寄存器,所以你不能真正信任它们。
有一种方法可以获得真正的快照,但这有点困难且高度依赖操作系统:
为非法非法操作码扩展安装异常处理程序。处理程序可以是实际中断,信号处理程序或OS异常处理程序(C ++的try / except块不起作用)。
在您的代码中发出非法操作码。
这里的技巧是,非法操作码没有寄存器副作用。异常处理程序可以从堆栈或异常信息结构中复制寄存器。
同样的技巧可能适用于断点中断强制溢出,陷阱等。通常有一种方法可以从一段代码中引发中断。
关于EFLAGS:您可以通过堆栈操作获取它们:
PUSHFD
POP EAX
, eax now contains the EFLAG data
答案 1 :(得分:1)
答案 2 :(得分:1)
对64位计算机进行了测试。如果您有32位计算机,请删除64位设备,然后更改flag64 - > flag32(并使用pushfd
而不是pushfq
)。在实践中,我发现我只需要检查来自标志寄存器的CY(进位)和OV(溢出)(我通常使用jc
,jnc
,jo
和{ {1}})。
jno
答案 3 :(得分:0)
我认为使用Jcc会更长,而不是使用内联汇编。
以下是我目前使用的CMOVcc:
void dump_regs() { int eax = 0; int ebx = 0; int ecx = 0; int edx = 0; int esi = 0; int edi = 0; int ebp = 0; int esp = 0; int cf = 0; int sf = 0; int zf = 0; int of = 0; int set = 1; // -52(%ebp) asm( "movl %eax, -4(%ebp)\n\t" "movl %ebx, -8(%ebp)\n\t" "movl %ecx, -12(%ebp)\n\t" "movl %edx, -16(%ebp)\n\t" "movl %esi, -20(%ebp)\n\t" "movl %edi, -24(%ebp)\n\t" "movl %ebp, -28(%ebp)\n\t" "movl %esp, -32(%ebp)\n\t" "movl $0, %eax\n\t" "cmovb -52(%ebp),%eax\n\t" // mov if CF = 1 "movl %eax, -36(%ebp) \n\t" // cf "movl $0, %eax\n\t" "cmovs -52(%ebp),%eax\n\t" // mov if SF = 1 "movl %eax, -40(%ebp)\n\t" // sf "movl $0, %eax\n\t" "cmove -52(%ebp),%eax\n\t" // mov if ZF = 1 "movl %eax, -44(%ebp)\n\t" // zf "movl $0, %eax\n\t" "cmovo -52(%ebp),%eax\n\t" // mov if OF = 1 "movl %eax, -48(%ebp)\n\t" // of "movl -4(%ebp), %eax\n\t" // restore EAX ); printf("EAX = %#08x\tEBX = %#08x\tECX = %#08x\tEDX = %#08x\n",eax,ebx,ecx,edx); printf("ESI = %#08x\tEDI = %#08x\tEBP = %#08x\tESP = %#08x\n",esi,edi,ebp,esp); printf("CF = %d\tSF = %d\tZF = %d\tOF = %d\n",cf,sf,zf,of); }
我还没有解决的一个重要问题是副作用,我希望能够在不打扰状态的情况下调用它,欢迎任何提示。
答案 4 :(得分:0)
在我的头脑中,如果我错了,请纠正我,但你可以分配一些内存,分配地址,然后用asm括号简单地写入寄存器内容...... 或者你可以把它推入堆栈并以某种方式手动读取它... 我想这需要一些好的asm代码,它可能不是做这样的事情的理想方式,但它会起作用。