Tag: 汇编

未对齐的内存访问

我正在玩C中的内存地址,并想知道这个名为未对齐内存访问的主题。 我目前使用的是带有Linux内核的x86英特尔,但是本着主题和操作系统不可知论的精神来讨论这个主题 – 尽管以下是Linux和HW特定的: 当我从/向未对齐的地址读取/写入简单类型时,我没有错。 日志或任何内容中没有消息。 我也尝试过: perf top -e alignment-faults # And with PID perf top -p NNN -e alignment-faults 但没有命中。 通过以下方式启用对齐检查 __asm__(“pushf\norl $0x40000,(%esp)\npopf”); 给出“通缉”结果: Bus error (core dumped) (但仍然没有消息) 我的问题是硬件+操作系统如何处理这个问题以及什么是最佳的。 我的想法和问题到处都是,但我会试着说出一些具体的观点: CPU是否默认启用了对齐检查,但是内核检测到支持off并指示它不检查 ? 作为内核,至少我在其他硬件上经历过这种情况,由于某些驱动程序试图访问未对齐的内存,可以获得oops:内核是否运行在对齐检查 -mode? 或者它可能只是代码的某些部分呢? 由于未对齐内存的访问需要更多资源; 在软件的测试阶段,启用对齐检查是一个好主意,例如在assembly线之上? 这会使它更便携吗? 我对此有很多疑问,但现在就把它留在这里。

从icc获取Intel-syntax asm输出,而不是默认的AT&T语法?

我遇到了问题。 我一直在使用gcc来编译/汇编我的C代码一段时间,并习惯于阅读英特尔汇编语法。 我在生成程序集文件时使用了-masm=intel标志。 然而最近,由于公司迁移,他们获得了英特尔的icc,声称它更好。 所以现在我需要使用icc,但奇怪的是它有默认的汇编语法为AT&T。 我试图改变它,但它没有用,所以我联系了英特尔支持,他们也不知道,每个人都给了我一个矛盾的答案。 有没有办法集成gcc和icc,以便我使用icc编译“优势”,同时用gcc编译intel的语法? 我正在使用ubuntu并获得了icc版本12.x.

x86架构中的指令解码

我正在为我的实验室开发一个操作系统项目,我将使用指令指针和指令操作码。 现在我需要知道的是它是什么类型的指令。 为此,我正在从指令指针指向的地址读取数据。 该数据的第一个字节给出了指令类型。 例如,如果第一个字节是0xC6 ,则它是MOVB指令。 现在有些情况下指令指针的第一个字节是0x0F 。 根据文档0x0F ,这意味着它是一个双字节指令。 我的问题是这种类型的指令。 我不知道如何找出双字节指令的指令类型。 在那之后,我的第二个优先级是两个找出指令的操作数。 我不知道从代码中做到这一点。 任何示例代码将不胜感激 第三,需要找出指令的大小。 由于x86是可变长度,我想知道每个指令的大小。 起初我打算使用查找表,我将维护指令名称及其大小。 但后来我发现相同的指令可以有不同的长度。 例如,当我在.o文件上使用对象转储时,我发现了两条指令C6 00 62 ,用于MOVB $0x62,(%EAX)和C6 85 2C FF FF FF 00 ,用于MOVB $0x0,-0xD4(%EBP) 。 看这里两个指令类型相同( C6 )但是长度不同。 所以我需要回答这些问题。 如果有人能给我一些解决方案,我们将非常感激。

如何编写从汇编代码调用的C函数

我需要编写一个C函数,它将从linux内核中的汇编代码中调用。 应该考虑哪些特殊问题? 我有一些想法,但任何人都可以提供更多细节: (1)召集会议 确保组件中的呼叫者和c中的被叫者握手良好。 但是我应该使用哪种调用约定? 如何声明c函数并在汇编代码中声明它? (2)保护寄存器 在调用之前,应将某些寄存器保存在程序集中。 我粗略记得他们是eax,ecx和edx。 但我不需要保存它们,除非我需要在调用C函数之前引用旧值,对吧? 还有什么其他问题?

是否可以从OCaml调用C函数,而不包含类型?

