Tag: cpu registers

如何在C / C ++中检测机器字大小?

是否有一种或多或少可靠的方法(不一定完美)来检测我正在编译的目标架构的机器字大小 ? 机器字大小是指整数累加器寄存器的大小(例如x86上的EAX,x86_64上的RAX等, 不是流扩展,段或浮点寄存器)。 该标准似乎没有提供“机器字”数据类型。 因此,我不是在寻找100%可移植的方式,只适用于大多数常见情况(Intel x86 Pentium +,ARM,MIPS,PPC – 即基于寄存器的现代商品处理器)。 size_t和uintptr_t听起来像是好的候选者(并且在实践中匹配我测试的所有寄存器大小)但当然是其他东西,因此不能保证总是这样做,如Is size_t中已经描述的那样。 上下文 假设我在一块连续数据上实现哈希循环。 结果哈希依赖于编译器是可以的,只有速度很重要。 示例: http : //rextester.com/VSANH87912 在Windows上进行测试表明,在64位模式下以64位模式进行散列的速度更快,在32位模式下以32位进行散列: 64-bit mode int64: 55 ms int32: 111 ms 32-bit mode int64: 252 ms int32: 158 ms

如何在C中使用FP

我正在努力学习并更好地理解FP(BP),根据我的教科书“FP(BP):指向当前活动function的堆栈帧”。 我已经知道堆栈帧链接列表以0结尾。因此,为了打印出堆栈帧链接列表,我编写了这个函数: int a = 1; int b = 2; int c = 3; asm(“movl %ebp, FP”); //Sets FP int *i = FP; while(i != 0) { printf(“Value: %d \n”, i); //Not working printf(“Hex Address: %#X \n”, i); i = *i; } 所以我认为十六行地址是有效的。 它打印3个hex地址。 我可能错了,但我要做的是打印“active function”中所有3个变量的值以及它们的hex地址。 我的价值线不起作用。 也许我不明白函数堆栈是如何工作的? 我尝试打印我喜欢我,*我,我,尝试了所有不同的东西,不起作用。 有什么帮助澄清?

修复关于C / C ++和注册访问的知识

不可否认,我是C ++的新手。 不幸的是,我见过的大多数代码都使用asm调用或定义了一个extern函数,它的主体位于汇编文件中。 这就是为什么我很想找到下面的代码。 我已经研究了3天的代码库 。 从语法上讲,我理解下面代码的每一行; 除了那个重要的因为我不知道它是如何工作的! types.h定义了uintptr和uintptr (我见过它们) 当C和C ++代码混合时需要ifdef __cplusplus。 特别是因为extern C是C ++特定的。 如果gcc具有-fno-exceptions参数,则可以省略 volatile用于防止编译器进行任何优化,因为地址必须是完美的,因为它是从寄存器写入/读取的。 总而言之,我仍然不知道这段代码实际上是如何从寄存器写入或读取的。 #include #ifdef __cplusplus extern “C” { #endif static inline u32 read32 (uintptr nAddress) { return *(u32 volatile *) nAddress; } static inline void write32 (uintptr nAddress, u32 nValue) { *(u32 volatile *) nAddress = nValue; } […]

IA32注册地址

我有几个互相关联的问题让我失望。 我正在进行一项任务,我必须在gdb查看汇编代码,以找到使C程序正常工作的正确输入。 为了测试这个,我输入一个由一些数字组成的测试字符串,并逐步读取/读取程序集以预测其行为并找出解决方案。 这是主要问题:在某一点上,我的整个输入字符串存储在%eax寄存器中。 我打电话的时候: x/a $eax 它返回一个hex,我假设它是%eax的地址。 此时,hex的最后一个字节会根据输入而变化。 程序在输入字符串上调用strtol()后不久,从字符串中删除第一个数字,并将缩短的字符串放回%eax 。 事情变得令人困惑:似乎无论原始输入有多长或附加输入有多长,当我在$eax上调用x/a时,返回的hex值的最后一个字节似乎总是等于32。是一个问题,因为在使用%eax地址的最后一个字节之后不久有一个cmp测试,而数字32会导致程序故意崩溃。 我误解了x/a的使用,事实上,我返回的hex根本不是一个地址吗? 输入的大小是否会影响注册表的地址? 任何其他有用的提示可以帮助我在这种情况下? 非常感谢

如何使用Python写入硬件中的寄存器?

