Tag: assembly

GCC不在函数调用中保存/恢复保留寄存器

我在GCC有一个场景给我带来了问题。 我得到的行为不是我期望的行为。 总结一下这种情况,我提出了一些x86-64的新指令,这些指令是在硬件模拟器中实现的。 为了测试这些指令,我使用现有的C源代码并使用hex对新指令进行手动编码。 因为这些指令与现有的x86-64寄存器交互,所以我使用input / output / clobber列表来声明GCC的依赖关系。 发生的事情是,如果我调用一个函数,例如printf,则不会保存和恢复相关寄存器。 例如 register unsigned long r9 asm (“r9”) = 101; printf(“foo %s\n”, “bar”); asm volatile (“.byte 0x00, 0x00, 0x00, 0x00” : /* no output */ : “q” (r9) ); 101被分配给r9,并且内联汇编(在此示例中为假)依赖于r9。 这在没有printf的情况下正确运行,但是当它存在时,GCC不会保存和恢复r9,并且在调用自定义指令时会有另一个值。 我想也许GCC可能秘密地将赋值更改为变量 r9,但是当我这样做时 asm volatile (“.byte %0” : /* no output */ : “q” (r9) ); […]

热修补function

我正试图在内存中修补exe,源代码可用,但我这样做是出于学习目的。 (所以请不要评论建议我修改原始来源或使用绕道或任何其他库) 以下是我遇到问题的function。 vm_t* VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret ) { MessageBox(NULL, L”Oh snap! We hooked VM_Create!”, L”Success!”, MB_OK); return NULL; } void Hook_VM_Create(void) { DWORD dwBackup; VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup); //Patch the original VM_Create to jump to our detoured one. BYTE *jmp = (BYTE*)malloc(5); uint32_t offset = 0x00477C3E – (uint32_t)&VM_Create; […]

汇编中如何为无符号整数分配负数?

我学会了2’s Complement和未签名并签署了int。 所以我决定测试我的知识,据我所知,负数以2’s complement方式存储,因此加法和减法不会有不同的算法和电路会很简单。 现在,如果我写 int main() { int a = -1 ; unsigned int b = – 1 ; printf(“%d %u \n %d %u” , a ,a , b, b); } 输出结果为-1 4294967295 -1 4294967295 。 现在,我看了位模式和各种事情,然后我意识到2的补码中的-1是11111111 11111111 11111111 11111111 ,所以当我用%d解释它时,它给出-1 ,但是当我使用%u解释时,它将其视为正数,因此它给出了4294967295 。 我检查了程序集的代码是 .LC0: .string “%d %u \n %d %u” main: push rbp […]

在C中使用内联汇编进行位奇偶校验?

我正在尝试计算大量uint64的位奇偶校验 。 比特奇偶校验是指接受uint64的函数,如果设置的比特数是偶数则输出0,否则为1。 目前我正在使用以下function(@Troyseph,在这里找到): uint parity64(uint64 n){ n ^= n >> 1; n ^= n >> 2; n = (n & 0x1111111111111111) * 0x1111111111111111; return (n >> 60) & 1; } 相同的SO页面具有以下汇编例程(由@papadp提供): .code ; bool CheckParity(size_t Result) CheckParity PROC mov rax, 0 add rcx, 0 jnp jmp_over mov rax, 1 jmp_over: ret CheckParity ENDP END […]

在没有编译器的情况下创建C函数会生成prologue / epilogue&RET指令吗?

考虑这个function: void foo(){ //do something } 在assembly中,它看起来像这样(不准确): push something ;do stuff pop something ret 但我不想要这个生成的代码( RET , PUSH , POP ……)。 我只想要一个代码块的标签,所以我必须回复自己: void bar(){ //do something asm(“iret”) //i want to use this function as a ISR } 在汇编中,它看起来像这样: ; do something iret 没有PUSH , POP或RET 。 是否有任何预处理器指令或关键字可以让我实现这一目标? 我在Windows下使用GCC和NASM ,我正在尝试生成自己的中断服务例程(ISR)。

汇编代码fsqrt和fmul指令

我正在尝试使用汇编代码在此函数中计算1.34 * sqrt(lght),但我收到的错误如下: ‘_asm’未声明(在此函数中首次使用)每个未声明的标识符仅针对预期的’;’中出现的每个函数报告一次 在'{‘之前 我一直在研究如何解决这个问题,但找不到太多的信息。 有人可以建议一种让这个工作的方法吗? 我的代码是: double hullSpeed(double lgth) { _asm { global _start fld lght; //load lght fld st(0); //duplicate lght on Top of stack fsqrt; square root of lght fld st(0); //load square result on top of stack fld 1.34; //load 1.34 on top of stack fld st(i); duplicate 1.34 on […]

哪个运算符更快(>或> =),(<或<=)?

<更便宜(更快)而不是<= ,同样地, >比>=更便宜(更快)? 免责声明:我知道我可以测量,但这只会在我的机器上,我不确定答案是否可以是“特定于实现”或类似的东西。

将C与NASM链接

我有一个NASM文件和一个C文件。 如何从NASM文件中调用C文件中的函数? 如何从C文件中调用NASMfunction? 非常感谢DD

从汇编调用交流function需要“asmlinkage”吗?

我正在编写一个将从汇编代码调用的C函数。 (具体来说,我想在linux内核的系统调用处理路径中做一些检查工作,所以我将在entry_32.S中调度系统调用之前调用c函数) 在定义我的c函数时,我对“asmlinkage”修饰符感到困惑。 我知道asmlinkage是告诉编译器参数将通过堆栈传递。 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) 问题: (1)在定义将从汇编代码调用的函数时是否需要asmlinkage? (2)gcc中的默认调用约定是什么。 如果我在定义交流function时省略“asmlinkage”,它是否意味着_cdecl或fastcall? (3)如果默认调用约定是cdecl,为什么需要asmlinkage,考虑到cdecl等于asmlinkage修饰符? (我在这里纠正吗?) (4)为什么那些系统调用函数都用asmlinkage声明。 我们可以先将参数复制到寄存器,然后调用那些系统调用函数吗? 从我的角度来看,在x86中,当发出系统调用时,参数很容易保存在寄存器中; 那么为什么还要在堆栈中保存然后通过堆栈约定强制执行这样的传递参数呢? 最后,任何人都可以推荐一些我可以参考混合汇编/ c编程的资源/书籍吗?

是否可以在C中访问32位寄存器?

是否可以在C中访问32位寄存器? 如果是,怎么样? 如果没有,那么有没有办法在C中嵌入汇编代码? 顺便说一下,我正在使用MinGW编译器。 提前致谢!