C /汇编:如何改变CPU寄存器中的一位? [英] C / Assembly: how to change a single bit in a CPU register?

查看:241
本文介绍了C /汇编:如何改变CPU寄存器中的一位?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是软件故障注入领域的新研究员,目前我的最终目标是编写一段简单的代码,可以在CPU寄存器中更改一位。我正在考虑用C语言来完成它(代码中包含一些程序集调用)。考虑到这一点,我在Stack Overflow中发现了这个伟大的线程&有关如何访问32位CPU寄存器内容的简单示例:是否可以访问C中的32位寄存器?这样,我就可以编写这个简单的代码:

  #include< stdio.h> 

int main()
{
寄存器int值;

寄存器int ecx asm(ecx);
printf(ecx的内容:%d \ n,ecx);

asm(movl %% ecx,%0;:= r(value):); // Assembly:将ecx值存储到变量值
printf(value of contents:%d \ n,value);

返回0;
}

这似乎是对这个主题的一个很好的介绍,并且在那里提供了答案给了我很好的见解和信息来源(我已经阅读了GCC文档),但现在我需要进一步移动,我。即,我需要了解如何更改CPU寄存器中单个位的内容(或者至少要启动,更简单:我如何更改CPU寄存器值?)。如果有人可以给我一个提示或者告诉我最寻找它的最合适的来源,我会非常感激。



所有最好的&预先感谢,
João



PS:不知道这是否有帮助,但我正在研究CentOS 6.5 32位系统(尽管CPU是64位的,更确切地说是Intel奔腾双CPU E2180 @ 2.00 GHz)。此外,我之前曾与大会进行过接触,但它与10年前一样,在一个单一的课程单元上进行了几个月,所以目前我正在努力回顾关于该语言的小知识。

解决方案

修改程序集中寄存器位子集的常用方法是对常量使用逻辑运算。
$ b

AND%eax,0xFFFFFFFE 取消设置第0位。

OR%eax,0x01 设置第0位。

XOR%eax,0x01

(谢谢@harold的更正)。



这就是说并且如注释中所述,您可能不希望在程序中直接使用内联汇编来模拟硬件故障。它将与引入修改的地方紧密相连,并且在源代码和二进制级别混合引入错误不是我会推荐的方法(您的编译器可以并且将重新组织和优化代码,所以很可能它最终会导致意外的行为,请参阅Balakrishnan's和Reps的你所看到的并不是你所执行的)。

你可以使用二进制仪器平台,例如英特尔的PIN或一个现有的错误注入框架。

编辑:
由于OP要求在注释中使用内联asm的hello world这里是:

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

int main()
{
寄存器int eax asm(%eax);
asm(xorl%eax,%eax);
asm(xorl $ 1,%eax);
printf(eax的内容:%d \ n,eax);
返回0;
}

另存为test.c然后编译:

  gcc test.c -o test 

或更好:

  gcc test.c -S 

这将创建test.s,一个包含程序的汇编输出的文件。这个文件可以让你理解很多关于你的代码的东西,而且在编译时你应该编译汇编之前使用内联汇编(至少在你有什么不明白的地方)。



然后,您可以使用以下代码从程序集中组合二进制文件:

  gcc test.s -o test 

在x86上需要注意以下几点:




  • 在实际指令中,我将目标寄存器放在指令的最后。

  • 立即前缀 $,注册为%
  • 操作扩展寄存器(32位寄存器,前缀为e)的指令后缀为l

I'm a new researcher on the software fault injection field, and currently my ultimate goal is to write a simple piece of code that is able to change a single bit in a CPU register. I was thinking of doing it in C (with some Assembly calls included amongst the code). With that in mind, I found here in Stack Overflow this great thread & simple example on how to access the contents of a 32 bit CPU register: Is it possible to access 32-bit registers in C? This way, I was able to write this simple code:

#include <stdio.h>

int main()
{
    register int value;

    register int ecx asm("ecx");
    printf("Contents of ecx: %d\n", ecx);

    asm("movl %%ecx, %0;" : "=r" (value) : ); //Assembly: this stores the ecx value into the variable value
    printf("Contents of value: %d\n", value);

    return 0;
}

This seems to be a great introduction to this theme, and the answers provided there gave me great insight and information sources (I'm already reading the GCC documentation), but now I need to move further, i. e., I need to understand how can I change the contents of a single bit in a CPU register (or at least, to start, something simpler: how can I change a CPU register value?). If someone can give me a hint or tell me the most approriate source to look for it, I'd be deeply grateful.

All the best & thanks in advance, João

P.S.: Don't know if this helps, but I'm working on a CentOS 6.5 32 bit system (although the CPU is a 64 bit one, more precisely a Intel Pentium Dual CPU E2180 @ 2.00 GHz). Also, I have had previous contact with Assembly, but it was like 10 years ago, on a single course unit for a couple of months, so currently I'm trying to review the little knowledge I have on the language.

解决方案

The usual way of modifying a subset of the bits of a register in assembly is to use logical operations with constants.

AND %eax, 0xFFFFFFFE unsets the 0th bit.

OR %eax, 0x01 sets the 0th bit.

XOR %eax, 0x01 flips the 0th bit.

(thanks @harold for the corrections).

That being said, and as noted in the comments, you probably don't want to directly use inline assembly in the program to simulate hardware faults. It will be tightly bound to the place where you introduced the modification, and mixing fault introduction at the source and at the binary level is not an approach I would recommend (your compiler can and will reorganize and optimize code, so it is likely that it will ultimately lead to unexpected behavior. See . Balakrishnan's and Reps' What You See Is Not What You eXecute).

you could use a binary instrumentation platform such as Intel's PIN or an existing fault injection framework.

EDIT: Since OP asked for a "hello world" example of inline asm in comments, here it is:

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

int main()
{
    register int eax asm("%eax");
    asm("xorl %eax, %eax");
    asm("xorl $1, %eax");
    printf("Content of eax: %d\n", eax);
    return 0;
}

Save as test.c then compile with:

gcc test.c -o test

or better:

gcc test.c -S

which will create test.s, a file containing the assembly output of your program. This file will let you understand many things about your code, and you should produce the assembly before compiling when using inline asm (at least when there is something you don't understand).

You can then assemble the binary from the assembly with:

gcc test.s -o test

Here are a few things to note on x86:

  • In actual instructions, I put the destination register at the end of the instruction.
  • Immediate are prefixed with "$", registers with a "%"
  • The instructions that manipulate extended registers (32 bits registers, prefixed with "e") are suffixed with "l"

这篇关于C /汇编:如何改变CPU寄存器中的一位?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