我正试图在OCaml中编写一个(极其微小,简单 – 我不知道我在做什么,让我们真实!)编译器。 我真的想避免在项目中检查任何 ISO-C代码(尽管很好地了解C;这里的目标是专门学习和使用OCaml。)根据这一点,我需要为编译编写一个“运行时” OCaml中的语言,与主项目分开编译,然后将其与编译器本身的输出相关联。 不幸的是,它看起来像任何外部函数 – 甚至那些不接触任何OCaml数据结构/ OCaml堆的函数 – 都应该使用OCaml的C宏构建: CAMLprim value scheme_entry(value unit) { int i; i = 42; return Val_int(i); } 如果我自己发出assembly说明,这可能不是一个选择。 (至少,直到我学到更多东西!) 是否有任何方法(包括hacky – 这是一个个人学习项目)来调用OCaml中的以下非常简单的函数? _scheme_entry: movl $42 %eax ret 作为参考,我正在通过Ghuloum的IACC: http ://ell.io/tt$ocameel

模拟jg指令(datalab的isGreater)

我正在做CSAPP的datalab,即isGreaterfunction。 这是描述 isGreater – if x > y then return 1, else return 0 Example: isGreater(4,5) = 0, isGreater(5,4) = 1 Legal ops: ! ~ & ^ | + <> Max ops: 24 Rating: 3 x和y都是int类型。 所以我考虑模拟jg指令来实现它。这是我的代码 int isGreater(int x, int y) { int yComplement = ~y + 1; int minusResult = x + yComplement; […]

GCC内联汇编’Nd’约束

我正在用C开发一个小玩具内核。我需要从键盘获取用户输入。 到目前为止,我已使用以下代码实现了inb : static inline uint8_t inb(uint16_t port) { uint8_t ret; asm volatile(“inb %1, %0” : “=a”(ret) : “Nd”(port)); return ret; } 我知道”=a”约束意味着al/ax/eax将被复制到ret作为输出,但我仍然对”Nd”约束感到困惑。 任何人都能提供一些有关为什么需要这种约束的见解? 或者为什么我不能只使用像”r”或”b”这样的通用寄存器约束? 任何帮助,将不胜感激。

如何获取我的代码的结束地址

我正在为一个课程项目从头开始编写一个实时操作系统。 我想在将代码下载到芯片后知道代码的结束地址,因为我打算使用空闲内存来获取堆栈空间,我需要确保不会覆盖现有代码。 我听说GCC提供的__end变量是代码的结尾,但我不知道__end的含义是什么以及如何在我的代码中使用它。 任何人都可以解释一下或提供一些材料的链接,因为我不能google __end? 非常感谢。

使用内存屏障强制按顺序执行

试着继续我的想法,使用软件和硬件内存障碍我可以禁用编译器优化编译的代码中的特定函数的无序优化,因此我可以使用像Peterson这样的算法实现软件信号量或者Deker不需要无序执行,我测试了以下代码,其中包含SW barrier asm volatile(“”: : :”memory”) __sync_synchronize asm volatile(“”: : :”memory”)和gcc builtin HW barrier __sync_synchronize : #include int main(int argc, char ** argv) { int x=0; asm volatile(“”: : :”memory”); __sync_synchronize(); x=1; asm volatile(“”: : :”memory”); __sync_synchronize(); x=2; asm volatile(“”: : :”memory”); __sync_synchronize(); x=3; printf(“%d”,x); return 0; } 但编译输出文件是: main: .LFB24: .cfi_startproc subq $8, %rsp […]

char *的大小是否与int *的大小相同?

我知道:char *是一个指向char的指针。 和int *是指向int的指针。 所以,我想确认以下两件事: 所以现在假设我在32位机器上,那么这意味着内存地址是32位宽。 这意味着char *和int *的大小都是32位(4字节),对吧? char * *的大小也与int *的大小相同? 假设我有:int * ptr; 因此现在做*((char * *)ptr)= 0x154与*((int *)ptr)= 0x514相同,对吧? (0x514只是任意随机存储器地址) 平台:我在x86上。 PS:我知道类型转换不是建议的代码方式。 但我正在做内核编码,因此我必须做类型转换!