我有一个C函数,通过打开设备描述符(nf10)可以完美地读/写硬件寄存器。 我正在尝试使用Python做同样的事情。 我能够读取寄存器,但我无法写入寄存器。 为什么我不能写? 有没有更好的方法来对硬件中的寄存器进行读/写操作? 相关的Python代码: #! /usr/bin/env python import os from fcntl import * from struct import * SIOCDEVPRIVATE = 35312 NF10_IOCTL_CMD_READ_STAT = SIOCDEVPRIVATE + 0 NF10_IOCTL_CMD_WRITE_REG = SIOCDEVPRIVATE + 1 NF10_IOCTL_CMD_READ_REG = SIOCDEVPRIVATE + 2 def rdaxi(addr): f = open(“/dev/nf10”, “r+”) arg = pack(“q”, int(addr, 16)) value = ioctl(f, NF10_IOCTL_CMD_READ_REG, arg) value = […]

gcc / g ++可以告诉我何时忽略了我的注册?

使用gcc / g ++编译C / C ++代码时,如果它忽略了我的寄存器,它可以告诉我吗? 例如,在此代码中 int main() { register int j; int k; for(k = 0; k < 1000; k++) for(j = 0; j < 32000; j++) ; return 0; } j将用作寄存器,但在此代码中 int main() { register int j; int k; for(k = 0; k < 1000; k++) for(j = 0; j < […]

C /汇编:如何更改CPU寄存器中的单个位?

我是软件故障注入领域的新研究员,目前我的最终目标是编写一段能够改变CPU寄存器中单个位的代码。 我在考虑用C语言(在代码中包含一些程序集调用)。 考虑到这一点,我在Stack Overflow中找到了这个很棒的线程和关于如何访问32位CPU寄存器内容的简单示例: 是否可以在C中访问32位寄存器? 这样,我就能编写这个简单的代码: #include 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; } 这似乎是对这个主题的一个很好的介绍,那里提供的答案给了我很好的见解和信息来源(我已经阅读了GCC文档),但现在我需要进一步,即我需要了解怎么能我更改了CPU寄存器中单个位的内容(或者至少,要启动,更简单一些:如何更改CPU寄存器值?)。 如果有人能给我一个提示或告诉我最合适的来源,我会非常感激。 最好的,并提前感谢,João PS:不知道这是否有帮助,但我正在使用CentOS 6.5 32位系统(虽然CPU是64位,更准确地说是Intel Pentium双CPU […]

处理ARM芯片的保留寄存器位

我正在使用ARM Cortex M3的寄存器。 在文档中,一些位可能是“保留的”。 在寄存器上写入时,我不清楚如何处理这些保留位。 这些保留位是否可写? 我不小心不接触它们吗? 如果我触摸它们会发生什么不好的事吗?

gcc参数寄存器溢出x86-64

我正在尝试使用x86-64程序集。 编译了这个虚函数: long myfunc(long a, long b, long c, long d, long e, long f, long g, long h) { long xx = a * b * c * d * e * f * g * h; long yy = a + b + c + d + e + f + g + […]

将指令的目标地址保持在寄存器中,直到指令退出为止

我想在XeonE5 Sandy Bridge上使用精确的基于事件的采样(PEBS)来记录特定事件的所有地址(例如缓存未命中)。 但是, Core TM i7处理器和Intel®XeonTM5500处理器性能分析指南 (第24页)包含以下警告: 由于PEBS机制在指令完成时捕获寄存器的值,因此无法重建以下类型的加载指令(Intel asm约定)的解除引用的地址。 MOV RAX, [RAX+const] 这种指令主要与指针追逐有关 mystruc = mystruc->next; 这是捕获存储器指令地址的这种方法的重大缺点。 根据objdump,我在程序中有许多该表单的加载指令。 有什么办法可以避免吗? 由于这是一个特定于英特尔的问题,解决方案不必以任何方式移植,它只需要工作。 我的代码是用C语言编写的,我理想地寻找编译器级解决方案(gcc或icc),但欢迎任何建议。 一些例子: mov 0x18(%rdi),%rdi mov (%rcx,%rax,8),%rax 在这两种情况下,在指令退出之后(因此当我查看寄存器值以确定我加载到/来自的位置时)地址的值(在这些示例中分别为%rdi + 18和%rcx + 8 * %rax )被mov的结果覆盖。